本帖最后由 strang 于 2018-12-12 16:08 编辑 1 ^& n# `9 s; O( h8 r3 S
, l! G- \8 Y/ W9 L4 m' L编辑原因:上传代码不全,补齐代码。 3 x! C. x2 O( v0 ^
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员! 一、NVIC中断优先级 NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。 下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法: - static void NVIC_Configuration(void)) c9 s$ K Y9 F; F) }
- {
9 ]7 U( d8 H" h7 b# y8 H+ @, @ - NVIC_InitTypeDef NVIC_InitStructure;
7 L8 F8 }: S/ m2 B3 ` - /* 嵌套向量中断控制器组选择 */$ S! E Y5 \7 [5 U& u
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
, K: m" V5 Q$ B" g p @2 u - /* 配置USART为中断源 */
4 s- m3 g' D% \% d; X2 e' {2 c - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
, t3 z" K! i5 d3 U: p - /* 抢断优先级*/ M7 n- ^6 r4 x+ X
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
+ ]. }- R1 [7 ~3 O$ ~) l. w( @ - /* 子优先级 */( {7 L$ X" u5 B% ?0 l Y
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;/ q* F! b) @7 E, y3 e% }
- /* 使能中断 */
! e. l3 _5 t% h" }5 E - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
: Y+ ~ n, r: V - /* 初始化配置NVIC */
1 W4 U, e' y: d2 G% d - NVIC_Init(&NVIC_InitStructure);
9 q& s! O9 `7 R/ ]3 i! W - }
复制代码二、DMA---直接存储器访问
7 G& i# n( G: B [, X! {9 NDAM有DAM1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道。 DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。 1. 串口DMA配置:(从存储器到外设) - void USARTx_DMA_Config(void)5 |( L. C2 Q% }! G$ Q6 { l0 a
- {0 x: d9 t6 y- H3 y
- DMA_InitTypeDef DMA_InitStructure;2 X, e O% {& S
- // 开启DMA时钟
7 o* v: n. r& e - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
7 `3 n# V' c$ }: m - // 设置DMA源地址:串口数据寄存器地址*/ n2 \: t+ k* o" p9 `7 A% D/ O
- DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS; ]* _# j( r. Y" Q' n
- // 内存地址(要传输的变量的指针)
7 K4 i7 N4 G, F K - DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
% A7 L6 t2 s& Z; \ ~+ q - // 方向:从内存到外设
0 P! |- \! k' R7 f - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;$ A+ W3 H/ x* T/ J- O
- // 传输大小 0 [! Y1 s: k' Z! `8 y' L% U: ~
- DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
& j) C1 g1 f- u% x7 a - // 外设地址不增
2 U0 T- Z) {* p& J' j - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;& g& F0 s0 ~& o& K7 @4 P
- // 内存地址自增9 v2 H2 N$ a0 V" C
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
1 y8 Q q Y0 ?% O- P8 R' B - // 外设数据单位 9 u: q" E, l- N+ b. ^
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;+ E$ m4 k+ l- Z0 c7 C5 E: g
- // 内存数据单位
" y+ F9 j- w- K4 X) q/ z" S - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
0 I7 H5 r$ V$ D0 ~. o - // DMA模式,一次或者循环模式
7 d, b5 ?3 N, ]% o% \ - DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
7 A' p' F4 H6 v; @; a2 @ - //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
1 y+ ^- G0 H9 h4 @1 } - // 优先级:中 4 X& c+ J. x- c$ g
- DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; : m7 r* H! ?+ \, o
- // 禁止内存到内存的传输: G/ g# w+ N- G2 T6 M& }+ @
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
, d8 N% ~9 J/ v- A7 S8 H - // 配置DMA通道 3 y- \3 `( ^/ H* Y& B
- DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);
( h- C- Z G: _) V6 G - // 使能DMA/ Z; Y) n+ K, m+ \8 p9 o
- DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);1 K- W7 c7 f5 _. x
- }
复制代码 2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC- u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
" [ @& g# }! \% a! }8 t) T6 W - u16 After_filter[M]; //用来存放平均值之后的结果
6 L2 B: S0 W6 @9 J
* S8 Z( p* m" i& \* S6 {- //使能ADC1和DMA1的时钟,初始化PC1-PC3端口
' F% Y( M S$ w% J - static void ADC1_GPIO_Config(void)( ], s- D0 A1 L: S
- {5 u0 w1 B- f1 ^: o8 B
- GPIO_InitTypeDef GPIO_InitStructure;
& f% |! }; r ~ -
6 Z! `$ R* I* F& R7 [$ z+ J - /* Enable DMA clock */2 E, e' F0 v7 B* I+ F8 h% M% w
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
8 P% j5 ^: U3 j v* _. ?" M! B& }0 E - $ \3 F0 Z3 d7 e
- /* Enable ADC1 and GPIOC clock */
. [) g$ ^/ L7 _* v- X4 Q; n - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);+ k) Q/ H5 R2 p8 [; G4 O
-
7 V" y; z& R/ m. b! s, q3 ^ - //PC 作为模拟通道输入引脚 1 S' @% Q. }: u' u- k1 e8 M* ]5 U7 @
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
0 A7 p x' {/ K) [ - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; ) _/ r& a# U1 s; _/ ^& M7 p
- GPIO_Init(GPIOC, &GPIO_InitStructure);
2 ]5 `, c0 R, l3 V - }
+ j* m9 ?6 u/ b2 V3 a
T' u( Z! a( h, x4 N/ r- //配置ADC1的工作模式为DMA模式- A8 J {+ F8 m
- static void ADC1_Mode_Config(void)
. p$ M( i( G8 J1 G# W - {
* c9 N. G+ x3 F- ` N1 J - DMA_InitTypeDef DMA_InitStructure;7 \2 H: z% E! w
- ADC_InitTypeDef ADC_InitStructure;* N# C) \* |& w& P+ |$ B8 g
- 7 [/ Z/ n! o5 d) y4 Y
- /* DMA channel1 configuration */3 O2 G$ J$ [6 H; h
- DMA_DeInit(DMA1_Channel1);( Z2 D6 h! ]* q I# F- ~: n
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
" j! ^' M) k7 n; O: W4 U- y - 2 _' v: F( T% n. a8 W3 y1 X2 K3 z) N
- //内存地址
3 P1 ~( ^% z* H" K- s - DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];! z: s7 K0 O* C
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;& x9 }0 C5 I% o( p
- DMA_InitStructure.DMA_BufferSize =M*N;( p" P- ^) Q8 ~7 E0 O7 F: T8 m; B
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
. i( K' f6 \1 r# s1 e+ b - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/ c& K# U/ {7 M8 H W$ Z% E - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
: z W7 b8 J- m3 I4 } - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
" n8 _. U1 j/ p - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;+ s1 P6 T2 D& D" n l
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;3 v7 Q. D4 O$ X; V$ o8 O) q
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;4 ~. q- E8 i6 i' L. T
- DMA_Init(DMA1_Channel1, &DMA_InitStructure);+ _! _) ~# w6 @+ V% v9 e( S' q
-
+ f1 `, }1 n" U. V - /* Enable DMA channel1 */: O$ `, F! L5 j% w! R e g
- DMA_Cmd(DMA1_Channel1, ENABLE);
( Y: G& ]; D) U) ]+ |5 w) { -
( p7 w4 \5 T8 f& x1 ` - /* ADC1 configuration */
& _# Y# i% X- _ - ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
: E0 K7 A+ C$ { - ADC_InitStructure.ADC_ScanConvMode = ENABLE;
" s. b& `, h( |/ M& T - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
- V5 |. p% Q( n5 v* S n: b - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;1 J. S( F# t) S8 W( |
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;! u p4 e3 x0 x5 r, |" I* t- `
- ADC_InitStructure.ADC_NbrOfChannel = M;
h$ y5 }) t+ M3 M- H - ADC_Init(ADC1, &ADC_InitStructure);9 k. N* n1 |9 p- Z6 J! e' T
- . J& O( O# g! d" T8 o
- /*配置ADC时钟,为PCLK2的8分频,即9Hz*/
, }- y! X' L$ L+ ^# j6 L - RCC_ADCCLKConfig(RCC_PCLK2_Div8); 7 j$ m5 m5 e% A* x' h4 X; q$ q! d) C
- /*配置ADC1的通道11为55. 5个采样周期,序列为1 */ ) S5 O! V. q6 j
- ///ADC_SampleTime_239Cycles5 ADC_SampleTime_55Cycles5
1 |3 `: ^: O7 N - ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
; ?* G$ q: Y1 o7 r4 [8 W) S" K - ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
# H$ M7 p# L8 ^& N# a2 E( z1 { - ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);
6 Y: L4 `: R0 d! p; g - ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);
5 z- B- x/ ^5 H! G8 M) R) i% _ -
9 Y# y: Y8 F x& s: e- I* v5 }3 y - /* Enable ADC1 DMA */
0 {0 e4 k: R4 j9 B0 \ - ADC_DMACmd(ADC1, ENABLE);, l& }$ I- y- H# @# M( k: o
- B, D; E2 e1 z( f& R1 U+ p
- /* Enable ADC1 */6 U- O! J/ r9 [- ~9 G4 }
- ADC_Cmd(ADC1, ENABLE);& Y* F# V0 ?& O- O3 N" p
-
; }5 R6 A8 ^ Y3 W9 M" f; ~ - /*复位校准寄存器 */ 8 M2 H# o, r, n9 l, P+ W( D
- ADC_ResetCalibration(ADC1);( ?4 c5 H- j0 N* C
- /*等待校准寄存器复位完成*/! j3 C# G6 b: L; h' y0 e6 J- V P
- while(ADC_GetResetCalibrationStatus(ADC1));
5 B1 c; G, P# @ Q7 r - 6 I1 @+ Q( s( V/ `: @
- /* ADC校准 */0 X7 P+ z }$ C
- ADC_StartCalibration(ADC1);0 r. }5 @0 `; G
- /* 等待校准完成*/) e5 ^1 B0 b3 M3 J7 m/ d
- while(ADC_GetCalibrationStatus(ADC1));
7 B1 c2 f ^% Y Q! H4 L. w0 M -
4 ~1 H; {2 R" I e" \ - /* 软件触发ADC转换 */ ) |; [% S( B; v; g7 m
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);" ~; `$ v6 n/ t3 a1 `0 y/ n
- }
) N5 D6 U+ s& f: h% N - /* ADC1初始化*/
& d( S% @, Q4 k) R; _$ o7 t( \1 e - void ADC1_Init(void)
8 l4 Q9 a# H: V+ O3 m: q - {. i8 k. z2 K7 R7 E6 K
- ADC1_GPIO_Config();! g& l! V3 u+ Y7 i
- ADC1_Mode_Config();
( O; }! X; u+ y! ^- O1 v5 z; U - }
复制代码- /*ADC滤波*/5 B* g6 y, z. ?7 K( R
- u16 MultiDMAGetAdcTest(u8 ch)
: G/ x. `% S% l$ r+ \1 X b - {
3 d$ E9 Q V& e+ U! f - u8 i;
# U* |& S! Y* U4 L/ a" a - u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
0 Q2 Y' N, X. Q! G- Q8 [9 _ - volatile u32 ADC_Data;
& b4 w1 x/ ?6 E4 A ]
$ g- i" @! w$ a0 U( | s0 y- ADC_Data=0;
+ M' m3 E# D/ r$ ^6 N% Y - % O: F" b8 V8 |# l1 B
- AdcMax=0;, F! B& k8 H0 |! | G9 Y/ `; `
- AdcMin=~0;' G% X, K% I# W; O
- AdcSum = 0;
/ ?$ i* [/ [* B- z% C2 Q/ T - Adc_temp = 0;7 N# ~6 S: b+ ?& X
- 3 K8 G) O7 D- B& e
- for(i=0;i<34;i++)% X, {9 h# S2 L: L* N o
- {
" ~/ {' c8 u, _( |2 ^ - Adc_temp =AD_Value[i][ch];
; \: R$ O) F# z( |7 c5 G* [ h1 F - if(Adc_temp>AdcMax) ' P K$ c. o1 f* [* g- [
- {7 {$ I5 @7 S3 X
- AdcMax=Adc_temp;
$ Z' E3 Y2 r% d( K1 C+ b5 f - }
$ V* \8 n) e: f' h& O! p, A6 f - if(Adc_temp<AdcMin)# {, H( z) r u" T: C
- {, }, P: a9 t$ J8 s! P# j8 u
- AdcMin=Adc_temp;& R& J& K( s, N+ B2 J. D1 G
- }
2 V0 @/ g9 h! o: W) V5 W - AdcSum+=Adc_temp;/ j5 K% w o) l3 m+ j
- }
% v2 k8 S1 d* ~ - AdcResult=(AdcSum-AdcMax-AdcMin)>>5;
8 a; n* }+ M, q# P3 }- N3 G - After_filter[ch]=(u16)AdcResult;
! x3 r0 ?" \% }3 t+ \ - return(After_filter[ch]);' R! V i, t- G/ ^. H1 O
- } \8 ]& y( ~4 B/ E' Y5 } E
- /*获取ADC1通道0的值*/
# r ?" J0 j' l( | - uint16_t AD_Leach(void)4 K1 ^* Q F, W3 Z: F' W
- {7 M7 I: s* M) P( |* ~& `
- uint16_t adcx1;! R4 \% S% W+ M3 {, k
- adcx1=MultiDMAGetAdcTest(ADC_Channel_0);! _ Y/ R3 F- S
- return(adcx1);
! y" y9 Q# N% J6 w2 W4 z# z - }0 P ]4 Q, n! y& [9 a) l6 ]
- /*获取ADC1通道1的值*/
* X0 s( a7 Z' m" @! g( ?! u+ I" |# P - uint16_t AD_Leach_1(void)
, K! e7 C2 U0 G - {( {+ H5 S) W9 v+ P7 A- B
- uint16_t adcx2;
6 o% t# i* B; ^ - adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
7 ~" W5 `! ^, {* ^8 V - return(adcx2);
8 m9 U- I T& k O - }; I+ X% |) v8 t$ @
- /*获取ADC1通道2的值*/
! M3 ^4 j+ [/ M/ x, @. C d - uint16_t AD_Leach_2(void)8 I6 T9 N* [% @" Z8 w9 n# G
- {
5 m7 B, k% l) O8 @' `9 j; C - uint16_t adcx3;
6 @- G1 c9 n/ i* J - adcx3=MultiDMAGetAdcTest(ADC_Channel_2);3 c! F7 z7 {6 B6 j- x" s6 J
- return(adcx3);% B s( l0 }1 |0 `3 H; I, Q7 o+ M
- }4 Q! A: T7 i0 x# t3 U
- /*获取ADC1通道3的值*/! u. `9 r3 ^% J$ A
- uint16_t AD_Leach_3(void)
! j4 l1 F1 Z7 S0 v e) X - {
% d1 @% N% B4 w y - uint16_t adcx4;2 D6 |% u- M) h6 m; {6 Z' @. ~
- adcx4=MultiDMAGetAdcTest(ADC_Channel_3);0 L7 |8 y6 ?9 x' V' k' e
- return(adcx4);
9 _ P+ C8 d+ z; m3 C* L9 N" x0 Q - }
复制代码
6 H, V) G' I- r8 P' R$ d0 p5 A: i' r* Q
目前就学习到这里,后续再写!7 ?4 ^3 z. I* _& l- ?- ~' {/ ~
. c+ J7 i7 @- |0 R7 _7 u* C- N
8 c9 D* k- I7 {' ], { S W9 e5 {
, r" v2 D6 y. ~1 h9 h4 d1 g2 A) V( E |