本帖最后由 strang 于 2018-12-12 16:08 编辑
+ |# z4 n5 N8 i% X6 l7 Y) q
4 b4 {& A6 \; P2 `# U7 g: x) X编辑原因:上传代码不全,补齐代码。 ( E! H" T4 @, M. s6 T; ~; u0 q
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员! 一、NVIC中断优先级 NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。 下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法: - static void NVIC_Configuration(void)
% M( n; y3 L: |6 l) {9 T5 c - {
; H4 u8 l, Z0 j4 L1 b - NVIC_InitTypeDef NVIC_InitStructure;
7 t, j& W0 m; e/ f- q - /* 嵌套向量中断控制器组选择 */
" @ E! e; q& @0 a+ A- B - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
) ~. v6 _( H+ v7 e7 y - /* 配置USART为中断源 */1 j8 e& n$ R- X( |
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
+ S6 t) W$ f; [# \( N - /* 抢断优先级*/
3 U& M& e) [9 \ e' ? - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;2 ?8 u% J+ M2 \. J( X5 W* v5 M
- /* 子优先级 */
+ {/ J! N! Y/ n" F$ x, {0 F0 Q/ ` - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;4 k0 J4 y' _ k# q/ r) N
- /* 使能中断 */4 D+ [/ Y; {# `) ~- m( X
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;% u" x. E Z. }( u. v* ^; I
- /* 初始化配置NVIC */
; c' k* l" a" a9 P. |; E7 G - NVIC_Init(&NVIC_InitStructure);8 q9 r/ a1 N7 H$ q" ]
- }
复制代码二、DMA---直接存储器访问 & R# }+ a6 }5 {( \
DAM有DAM1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道。 DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。 1. 串口DMA配置:(从存储器到外设) - void USARTx_DMA_Config(void)
0 W B+ C! T' L$ M( D$ n: @3 h( n* m - {
- n8 Y2 ]- V& C4 I0 D- {1 g J - DMA_InitTypeDef DMA_InitStructure;3 G- f" \( r+ f1 l3 W: X
- // 开启DMA时钟/ n8 K P9 v% H) L
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);- n" K7 Z2 c9 w; O
- // 设置DMA源地址:串口数据寄存器地址*/: y ]/ a0 q; |9 q1 ~
- DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;, H/ H' x- r% Z# N
- // 内存地址(要传输的变量的指针)
( g/ j, J3 H7 p7 M- f: F - DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
" N# d/ ]) P& I3 D4 M5 x9 d - // 方向:从内存到外设 9 B U! C0 w2 V8 C- f
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
% U. y9 |: }5 R; W6 P: P1 a% o - // 传输大小
% X7 f8 ?9 U+ F5 I - DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;0 [: K- _# M3 P4 d2 m9 ~
- // 外设地址不增
( r, h; t2 I% `, Y- t/ | - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
5 Z( z3 T _' `6 w - // 内存地址自增
" u4 r6 r! H" ? - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
# `6 B' {/ y: O3 C) [+ X& P A - // 外设数据单位
; f8 W/ B1 N% N, A - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
# y! g/ B( W% c - // 内存数据单位
+ \ }5 r4 _. S/ J8 H - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
+ s' z# \( e, N$ F4 ^ - // DMA模式,一次或者循环模式' u2 L- b2 R0 o3 ~$ X9 ^
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;3 d& U5 s* x- X
- //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
4 _0 w, E/ F% [$ T2 V4 M" D) ^ - // 优先级:中
4 B5 i" q- E! @- r1 _ - DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
1 ~* f1 J/ L! [8 S% T6 P- b. Y - // 禁止内存到内存的传输/ I& |; D! U5 A5 _6 m
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
! j( J' S; m; A( H1 j* Y - // 配置DMA通道
, ^" N. P. _; s7 w9 X' b: Q1 ]" ?8 b - DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);
) i' ` D. V/ U+ p - // 使能DMA* d6 ^; f B5 V
- DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
) A. c! y! E% Z- j# Q' w% g$ y - }
复制代码 2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC- u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址( p8 q* o& o8 H; ^+ Y- L
- u16 After_filter[M]; //用来存放平均值之后的结果
* C2 j; i$ K5 `+ s7 M - 3 Q$ ^( e9 c# @' T' {6 E5 e
- //使能ADC1和DMA1的时钟,初始化PC1-PC3端口
+ o: \/ }% X. M1 L9 p+ q+ s - static void ADC1_GPIO_Config(void)
1 S0 u& Q( q2 Z- G - {
^6 m6 D2 f$ L ?' a1 a$ D - GPIO_InitTypeDef GPIO_InitStructure;
' b: f2 U! B0 I. p z -
7 x6 A' ]1 p, K, `+ U. V: g - /* Enable DMA clock */' a O4 j' ?& w, ~
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);3 L: Q+ a6 i t& S' }
-
/ P( T l! z! [, ^. A1 T - /* Enable ADC1 and GPIOC clock */0 g$ F8 Y* Y" E7 u8 [) ~
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
& \ g( p3 i) g# I9 P# w - % f. o! ]7 A+ C8 [' J- Q
- //PC 作为模拟通道输入引脚
& a" t! X$ v* o! Q% T - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;0 g2 `5 H! }! x0 Q) H ?3 J
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
3 G% K+ P3 v( u! L7 R: t }9 ? - GPIO_Init(GPIOC, &GPIO_InitStructure); ' f0 ~# ~4 F3 f/ N
- }
4 q {$ U9 s8 D; `: \1 Y. y' l+ e - 2 s v5 Y" z* A2 \: ?! Q1 S/ l
- //配置ADC1的工作模式为DMA模式1 R9 X" ^1 Y; u
- static void ADC1_Mode_Config(void)
# h' g5 H: Z; w* U% I2 q - {
d T+ e( G" u - DMA_InitTypeDef DMA_InitStructure;- B6 J! l- y) c) y+ ^" o
- ADC_InitTypeDef ADC_InitStructure;
& U9 A# ` k7 y1 j0 c -
I% k1 Z* @, m k - /* DMA channel1 configuration */
) ^3 ~' ~( E% F0 S% h- m6 A - DMA_DeInit(DMA1_Channel1);, c7 C0 h4 e" T
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;4 L: C8 P! n, o v
3 `' W3 P( F+ X1 w2 ?/ G- //内存地址
) t- g7 l) r1 I, w - DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];
" O1 a6 P) |: W8 E - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
6 l' p$ ] j2 N2 J8 K5 H* U5 s - DMA_InitStructure.DMA_BufferSize =M*N;
9 S& n7 q3 e' W6 t- Q4 [7 C& b+ ] - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;- L7 u& `( X, ]$ l' r% H
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;! x0 g( r4 ?5 a2 f1 t" P
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;9 H# J' G% B) p ^- E$ w$ C3 e
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
9 ?( E0 P6 x3 B% X - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
9 X$ r+ x. A( O0 Z2 y% u0 q; \ - DMA_InitStructure.DMA_Priority = DMA_Priority_High;
+ c; v: V& ]' q" g- h - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
# q8 i& U! ]' ], U8 F - DMA_Init(DMA1_Channel1, &DMA_InitStructure);
) t+ A; u* q' E/ o% c& ?8 ~+ a9 ~ - , }* ], u2 A, s8 }3 N/ m
- /* Enable DMA channel1 */( p3 I! m6 |5 Q4 p. z4 w; P- y
- DMA_Cmd(DMA1_Channel1, ENABLE);; V4 K$ M* v- [$ _8 `. B
- ! s% |# d2 I& Q9 o0 r: _9 J. b0 X
- /* ADC1 configuration */ . q; v( H6 N! T! u
- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
! W' `2 ^' }) ]* e* c' t& {7 p% D - ADC_InitStructure.ADC_ScanConvMode = ENABLE;
$ B0 \9 {! E$ p9 H+ X% F: Z - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
a3 L; b. Z& o' o7 M& H; i - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
& ?. h/ A, [' R7 w% G- [" T, d( v) z - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;* @ N5 d; B: q. w
- ADC_InitStructure.ADC_NbrOfChannel = M;' V" d- s, y+ y1 R$ X0 Y z J
- ADC_Init(ADC1, &ADC_InitStructure);
7 w$ h; ?0 I7 W' Y" q' ^9 t# I -
7 |% O7 \" U1 k - /*配置ADC时钟,为PCLK2的8分频,即9Hz*/7 g8 r' B. ~9 z; L
- RCC_ADCCLKConfig(RCC_PCLK2_Div8); 7 W: V4 _5 l' Q4 n; P H+ k
- /*配置ADC1的通道11为55. 5个采样周期,序列为1 */
) v# ^+ ~* u8 E( h# n% K' J - ///ADC_SampleTime_239Cycles5 ADC_SampleTime_55Cycles5
3 p. G1 U6 j7 W/ ~ ]/ ]( l- ~0 b0 e - ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
5 i$ V# |6 C) S9 Z) o - ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
/ C& A# J/ m: G8 P/ N$ I9 l/ } - ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5); - {# f: B4 I. m* W S$ P5 [ m1 v
- ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);/ O' t9 h+ d5 [$ }+ m$ D% K4 y
- ! b# \ A# O; P% ^
- /* Enable ADC1 DMA */
7 x5 H, o2 @3 a: M - ADC_DMACmd(ADC1, ENABLE);
6 `. e. r- t2 E! Y9 k" y -
* q" L6 M: ]- T$ }, `8 l) }" _; {% O - /* Enable ADC1 */
0 j8 ~2 _$ r/ ~4 n+ q; V - ADC_Cmd(ADC1, ENABLE);
5 S: ?) j/ v& v9 l" H - ' B1 t7 U; p. k
- /*复位校准寄存器 */
) z" R) O0 @- y; S9 l1 a1 l - ADC_ResetCalibration(ADC1);
! X8 ~& D( E( c - /*等待校准寄存器复位完成*/
8 q8 D$ }& `' O6 ]8 W4 c' w - while(ADC_GetResetCalibrationStatus(ADC1));5 ?8 J% M- C- J! K" M
- . e! n, f0 D1 y7 C/ x, V7 H# ~
- /* ADC校准 */
8 m& i- _) ^# R. b$ l3 o - ADC_StartCalibration(ADC1);
/ B5 F4 [. v J - /* 等待校准完成*/: d( l. A* q& g# L3 H; j/ d* }
- while(ADC_GetCalibrationStatus(ADC1));
3 g1 a& b: L% ^ E4 E0 _$ |9 v- q; I! O -
& p) C* x7 V6 l% Q& [ - /* 软件触发ADC转换 */ / q( }+ Z' J u, z
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);8 M/ G! z: \0 z* e ~: `, M
- }9 h, c- H# C( A$ F2 [6 x4 R
- /* ADC1初始化*/ $ P7 B8 X- `% L4 q+ N* m8 |6 ~
- void ADC1_Init(void)
: g3 Q2 Y! ?+ _' P1 q1 @ - {8 ?! O/ _& V2 b, F+ o2 B& _& R
- ADC1_GPIO_Config();
* s8 M# r$ M V3 H% b! w) e - ADC1_Mode_Config();* |. I7 ]7 _! Y2 P2 R% v+ X) ]6 J
- }
复制代码- /*ADC滤波*/
0 \! X' x# X5 p+ W - u16 MultiDMAGetAdcTest(u8 ch)3 t4 a' Q3 O) M: y3 t' q
- {
9 d# p1 _3 Y: Q* c) o' W; z - u8 i;
0 T0 q2 j* U2 A2 u) C7 } z - u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;! H& f' x, ^7 B. [
- volatile u32 ADC_Data;
' O3 r; @$ L" U# }( o5 Y$ d - ' W$ i! \; w* \3 \. q# N
- ADC_Data=0;
& i" \9 F4 }) b: O U - 3 s. S% b: r- h
- AdcMax=0;) ?* V* k+ h7 [" J9 H) V: Q
- AdcMin=~0;) e- o; g1 M! R1 h0 t% I. f
- AdcSum = 0;
; E- E+ m4 }$ e1 ^% a+ O0 x. t! _! A$ F - Adc_temp = 0;
! k- w- b" Y* d; ^) J2 C
! Z' Q0 q* e# ^% W( h3 g- for(i=0;i<34;i++)- x4 l) y( y7 G
- {6 o( e- f" x2 l# F. ?7 W1 ]
- Adc_temp =AD_Value[i][ch];; n) t7 N6 m8 L+ X& W
- if(Adc_temp>AdcMax) $ s& @0 s0 i$ i0 ]/ R O( ~
- {. n! J& c9 [" `. M& H! s F |
- AdcMax=Adc_temp;
% ?) @- ?( @, y9 ~0 z6 ~) K - }
+ s, H$ p$ `0 Q2 r' w - if(Adc_temp<AdcMin)) Y9 S& v" S' F) p
- {
9 v, t* Z! B- k! g' y8 S2 O" k4 M - AdcMin=Adc_temp;. B6 b# A" t4 |* x
- }
$ V: I" g& u8 ]6 C - AdcSum+=Adc_temp;5 R( b& v5 E( ~4 R, c6 t
- }
" K4 w) D3 z" ~9 o! R2 [6 {7 x - AdcResult=(AdcSum-AdcMax-AdcMin)>>5;' O8 j% a& v2 |( a% i$ L0 S6 `' \" v
- After_filter[ch]=(u16)AdcResult;
9 a4 ]% M' E, m9 J7 ^$ ?7 K - return(After_filter[ch]);
' v: d4 Y% @; T - }
8 r4 Z9 @ k6 F - /*获取ADC1通道0的值*/7 A3 R; g( s9 d! E% Z
- uint16_t AD_Leach(void), H: \2 ^) n5 ~2 p
- {
/ y5 }& U* g/ l0 W U$ m9 } - uint16_t adcx1;
5 U& K6 J4 v/ R2 t. B - adcx1=MultiDMAGetAdcTest(ADC_Channel_0);5 R, ?, P9 p5 O8 H; h! Q/ |9 d
- return(adcx1);) |# t: J8 G% v: z- `. |
- }
1 y0 v( a9 j9 f/ P( \/ K) { - /*获取ADC1通道1的值*/
0 F7 x% o, ^) v' Y: h" y) m2 V - uint16_t AD_Leach_1(void)
7 S9 ]% J1 W: r4 _ - { f9 M- @6 O+ b7 T- w% M) e+ n
- uint16_t adcx2;
! z- f% Q" K5 V- ]7 Z - adcx2=MultiDMAGetAdcTest(ADC_Channel_1);: I: x' O3 z. {8 B. m
- return(adcx2);/ j/ Y9 e3 B; F$ g8 `2 n8 P
- }
& k4 k: ?* V3 X0 L - /*获取ADC1通道2的值*/
& z% l( ]! }9 Y3 ^& k - uint16_t AD_Leach_2(void)/ K8 a* R4 @- w) j3 D; D
- {! b8 U8 k Y) Z* B6 H- |, y
- uint16_t adcx3;
1 c; q* F* n5 j4 _8 D1 n3 H - adcx3=MultiDMAGetAdcTest(ADC_Channel_2);6 |/ ^# P" Q$ A- W) P3 L+ D1 i
- return(adcx3);- _9 t Q% ~, b9 S/ s& h$ j. i
- }* N' {/ O1 {% V! E" _0 f
- /*获取ADC1通道3的值*/& y% A3 C) Y9 a
- uint16_t AD_Leach_3(void) {7 }6 i0 J" n/ R$ C. \# o' i
- {. _% f. q7 W4 r+ |$ s( S
- uint16_t adcx4;8 n3 Q1 V+ O" o' G H
- adcx4=MultiDMAGetAdcTest(ADC_Channel_3);
: f* G% D8 j, Z& d - return(adcx4);/ g& r. B) w- @/ |* z
- }
复制代码
8 H* K9 O" H6 D% A7 {
0 S' s6 h8 g, J' e3 M2 n目前就学习到这里,后续再写!6 n! E' Y. D# c( ?, ]2 R8 G# v
$ V9 O! T' W' K2 n
$ l' T* i& F+ b& p$ a
/ g- T, f( E: n9 H! ~ |