本帖最后由 strang 于 2018-12-12 16:08 编辑 . \, a+ r# {9 u9 \5 [
! ^5 k1 N/ c5 B* _4 Z编辑原因:上传代码不全,补齐代码。 7 d8 B5 d- z% L# g d- R. |
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员! 一、NVIC中断优先级 NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。 下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法: - static void NVIC_Configuration(void)
, l& L5 I& b) Q) e' J9 c0 g: O - {
2 J+ x+ f' u% k9 \4 m - NVIC_InitTypeDef NVIC_InitStructure;% }; r: Q' }( z' J4 ~
- /* 嵌套向量中断控制器组选择 */
* w0 x- y4 u+ G6 ~ - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
1 l/ h0 }! {3 C) G( `1 [ R$ j - /* 配置USART为中断源 */0 L! v' l, s) U# I. C, \
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
: @$ H9 M2 _: ]- J% @ - /* 抢断优先级*/
' Y4 m+ X' E! ?& w5 o - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;2 G: t u% \9 |3 g! _# @# l( y
- /* 子优先级 */
! o# _1 R' ?; N0 M7 O - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
! W( ^ z, R. d& J9 @5 F - /* 使能中断 */
+ y8 r: O/ ~4 p; S. t8 K - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;- l) W1 n0 r+ }! s0 c c( a
- /* 初始化配置NVIC */. A, Y* N2 _' f
- NVIC_Init(&NVIC_InitStructure);
3 [8 h5 j0 A% p9 P/ n9 G - }
复制代码二、DMA---直接存储器访问
0 L* b. U/ ]% Q( O* Z0 d0 B- w, M! V2 rDAM有DAM1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道。 DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。 1. 串口DMA配置:(从存储器到外设) - void USARTx_DMA_Config(void)
4 f- Z7 T1 V9 |/ v/ w" p - {
% ?3 G" o" k) n7 ] - DMA_InitTypeDef DMA_InitStructure;
8 e3 S3 }$ C2 E! Q% `* | - // 开启DMA时钟( _7 S, R" P" v* C6 ]! Y; P
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);. g. e5 | A7 P/ x
- // 设置DMA源地址:串口数据寄存器地址*/
4 b0 s7 X9 B$ \5 H2 b0 {8 Y% b8 c - DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;
$ U3 F- c+ x: A0 ?, R' b - // 内存地址(要传输的变量的指针)7 z2 z, @+ W8 P
- DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
* v* a& c/ k5 H2 a a& X+ w - // 方向:从内存到外设
7 V7 N z: d5 ~+ ^ - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
) f V, K8 U7 w( b - // 传输大小 0 Q8 W2 `! X% h6 Y/ Z! x# v
- DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
! K) ~* w0 E1 x/ D - // 外设地址不增 6 Q2 V- [7 D {3 q, M
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
% o- Y& l4 a1 n4 E - // 内存地址自增
$ N% Y/ @4 j6 F/ b - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; u N1 t5 U* X, o
- // 外设数据单位
) t( E0 G1 v) S) X - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
0 I" c0 k& _; P( f4 U w* x: Y - // 内存数据单位+ r9 I* n, F4 Q1 M" k& `0 ? F7 O3 T
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
* L6 H+ Z4 K- d - // DMA模式,一次或者循环模式
7 G' j: O- s- Q Q y - DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;3 Z/ w. W7 `8 h& V$ J
- //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
8 P! K5 y8 o) A2 G0 d. q - // 优先级:中 & u: u2 U U. m* X( I8 \
- DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 1 C/ f" R4 M: e
- // 禁止内存到内存的传输; U# ~& f+ v5 L& W1 C! T
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
! \- W7 F+ O& H+ h4 Y - // 配置DMA通道 # V' i7 R G8 u2 x; g! a
- DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure); , n9 Z' J5 w' n& a
- // 使能DMA0 F& a W( \5 W! G
- DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
5 e$ r6 E$ O$ C5 O - }
复制代码 2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC- u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
0 s' I R# C# x/ V* A& @& ^1 ?, c- B - u16 After_filter[M]; //用来存放平均值之后的结果
* _0 ?3 }) i; `, Y - [/ B) o$ P7 C. R
- //使能ADC1和DMA1的时钟,初始化PC1-PC3端口8 e' R( m& n7 U, `9 | |
- static void ADC1_GPIO_Config(void)
7 y, l! X& |( y; l" K$ t( y0 u - {
" ]( q( n' ?- j; K, ]. M# b8 S7 v; P - GPIO_InitTypeDef GPIO_InitStructure;
! ?. f8 A- W" x& G6 { -
' s, [; } x) [; \4 E - /* Enable DMA clock */6 d) |- H" [% D7 Z! n/ h0 x
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);2 m) x+ N; U2 E5 a# ?. D; p9 C
- * T1 A, f1 z! M$ k
- /* Enable ADC1 and GPIOC clock */
5 v1 o* C- R! t B# y c - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
+ F: }4 B3 ~8 G# f. U# A - ! X5 x3 F+ Z+ M3 P8 J5 b, C9 H
- //PC 作为模拟通道输入引脚 6 s. ^0 t9 k- _3 n8 o& l( s
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
& n8 r- @! y; a o: Z; f - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; : h' e2 Q2 D5 y1 E
- GPIO_Init(GPIOC, &GPIO_InitStructure);
* i4 @3 ~, }) _1 z. y0 B - }" M, P" B; ]" D8 g$ n+ @
' M0 n/ g* S: D8 u' F" a- //配置ADC1的工作模式为DMA模式' n9 y, T5 H8 w4 S9 f$ W/ A( C6 S
- static void ADC1_Mode_Config(void)
* `8 m: j) I4 F - {5 o2 X1 `/ }! K" r7 i8 D
- DMA_InitTypeDef DMA_InitStructure;8 E% C& q/ c6 s+ d7 o+ n% I
- ADC_InitTypeDef ADC_InitStructure;7 o3 K. ]& @% ?3 m+ s" l" Y
-
1 Z5 e( W% |9 Z( Y& t5 f+ e - /* DMA channel1 configuration */
( n2 T7 Q- ]5 b - DMA_DeInit(DMA1_Channel1);, \7 Z/ ?) y- p+ p' M; c6 ~
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;7 ?8 U8 R6 y2 k6 p) }2 m# W7 `3 D4 t
- 6 K* d6 Y4 G0 C3 w5 \8 R
- //内存地址
, o% h" b" b. m' y' ` - DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0]; b! n, Q. w% ~* j& p0 t" d
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;: Q7 Q! ]# T9 E, `
- DMA_InitStructure.DMA_BufferSize =M*N;
9 @; [ y5 w( _& ? - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;6 k5 R6 M" C+ o9 u; p
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;6 O" f Y; V5 H8 I0 J ?
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;' [1 K0 P4 N* Y3 y, _6 \
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
8 ], N" H% L' c+ L: s - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;1 {* \8 i: v$ R# X3 {& f! t, S4 I
- DMA_InitStructure.DMA_Priority = DMA_Priority_High; N: r: O5 x- X. R1 M1 o
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;8 n, h# l' ?, F7 ]* ^
- DMA_Init(DMA1_Channel1, &DMA_InitStructure);
' f" o3 A, l. M/ W -
& z3 C, |- x" ^ a7 I - /* Enable DMA channel1 */
2 N1 B( ? y4 f6 m- `% { - DMA_Cmd(DMA1_Channel1, ENABLE);
~/ e# W4 {- U# y. j/ u -
% _9 Z1 R) }! Q( d: m6 l - /* ADC1 configuration */
0 j+ E m# ^) w; T - ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
, {4 j2 z$ e5 e. Q! _9 T/ h5 [ - ADC_InitStructure.ADC_ScanConvMode = ENABLE;
$ ~% X9 b" e5 h, O9 O - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
, |5 f# b. n& i. L0 P; X* U - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
2 k/ S# _4 H, g$ L- t- r- `. u% ] - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;' f1 k/ A. L7 R% x" R
- ADC_InitStructure.ADC_NbrOfChannel = M;. T& F4 u2 ]! |
- ADC_Init(ADC1, &ADC_InitStructure);
# b o3 H9 |* W# \ -
# w& a* |: ^! h2 ], I0 g - /*配置ADC时钟,为PCLK2的8分频,即9Hz*/- J( C1 M. @. O, U2 S4 T( ]
- RCC_ADCCLKConfig(RCC_PCLK2_Div8); # |% g. p3 F4 ]( q; ~% u6 R
- /*配置ADC1的通道11为55. 5个采样周期,序列为1 */
* y3 ^* Z+ e; K1 I - ///ADC_SampleTime_239Cycles5 ADC_SampleTime_55Cycles5: o! s% Z3 n3 `1 |( `7 c0 V1 f* M
- ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5); g8 k( l' i- V' C, P
- ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
. {0 E- U/ R7 Z* R - ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);
" k, Y4 f. U6 l# \( Y - ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);8 H' f- ]2 G3 M; F
- 7 R% b5 L; G4 E/ u
- /* Enable ADC1 DMA */9 h/ w8 M6 O% q* P( P# |
- ADC_DMACmd(ADC1, ENABLE);
* V, t& y+ n& y2 U -
# z3 f; F" d) _ - /* Enable ADC1 */
- p# ?; j$ y/ P" V- Q- Y+ S+ B* n - ADC_Cmd(ADC1, ENABLE);) `% _: D8 D" d* g7 w5 `) y+ @ M& I! y
- ' M2 c, H8 p, B' [, X% H9 Y
- /*复位校准寄存器 */ 6 J9 \, b! U* B* s7 w: j
- ADC_ResetCalibration(ADC1);+ }2 X3 F8 e# B- {6 B! g
- /*等待校准寄存器复位完成*/
+ ~. E$ y# B5 b* T3 R" V- [* v - while(ADC_GetResetCalibrationStatus(ADC1)); O# m. _2 m5 T
- & e2 h( z) |$ R; g/ c
- /* ADC校准 */
. P' T$ p" i0 [ - ADC_StartCalibration(ADC1);
1 b$ q: D6 g* @# F# ] - /* 等待校准完成*/
! ?: Z! i; \! R M1 t3 N - while(ADC_GetCalibrationStatus(ADC1));
; t+ x/ o. r- u- z - - P+ o9 U% r$ I. h `1 u+ h; [; d- S
- /* 软件触发ADC转换 */
2 P, r, o2 v A) r$ X - ADC_SoftwareStartConvCmd(ADC1, ENABLE);7 T* q7 I# V) [; F4 {* A& \
- }$ ~5 N: k+ r) ^' l
- /* ADC1初始化*/ r. F- }# `% P; q8 B0 Y1 f S+ b
- void ADC1_Init(void)5 U( G F# ]! K1 m
- {" K4 ]0 V/ l% H7 M: S* j7 @
- ADC1_GPIO_Config();
; D A4 M/ K+ d - ADC1_Mode_Config();
: o! g8 M6 ^: ~; e( s - }
复制代码- /*ADC滤波*/: X8 m: Z0 q1 h$ Q; l g
- u16 MultiDMAGetAdcTest(u8 ch); x: m; ^' Z0 b1 l( b2 f8 D9 O g
- {5 c1 R' \" ^* [- q
- u8 i;
9 q- i9 ~: r- \ - u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
; w& W0 D9 L' k+ q- d4 |4 C - volatile u32 ADC_Data;
5 e" T% j9 `6 d' o - , C R5 r3 i% M0 a. I: B
- ADC_Data=0;
% Q. d" T- W! o7 |& { - . S* D( X: S2 C0 A0 p
- AdcMax=0;6 _( K& L4 \# f, F
- AdcMin=~0;6 X9 {# B' F' {& p% l" n5 A
- AdcSum = 0;6 a2 R% p- P( p% d+ j
- Adc_temp = 0;) g( v! V3 ?, n' c% a
6 ]8 Y! \: c2 q* q9 v5 g" }- for(i=0;i<34;i++)
) [' u7 k" u' R2 r - {
! t# s' Q4 n. j - Adc_temp =AD_Value[i][ch];! p6 N9 K2 W( }3 `; |, r9 l
- if(Adc_temp>AdcMax)
+ S/ f, O4 \- Z2 ~& _$ b - {
) g2 r1 ~8 _2 G - AdcMax=Adc_temp;# y& `8 o( s6 E0 C4 X
- }
! R8 `7 R" j+ S* B9 J$ b. q" _ - if(Adc_temp<AdcMin)0 X* P4 `6 `( A
- {
( n. O/ K' x* `& I. z - AdcMin=Adc_temp;
# j2 {7 t( \: L - }
2 W0 a q" C* H( T - AdcSum+=Adc_temp;& d |1 A( e4 O! I) u" u z
- }: l% S6 R. B1 h! I1 q. M
- AdcResult=(AdcSum-AdcMax-AdcMin)>>5;* z3 D' L: n) `+ R6 E$ s
- After_filter[ch]=(u16)AdcResult;
. ]4 r8 ~% b/ D, E' y: G' A: `! `0 a - return(After_filter[ch]);
( X1 }8 [2 C- t( v - } & c/ L0 z1 K- E5 W5 n# n& x2 M8 P
- /*获取ADC1通道0的值*/6 R- z0 r8 B5 H9 W# g
- uint16_t AD_Leach(void)
5 F# Y- Q. L; e - {
5 f; m0 ^6 l/ D1 [9 q3 d - uint16_t adcx1;
4 S# V) E) C& H% X- L0 d - adcx1=MultiDMAGetAdcTest(ADC_Channel_0);
& R& c. |3 D. Q F - return(adcx1);
3 \7 a5 h- a( v7 d( i t - }
, [, |- ^$ e& h9 n - /*获取ADC1通道1的值*/
8 X, \. B& |" ]; a4 W7 r - uint16_t AD_Leach_1(void)8 E# l3 q [3 z, z$ w: ^) f- d
- {
. _! W3 j: P+ e# T6 |8 n: O - uint16_t adcx2;( s: W x" e% T* E t; W6 O* y4 x
- adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
- v: s; B& C+ E - return(adcx2);
: B5 u" K. T* k2 q! v - }
$ R$ ]/ W8 `( j" T' A% p2 Z - /*获取ADC1通道2的值*/0 P4 k& g) Q& }3 q
- uint16_t AD_Leach_2(void)7 e* M2 S- j1 [* Z$ L5 L# L
- {( i6 J% A3 }* ]+ o
- uint16_t adcx3;% \* j0 ~& j" q6 p3 E
- adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
& }6 i8 c( Z( F' d - return(adcx3);- k; F; Q2 [2 C" C3 l4 r
- }$ C, g- X; A! y9 N Q) \+ `2 R
- /*获取ADC1通道3的值*/
3 I2 z. |8 C# C) ~! s6 D; K2 \/ K - uint16_t AD_Leach_3(void)
. d6 |4 b8 M) |3 }* ]4 U - {
1 Q! X6 o' c0 ^/ M0 W+ U - uint16_t adcx4;
% A n( e+ l ]# |' e# q9 x - adcx4=MultiDMAGetAdcTest(ADC_Channel_3);5 W. R, r" N$ H6 E( _0 n- [
- return(adcx4);- U3 u$ L# y: A* U
- }
复制代码
4 |9 _+ ?( |/ f. g% n: F
& F- T2 e: R% P& @: [目前就学习到这里,后续再写!/ J3 L/ X! p0 a. B$ g
/ k$ o9 U' X1 m6 \3 w1 t
W. o, q3 s5 T, ]& w
n4 j$ h+ z& i |