本帖最后由 strang 于 2018-12-12 16:08 编辑
" y9 c0 M- t/ [, [9 ^9 V
( n% W. l! e6 i" L1 ]) w r! H" Y编辑原因:上传代码不全,补齐代码。 & \ D* N. I; D4 L
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员! 一、NVIC中断优先级 NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。 下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法: - static void NVIC_Configuration(void)$ V: f" X4 k3 h9 p- `
- {
5 X$ x: p9 \1 L3 `+ l6 u3 ~ - NVIC_InitTypeDef NVIC_InitStructure;
/ L) \3 M+ l, } - /* 嵌套向量中断控制器组选择 */" Z* A- P3 g+ u9 \- o1 X4 B
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);: k/ G5 ?8 T. R4 n1 p+ q/ k. z
- /* 配置USART为中断源 */
' q0 f7 p; U" s$ K - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
' s' J" y- o3 y/ ~* c6 ?9 M/ g. x( e& C - /* 抢断优先级*/7 |! x9 a: |5 h" v% L# A4 L0 m
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;' t8 ]! w( h/ J" h/ I/ T
- /* 子优先级 */# q# C" L7 {: j% q; q5 M
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
4 X! }! h0 o6 l. E) i3 Q5 D& n - /* 使能中断 */
. F+ }: V6 f+ l, A9 L6 ] - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;1 w7 `* _" T4 C$ D
- /* 初始化配置NVIC */
; h5 N+ i4 [$ \: U p: a - NVIC_Init(&NVIC_InitStructure);$ Z$ }8 \# |& V0 [/ R3 @
- }
复制代码二、DMA---直接存储器访问
( ]& l5 j& |- E7 V/ o5 J) g) JDAM有DAM1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道。 DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。 1. 串口DMA配置:(从存储器到外设) - void USARTx_DMA_Config(void), Q: N& Q) G( K$ Y3 M
- {
6 r% \& i5 J: r! i" M5 ?; U9 V, L - DMA_InitTypeDef DMA_InitStructure;+ w5 ^# I* b- _! _- r, L ^
- // 开启DMA时钟
# `0 ^. f% r! A+ W% _* H9 b - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
0 O I$ F# m! Z/ U7 }0 T) M - // 设置DMA源地址:串口数据寄存器地址*/+ S6 G9 d, B5 {) a6 t, G
- DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;3 O. S) D. h/ ~4 @% e8 |
- // 内存地址(要传输的变量的指针)
0 E, g" F1 |6 }5 N, r - DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;/ h, b# ~; [5 x$ [9 u" ^
- // 方向:从内存到外设
) {3 j J7 M* d! E+ L1 c7 t - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;1 \$ ]: h) Q- n
- // 传输大小 3 y0 `: |: K. \1 Y
- DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
9 `: a( v) k2 U9 Z3 ^. T - // 外设地址不增 1 }4 m4 e, f p( c7 v( J+ w
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
1 v2 I) N( }2 ]; z+ i) D, r, G/ k3 t - // 内存地址自增3 l7 l# G* n F% ]
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
% K# U* i; l+ T$ }2 N+ G - // 外设数据单位
5 v$ q0 |$ m; P4 C6 \ - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
. o7 {& }/ x: z1 Q0 W9 Y - // 内存数据单位
4 l% e8 l t+ Q1 E% S+ R! C; t - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; 4 F8 a% ^7 f" H8 I, T3 M
- // DMA模式,一次或者循环模式5 u* @2 ]; U" x# i0 \+ Y6 v
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
! D( w9 s+ Q" ]3 k6 n8 M* H: h - //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; . v$ I7 ^2 x9 {: N* \: g
- // 优先级:中 - s5 C( k# L/ p0 q
- DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
0 I% d% j4 z( a# H( G- y+ @ - // 禁止内存到内存的传输
$ M6 o# R5 h) M/ x+ [. D" x - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;# i) g2 \; z$ S; n1 ~
- // 配置DMA通道
: X$ G) p9 [ q( S3 a- @- W - DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);
4 q+ v0 ]: B; G; t - // 使能DMA t' Z' F. S( K" V# d+ C
- DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);* [4 i5 O/ ]+ t5 |$ f P K: z
- }
复制代码 2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC- u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址& `: j, O7 A6 }" B
- u16 After_filter[M]; //用来存放平均值之后的结果; n9 u+ _& [1 I# K2 [& R
; O: ~$ L! _4 l% n0 \& e- //使能ADC1和DMA1的时钟,初始化PC1-PC3端口+ q# | ]% q y( J% Z6 y
- static void ADC1_GPIO_Config(void)
/ {, U" }- [( g: f4 N - {" E( o. E$ X4 S5 q$ `7 ~: ]3 r
- GPIO_InitTypeDef GPIO_InitStructure;& n+ o: |' _, V$ L
-
* k- c+ W" G( C% M - /* Enable DMA clock */
$ \2 I4 L! e! Z/ h( R6 n - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);; v3 n! X2 O* F, M8 v3 l0 z
- 9 G2 _3 i) F! e; z1 _
- /* Enable ADC1 and GPIOC clock */) b$ `% [7 E% n5 ~
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
* m' o+ D- A& Y3 A3 { -
* {# Q7 H, b7 ?( }7 z - //PC 作为模拟通道输入引脚
1 i* @. Q, B& B0 B; V$ _" o - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
. w; |2 R$ H! M; {& G8 W: K - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
1 ?9 t: C. K! m4 f$ Q* O5 I - GPIO_Init(GPIOC, &GPIO_InitStructure);
+ V+ j0 t4 H% T5 C3 w* C# i8 \2 Q - }
' K5 D6 a! o6 `, f8 L# }' j
6 m; v$ F' q% h+ V# l, C3 B- //配置ADC1的工作模式为DMA模式& ?9 z2 W$ |9 v( T+ b: _- t
- static void ADC1_Mode_Config(void)
W% Z; x/ D/ }/ k - {
4 N8 q( d) g. C - DMA_InitTypeDef DMA_InitStructure;4 I5 O* a7 r: O' }5 y
- ADC_InitTypeDef ADC_InitStructure;
1 v- M% Y3 X( r+ _8 I -
7 k. l: {3 u# _ - /* DMA channel1 configuration */
% [' \: X5 ?% m1 _ - DMA_DeInit(DMA1_Channel1);: S! W! b; N+ }7 S+ g: Q) v
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;5 R9 O3 v7 M6 h" l! t
; b+ B) n- n$ t; L/ w- //内存地址
) D( I, Z" W& N \. L( F5 F - DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];4 ?, r/ |; l# o$ U. i
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
; |1 M% O! g% P' P* S' }! a" K - DMA_InitStructure.DMA_BufferSize =M*N;
: P2 h$ a: g0 f% `4 i" Z; N - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
$ A9 V" k7 ?% X' a$ i - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
" ?- T: X: n6 P - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
, f v, k& R- X - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;7 v1 Q& ^" m+ y2 x5 V( U
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;- W: P, L6 w6 l* o, c7 I- D
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;' ?! R' ]) N! d5 z
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
" j% I- k7 [; P" x4 J2 q i- |- d - DMA_Init(DMA1_Channel1, &DMA_InitStructure);2 n z* b+ D2 A6 c% K& @
-
: o. ]. a- g, b3 A3 }7 j - /* Enable DMA channel1 */
" y4 D$ d' E0 l, D - DMA_Cmd(DMA1_Channel1, ENABLE);3 ]$ Z5 \ v, s# z% V& O2 l1 P
- ' y' I2 q1 X9 F
- /* ADC1 configuration */
9 v$ Z6 r7 t5 e3 H7 _0 T! A9 {3 r$ r" p - ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;) {$ s/ ^4 D) O2 O
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;! P) M9 D2 V/ p- U: }
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
( i: ]6 W+ c9 Z9 M - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;4 s& I4 E( ] e
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
( [2 }4 m& V+ n* C' H$ K2 ^ - ADC_InitStructure.ADC_NbrOfChannel = M;, J+ u5 j' D$ y9 W% i
- ADC_Init(ADC1, &ADC_InitStructure);
; ~' G3 o% C3 h6 O- n3 v. a, K& m -
. h+ I- `9 g: @6 J" l - /*配置ADC时钟,为PCLK2的8分频,即9Hz*/3 i/ b* q' a6 G9 k( R# x% N2 g9 s* w
- RCC_ADCCLKConfig(RCC_PCLK2_Div8);
- H* T9 j1 O; s B* `3 E' u* d - /*配置ADC1的通道11为55. 5个采样周期,序列为1 */
9 t+ [0 U7 w$ y: ?& w/ O - ///ADC_SampleTime_239Cycles5 ADC_SampleTime_55Cycles5
' h% W9 R% @4 i: q - ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);& D3 I& F+ T" y
- ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
5 b. d/ {& c8 [' U- U - ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5); y" J2 V$ [+ b% n2 t- p
- ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);6 L; W, U; h6 x' @- Q% B
- 0 _+ s2 j6 N$ D! a- j2 A( }
- /* Enable ADC1 DMA *// J8 D3 K# r' A. [* p0 f
- ADC_DMACmd(ADC1, ENABLE);
5 X9 R8 ~2 \: u8 p6 e$ n9 S6 U - . T$ p j6 U1 j' M' r
- /* Enable ADC1 */
2 V7 L) X! v' w! x9 ` - ADC_Cmd(ADC1, ENABLE);
; N/ m# e. ]8 C ?1 J% J- w - % R9 K5 |% \$ H' k; c4 I4 e7 j
- /*复位校准寄存器 */ 4 E5 ^4 J) Z& D% d! \: }$ `1 Y+ x
- ADC_ResetCalibration(ADC1);( ^3 S7 O4 m. L' D9 O# \
- /*等待校准寄存器复位完成*/
* h2 _. E, q6 y9 O/ R3 z0 w& M% W - while(ADC_GetResetCalibrationStatus(ADC1));+ y# h( F3 a g' y/ M) [
- & R, I( p' v) k3 T! U z# y9 {
- /* ADC校准 */
% s/ }8 y8 V+ Q# @9 y - ADC_StartCalibration(ADC1);
" g: ?. O2 E" p# j2 V - /* 等待校准完成*/
+ r) `( Z( v9 k( `( | {1 b - while(ADC_GetCalibrationStatus(ADC1));" \1 ~; m8 \/ P% C
-
5 b3 d+ f( o* T% U/ t, E0 Y - /* 软件触发ADC转换 */
4 s+ e( M8 l% | - ADC_SoftwareStartConvCmd(ADC1, ENABLE);
% ?: [4 P+ \1 r# e8 [; A- G, e# a' L - }
3 V7 e3 ]5 P# j$ _ - /* ADC1初始化*/ . m+ |5 ^ S% F" n/ K
- void ADC1_Init(void)& P/ A- N& T. k- E7 c5 W
- {
' F# n9 b; u% J5 Y: e1 p! H. v- o - ADC1_GPIO_Config();, g# o+ c4 X+ O k9 q
- ADC1_Mode_Config();
1 ^# y' Q. s; h" h% ~ - }
复制代码- /*ADC滤波*/
, k+ B/ H4 ?, r) M, K f" y8 `2 [ - u16 MultiDMAGetAdcTest(u8 ch)1 U& F1 o" i7 b/ Q& I2 S
- {0 z5 W6 c5 r$ u& j/ I X
- u8 i;/ u- y9 R& P# K8 d; Z* G8 @; L: g% W
- u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
2 A/ Q6 n5 u: c# c - volatile u32 ADC_Data;
* ?2 ?: t8 U8 Y - ( h y( K: H5 O! M
- ADC_Data=0;
# d2 _& c& J4 m
/ b0 o! j8 t; Q( G9 X- AdcMax=0;" {- V% v1 x$ m' Y3 r5 o
- AdcMin=~0;4 \; D* p, Q/ H; O
- AdcSum = 0;
! \; v9 u# F; v5 x - Adc_temp = 0;
" d8 h# K% @+ |# ]: S; z
2 i7 z0 X8 W# |$ L6 Q" I- for(i=0;i<34;i++) v& ^1 `* M( P0 l- i6 @
- {
8 t+ u4 q, R) g! c - Adc_temp =AD_Value[i][ch];0 F0 K3 G9 u- l1 E& }9 f% t
- if(Adc_temp>AdcMax)
7 h$ V6 [) h4 t7 q0 y; ]3 o j - {
: o. z7 ?% U) ` - AdcMax=Adc_temp;
! w& \3 ?+ q4 i- C4 T3 ` - }
) M4 r7 F/ y* f4 x4 U - if(Adc_temp<AdcMin)
$ f/ S% [. F0 n8 u: K - {
/ ~2 m: k4 u! y" g - AdcMin=Adc_temp;3 ?8 s, _1 F9 i5 E
- }
9 f/ _* k1 D! [( E' ~& {' ? - AdcSum+=Adc_temp;) N- X$ ?; { c
- }
# z% o0 D8 y3 b. }0 [ - AdcResult=(AdcSum-AdcMax-AdcMin)>>5;
, F0 r2 {% v; X8 A4 ] - After_filter[ch]=(u16)AdcResult;
/ b* b. V1 ^ S% ]/ F$ }# D - return(After_filter[ch]);
' T" ~! }7 u& U5 }' o* @ - } & j% U0 p9 N' ^9 P M9 r
- /*获取ADC1通道0的值*/
8 o! M+ n; S" Y. ^) X( T - uint16_t AD_Leach(void)
$ V4 ~* W4 g- ?9 Y1 U - {
. S" Q" {; f+ B' s- v& s4 u7 R, `+ { - uint16_t adcx1;
& }# D( [" r" \ W - adcx1=MultiDMAGetAdcTest(ADC_Channel_0);
n. J( f/ t' ]6 D - return(adcx1);6 b( E) \, Y& U8 X! S
- }- x; C7 b b& u) p2 D2 Q) N
- /*获取ADC1通道1的值*/) |4 A1 S1 V! Y/ u/ p
- uint16_t AD_Leach_1(void); O8 o# ?. ?( m" n* k( X
- {- }2 n* h( P; ]
- uint16_t adcx2;+ K; l* ^8 _/ N7 @* _
- adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
( r0 `( S) s' M* B' |5 j% X - return(adcx2);/ _5 q4 @# _, |
- }
8 m$ c7 E% ]. t - /*获取ADC1通道2的值*/
/ I2 F( d2 r. l d - uint16_t AD_Leach_2(void)$ H1 x+ I( x$ a" C
- {
! D0 x1 y2 ] y9 Q: ]! o - uint16_t adcx3;6 g, Z+ K+ M8 l& P( E8 X- q
- adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
) @+ u# ?: v% x9 E# y - return(adcx3);
0 }! u ^. Z, b" l( m - }
# t% V9 P; ?# ^- b7 Q% {. Q - /*获取ADC1通道3的值*/: l# [' N% o8 F
- uint16_t AD_Leach_3(void)
, j5 d/ q) g1 _1 M - {/ m4 B) i% z! _& ~& L$ z4 p( A
- uint16_t adcx4;
+ x8 q$ U/ G- g/ i* N5 o - adcx4=MultiDMAGetAdcTest(ADC_Channel_3);0 f1 E1 w* }& ]! a) Z* H
- return(adcx4);0 k. l! K1 D5 ]7 g9 C
- }
复制代码 , h* h" `* w6 }
) m9 o0 n- t! N3 |) w8 Y目前就学习到这里,后续再写!7 O8 B) c0 p4 V
8 K0 [# [# P! Q/ g1 k& k1 k0 U% u9 q5 a/ v1 s m6 }
/ C. i- f" I) b1 D5 h3 ?0 D$ h |