本帖最后由 strang 于 2018-12-12 16:08 编辑 " C$ d' s! _/ _1 U G
0 [; I. P4 ?" H3 [5 b
编辑原因:上传代码不全,补齐代码。 % q4 s8 f3 }8 U4 y( H+ S
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员! 一、NVIC中断优先级 NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。 下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法: - static void NVIC_Configuration(void)
, s# @$ ^, _3 u6 @5 U4 Y - {6 O) i: I' h! l6 w; _3 N' D
- NVIC_InitTypeDef NVIC_InitStructure;
; S- q# q p% r: q3 ~ - /* 嵌套向量中断控制器组选择 */
" ?) D4 _3 K) G, p- X - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
) Z& z" k7 w# n% p - /* 配置USART为中断源 */
- x5 f, x4 r% m0 `# J - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;
$ S0 l! `9 A5 Z) h- F* L# O2 V% \. w - /* 抢断优先级*/! V! o; r/ y5 z) S5 |
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
0 F3 B! {+ H$ g: F& Y - /* 子优先级 */
( U8 @/ I+ D( i+ V4 t" M: j - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;# B2 `3 x# l- T) a! Z# }
- /* 使能中断 */6 o( N: d0 _( G
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;! m0 T7 c: b$ t* U- C/ l* d
- /* 初始化配置NVIC */( A0 c* } w! D+ {* ^+ Z; r
- NVIC_Init(&NVIC_InitStructure);
; J, P) H2 C' k2 l8 n - }
复制代码二、DMA---直接存储器访问
- a: H% r+ P7 c) l4 k+ Z HDAM有DAM1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道。 DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。 1. 串口DMA配置:(从存储器到外设) - void USARTx_DMA_Config(void)
' v, O: D0 m, k - {
% D, Q) T. I9 d( G2 c7 i" ` - DMA_InitTypeDef DMA_InitStructure;+ @+ z# o* A% `; o5 n: q
- // 开启DMA时钟# r5 K5 h8 S. V* H( e% u7 [
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);, t" J6 f& U: F% x( p
- // 设置DMA源地址:串口数据寄存器地址*/
! }" h+ _8 N, R- _' q - DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;6 I3 m5 F! T( M5 m8 \6 d
- // 内存地址(要传输的变量的指针)
1 H8 g: H' Q5 i- ~1 \/ p) ^$ Y - DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;9 [. t1 t# v1 _. z. a# U
- // 方向:从内存到外设
! r2 T/ n. p0 Y# t - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;2 g, ]1 K( e& j& O& {: S
- // 传输大小 # E; @% Q) c: {0 ^, {
- DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
; k; x6 z" p# _0 L: E6 k- q - // 外设地址不增
. V. y& H2 l( {2 l" v - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;% ^0 Y3 K" ]/ i
- // 内存地址自增
1 l7 U: |$ C7 u& U( i' V - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;! _1 I$ H# h7 Y3 A; Q; M8 B
- // 外设数据单位 : T" {! g8 z. e# p: x
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
+ f8 n) M$ n8 l! a1 O4 n7 y - // 内存数据单位8 T3 v& T6 `. s# R7 u. v$ o e
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
! O9 z# R1 ]. M" o S4 D - // DMA模式,一次或者循环模式0 \. s6 }5 F s. q1 B2 X# K0 Y4 H
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
, r( O* l/ ~* Y - //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
; Y l) y4 X1 [5 U* E' H& ^ - // 优先级:中
7 g) T. u E8 k9 h8 p - DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
& |1 b+ C' v* u Q$ U, Z O% b - // 禁止内存到内存的传输3 ^, l; m7 R- f2 C0 x# \, @5 \
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
. c7 o, K( w( g0 n- P, n - // 配置DMA通道
+ }$ I C5 }( h; o - DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);
! ]2 B4 X$ d. ]" M% I" D - // 使能DMA' M1 `4 A9 d2 k+ o
- DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
* s- O- x$ {1 |- F8 d$ t - }
复制代码 2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC- u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
: \ D C5 I- w$ z& {) Y - u16 After_filter[M]; //用来存放平均值之后的结果4 v; f# B0 f- r2 i
- 5 H5 I. {. |- H
- //使能ADC1和DMA1的时钟,初始化PC1-PC3端口
7 [) F$ T1 m4 s- q - static void ADC1_GPIO_Config(void)
$ C/ P1 `0 t, h - {
6 V0 s, m( h' h! D - GPIO_InitTypeDef GPIO_InitStructure; ]" V+ Z# J$ k6 K! h; \
- 3 G- U2 c3 b. t# Z
- /* Enable DMA clock */5 `" v: S! a: M8 ~8 A0 i9 E
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
) T- b0 \. U9 {) y( o* F -
+ n, W5 S! W7 ~, _5 n - /* Enable ADC1 and GPIOC clock */# r2 A# I& K6 \& y
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
/ K& l |1 `7 A0 |& }1 R- W, ]- r7 ~ - " m* `5 y* m# J) j# u
- //PC 作为模拟通道输入引脚 % ?* \- p6 T5 V, c- r3 r
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
, }3 r" f8 q8 i! G( f - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
# F5 K* w* Q9 ~* X4 I! ~ - GPIO_Init(GPIOC, &GPIO_InitStructure); ' g$ {) [. H+ S; q% |$ [1 v
- }
- N# j0 S, r# \$ `/ W
4 E& ]. q' A1 [* E- //配置ADC1的工作模式为DMA模式8 K5 n( N- }4 a% [! A+ W* w! a8 A
- static void ADC1_Mode_Config(void)( v! ^/ a6 Z+ t* F. b' t# V
- {3 U* W, B0 ` ]8 Q
- DMA_InitTypeDef DMA_InitStructure;
, ~1 [# [/ C+ } P6 C - ADC_InitTypeDef ADC_InitStructure;+ e) Y @8 Z% l7 A2 {' n$ T
- 0 T1 r- l& m2 N0 z
- /* DMA channel1 configuration */. ]6 v" T$ E; P z
- DMA_DeInit(DMA1_Channel1);
' C. ]# Q* h6 w; U* P) W8 o9 B - DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;" J1 ?6 u: ?& H- M* O2 G0 n; \
3 c9 _+ Y' W3 T- //内存地址
3 I) M2 V/ w w$ S7 ^+ T - DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];
) }9 F3 i. O- R$ t/ T - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
0 t( p) k5 p& r6 W o - DMA_InitStructure.DMA_BufferSize =M*N;
( q: n5 {# |7 U6 ^- G1 ]1 } - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;2 B) l4 \! F) W
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;7 \5 D/ q+ @4 q
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;1 A4 P9 v1 Y( Y- F
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;- D0 m0 v# i6 B1 ~1 t2 ]
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
& J0 E, f% j" v u" o0 O7 ^ - DMA_InitStructure.DMA_Priority = DMA_Priority_High;
0 Z; s& H. I' n7 M - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
% X/ U1 \' p" F+ X! ~6 I+ o - DMA_Init(DMA1_Channel1, &DMA_InitStructure);
1 {5 y) k& W% z& T" o -
, r% V% R9 }3 Y9 J4 r - /* Enable DMA channel1 */
1 i# v; }: C) y# i. T - DMA_Cmd(DMA1_Channel1, ENABLE);" T# b6 Z% f& I, z
- 0 ?! L' f# a( ^3 P2 C% M
- /* ADC1 configuration */
6 O9 O0 g0 E7 x: k% D - ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;1 c8 i0 y# N. e4 j- A
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;
: o. j* O! I% X - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;- X3 Q3 [ X3 G8 ~
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;+ u4 C6 ?7 ^. ~ X! U+ a, P
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;$ h+ C; b8 q- Z7 w, h; Q
- ADC_InitStructure.ADC_NbrOfChannel = M;
8 h$ l, w0 ~& O) x6 a2 E( g% ] - ADC_Init(ADC1, &ADC_InitStructure);
( e* N) g8 E; q$ q5 u7 @5 b - ; ?7 K) |. w b" H6 {6 c
- /*配置ADC时钟,为PCLK2的8分频,即9Hz*/; V0 p/ v$ R; R! r7 M/ c* p
- RCC_ADCCLKConfig(RCC_PCLK2_Div8);
' e" f" ^2 \9 l( ~2 m/ h* ~! G9 P! t - /*配置ADC1的通道11为55. 5个采样周期,序列为1 */ , M) p+ V: X" v) C8 q7 T6 q
- ///ADC_SampleTime_239Cycles5 ADC_SampleTime_55Cycles58 T! {+ C. H' Q: x+ w o
- ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
5 m" z( p% \/ k0 u) b! B6 ~ - ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
' x% X8 @6 ^ B: B+ e - ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);
3 G5 T8 _$ X& n - ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);; M9 m j6 |) f( B c
- ; t) _1 \3 {! {% O* i
- /* Enable ADC1 DMA */% K! ? M3 Q$ }
- ADC_DMACmd(ADC1, ENABLE);# t) H) @1 Z. T6 g3 F
-
4 d( T; e/ [, ]; u - /* Enable ADC1 */. Y2 I& d. r2 ~- E
- ADC_Cmd(ADC1, ENABLE);8 M& X; C2 R6 c$ X
-
& T/ j( X& E: b, D$ I - /*复位校准寄存器 */ / W& q& a1 U9 N: }. L
- ADC_ResetCalibration(ADC1);; m3 [0 l: E* O, P# y* E. K
- /*等待校准寄存器复位完成*/' Z; a8 R& }# \! N
- while(ADC_GetResetCalibrationStatus(ADC1));2 `* \1 z8 ?# I. t8 E# x4 L0 `
-
9 T, Z9 J" E- r; V - /* ADC校准 */- {* Z& b! p* j$ }0 V- u( K1 k- Z5 \
- ADC_StartCalibration(ADC1);
) D- G/ U: W* h5 f4 a - /* 等待校准完成*/
! V% t0 e# f$ b6 U6 z3 M- N' m2 r - while(ADC_GetCalibrationStatus(ADC1));) ~9 k6 ]% ^+ ?! J# n. Q; B
-
' Q3 @* ?. f. D8 B - /* 软件触发ADC转换 */
6 A% T! l6 K; r/ S: b6 |/ o - ADC_SoftwareStartConvCmd(ADC1, ENABLE);9 D3 i$ h) e7 b- W' L- H8 ^
- }2 s9 V2 @% M6 b' P/ O
- /* ADC1初始化*/
& \$ n* R8 o4 g8 _3 h - void ADC1_Init(void)
2 e% ]" @) ^! m - {
) ~( j( Q+ f( ?$ | - ADC1_GPIO_Config();
z2 y1 H2 g* W0 \ - ADC1_Mode_Config();0 T. N2 i: W) v* F( C' h6 Z
- }
复制代码- /*ADC滤波*/
1 o [6 t1 f1 ?0 {, P ~! Q" ^) P - u16 MultiDMAGetAdcTest(u8 ch)
1 G& p! |% T/ f ]& G. G; \ - {
, \% {, y8 o9 |, P5 A. ] - u8 i;6 B, N: ]) J3 @7 ~8 M9 H( U6 U* s
- u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
6 ]- x/ R' P# v - volatile u32 ADC_Data;' v; R6 M: D. w8 r: |
( x3 H; g. h& g1 Z1 }7 J# r- B- ADC_Data=0;* b; c0 O5 a, f5 T5 L0 B4 W( r$ y5 K0 h
- o/ t4 ?0 \& A, r& i4 A
- AdcMax=0;2 F% x, t4 I8 n
- AdcMin=~0;2 j& C1 b( T# c$ i& d
- AdcSum = 0;
/ b9 v& a* g4 N2 \ - Adc_temp = 0;
7 o! x# w. L# T - % O$ e; ~8 `5 `' i
- for(i=0;i<34;i++)
H4 E; i1 z2 U, M" ?. ?' l - {- y& O6 n2 }% o+ M' q
- Adc_temp =AD_Value[i][ch];* ?* f% V0 A) z- U! h) m2 N
- if(Adc_temp>AdcMax)
, A; T: b5 E8 R - {& X( y; I y8 N1 v& k4 c; R4 x
- AdcMax=Adc_temp;
1 _6 [4 C# m% P r" q! w - }
2 Z1 L$ c# P# a. G - if(Adc_temp<AdcMin)
4 k; b3 R& P# p" y - {# a2 [$ s7 c0 d/ t* m9 _
- AdcMin=Adc_temp;
9 _ {6 ?5 F4 C4 a: l8 Y u - }
. l1 j# k) v' H% n7 ?! [; q - AdcSum+=Adc_temp;
) z: T s) Q3 L3 O - }% _3 W+ X8 s! P8 ?5 [' i1 P- ]/ L
- AdcResult=(AdcSum-AdcMax-AdcMin)>>5;7 _: ^9 Y7 n2 _$ ]2 Y) B
- After_filter[ch]=(u16)AdcResult;1 Y' m( K, J& H: v( w& g
- return(After_filter[ch]);
' v. R: Q* j; b5 ^7 t - } / Y v+ @9 @ M. i8 _ u7 J3 e' h
- /*获取ADC1通道0的值*/
' Q& A5 {, L+ }0 m - uint16_t AD_Leach(void)
5 `6 o3 E' R s1 _: U - {
" @# b: }% A" y/ T - uint16_t adcx1;
. j" ~' ^/ M* B4 [* c, W) T( u - adcx1=MultiDMAGetAdcTest(ADC_Channel_0);5 Z$ H9 J8 D, W2 z5 S
- return(adcx1);
9 p5 Z& J5 D; N# q4 k- o$ }( X - }5 F* F8 F3 E: |# L. r4 B
- /*获取ADC1通道1的值*/
% ]& o0 g- X5 h( s - uint16_t AD_Leach_1(void)8 s: W/ K j* l) t: C3 @7 @
- { Z- c9 B6 Y3 W
- uint16_t adcx2;
2 ?4 M9 ?& H- K9 |: ]" V - adcx2=MultiDMAGetAdcTest(ADC_Channel_1);! l8 w* y/ S" r# O
- return(adcx2);
5 b. a! p* Q" ^1 M& g - }
5 ?" t; X# ]& V/ [* G - /*获取ADC1通道2的值*/# n& A! b* d* m! K8 l# B
- uint16_t AD_Leach_2(void)
) {, |4 K1 T- k; L - {
& S0 `' t. r0 X - uint16_t adcx3;
' z. w- Y- t& F) r0 B" ]: ? - adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
; p% _) f/ u0 J& U0 g* t - return(adcx3);
3 W* L9 n$ q+ d+ \7 }- M2 ` v - }- _: }+ O1 x( I. Q' W7 A5 }- d4 N
- /*获取ADC1通道3的值*/1 B* B" ]) j5 O( q/ d5 t% h1 T0 z
- uint16_t AD_Leach_3(void)
! e: T' ~9 ~/ T7 P* K' p: F - {
- C9 z2 }" e& w - uint16_t adcx4;" v! j5 i% L5 C+ N! G: q" H9 C
- adcx4=MultiDMAGetAdcTest(ADC_Channel_3);
* _$ @. N4 z# T6 ~' Y5 Y - return(adcx4); f* T N9 Q) W
- }
复制代码 5 m2 _3 H, K' o5 U5 v6 g; ^/ n+ b2 ]
. G- i0 D. v4 G1 ~3 Q. J* c3 k
目前就学习到这里,后续再写!' @5 l% |+ a) f5 B4 o$ p
& O' \# a! s6 W1 S- E8 p
8 `% L9 ^) q/ H. M2 o( S N- H( X( I( Q1 K. T- S9 |4 i
|