本帖最后由 strang 于 2018-12-12 16:08 编辑
" S* X+ N! C9 W) A9 ?; N f9 T6 ?
编辑原因:上传代码不全,补齐代码。
2 L, e( n3 _/ E. D' G
在“野火助力,书香醉人—第四轮书籍申请 ”活动中申请到了《STM32库开发实战指南---基于STM32F103》 一书,此书共分基础篇和提高篇,46章,693页,内容非常丰富,全面讲解了各个外设和代码分析,火哥的例程写的很详细,移植起来非常方便,而且例程也很接近项目实际应用,在此感谢意法半导体STM32/STM8技术社区,感谢野火提供的书籍,感谢工作人员! 一、NVIC中断优先级 NVIC优先级分5组,主优先级数字越小优先级越高,子优先级在主优先级同等下,数字越小优先级越高。用到哪个中断,就用对应的中断源和使能中断。 下面是使能串口1的中断,同时设置抢占优先级为1,响应优先级为2的初始化方法: - static void NVIC_Configuration(void)
9 O v% P" S7 E# `6 K% M - {
7 z1 o, P5 ~5 ?0 ? - NVIC_InitTypeDef NVIC_InitStructure;- G7 [+ b1 ~ R: L4 T2 c! p
- /* 嵌套向量中断控制器组选择 */
2 M- l7 R6 j+ `4 s+ s5 p - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);) f0 T+ X. \/ `
- /* 配置USART为中断源 */) Y/ J2 C1 t, y! q
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQ;& O8 H2 `1 U9 Z+ g) y3 q9 Q" e
- /* 抢断优先级*/+ G/ j$ |% h ~2 E
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
2 h2 T0 T+ }5 B _8 {/ n - /* 子优先级 */4 k' W) g6 x2 g/ R0 }' M
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;3 e: m4 e/ r7 W, U8 ^
- /* 使能中断 */% V7 S" u5 H' h7 R3 m1 Q
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;1 B# S9 h- |- A" w8 l
- /* 初始化配置NVIC */
( v1 W% p& [ h# s3 D& ?, ^ - NVIC_Init(&NVIC_InitStructure);
4 ?3 w; i8 @$ O: z/ B+ T - }
复制代码二、DMA---直接存储器访问 9 Y; A) _- W. Z# }
DAM有DAM1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道。 DMA传输数据的方向有3个,外设到存储器,存储器到外设和存储器到存储器。 1. 串口DMA配置:(从存储器到外设) - void USARTx_DMA_Config(void)
/ e$ U( _0 i0 T8 G9 w, K8 s - {0 [- q) x2 I3 p: C
- DMA_InitTypeDef DMA_InitStructure;9 u) F3 V2 x/ B4 A/ |& A
- // 开启DMA时钟1 T6 @8 G; q4 @- ^" [6 @1 e3 J
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/ T3 f( o* v. t5 i. Q& I
- // 设置DMA源地址:串口数据寄存器地址*/
0 z, G/ o/ j( b0 Z- R7 w/ \ - DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS; P. B' a _. ?. m# x
- // 内存地址(要传输的变量的指针)3 ~3 Z/ U% F- m/ B% ]
- DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
6 w4 F1 I+ e. I, A - // 方向:从内存到外设
u" `; r2 D8 W, ^8 h - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
8 @5 {; K- T: l) k# [0 H) o - // 传输大小
" w( N% F: }/ }; v3 n - DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
+ b5 |" @) [' X1 j% E - // 外设地址不增 ! q \; A+ k. g0 @% V
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
4 C3 B* M& J: d1 N- ~$ H - // 内存地址自增+ _: T. L" \/ h+ `# B' r5 B
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
% K8 N8 ]* I+ A7 Y - // 外设数据单位
$ u0 j: M2 L9 s! ? _: A9 ?; v* E6 E - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
( ?) p) d; G2 f" `/ J& t# ? - // 内存数据单位
9 ]$ j3 _& d" \( V9 n5 S - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; ) g5 {1 C% T3 o$ \: I
- // DMA模式,一次或者循环模式
! p& { }5 I' q1 e( m9 w - DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;* C4 X+ [* T4 \/ A) [- A
- //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
* }- P1 C6 U; ~: g- I - // 优先级:中
) v8 q! o# _2 {' ]4 k! L - DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
+ _! @, [" d8 `: E/ B8 r9 F - // 禁止内存到内存的传输
) F9 t- t& T0 H* ?; o7 L- V5 k+ R - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;; g% s' a& r/ V U d4 q/ C
- // 配置DMA通道 ' P4 Y8 N$ W R0 J
- DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure); ' G! _) _: [) W
- // 使能DMA" p9 l$ \3 x: r+ A/ r8 D2 Q+ N
- DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
0 n8 i6 S/ z4 d - }
复制代码 2. 配置ADC1的工作模式为DMA模式(从外设到存储器)4路ADC- u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
9 W9 f% {9 {( ?4 N - u16 After_filter[M]; //用来存放平均值之后的结果+ @ m5 O2 y0 s6 y9 P0 `
- P6 }% H0 P. }4 I' q6 {. s- //使能ADC1和DMA1的时钟,初始化PC1-PC3端口8 g' k+ w& k( t% Q$ }
- static void ADC1_GPIO_Config(void)
( z3 a% Q% M" ? Y! o3 s7 Y( b7 G - {
3 P) d5 C; A4 z- C. A+ x8 b - GPIO_InitTypeDef GPIO_InitStructure;/ f: y& r, k, ?# n0 I' c
- 2 s8 j9 u5 V' m0 R& N
- /* Enable DMA clock */
9 Z3 Z" o, k8 x" ?+ g - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);, i5 e; Y3 p) [: v% z0 b
-
9 U, |9 P( P: u* j E' ^+ u* a - /* Enable ADC1 and GPIOC clock */7 M. z9 s' h1 h1 p* F8 |5 `% c
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);" z* E. d1 s3 Y6 X( r% k; m
- ; O8 m2 Z5 L: U& \6 h5 }
- //PC 作为模拟通道输入引脚 " [9 h A/ }0 P& r4 G" c! i' J9 F
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
# |% _6 D) I2 `) J) R6 O# i - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; , _' F: ]2 k5 ^2 P1 B
- GPIO_Init(GPIOC, &GPIO_InitStructure); & w, F' Z1 Z7 C3 e. k
- }( ]# V( u0 i b& L( y7 R
+ P) n3 x: M6 M3 \/ X( [: W9 ^3 |8 z- //配置ADC1的工作模式为DMA模式
% M% @' A" \7 e, r* @5 o - static void ADC1_Mode_Config(void)1 h* d& |8 y$ h9 v$ t# C
- {, Q" J% T/ `* V) Q. q
- DMA_InitTypeDef DMA_InitStructure;/ W6 Y$ T& b2 G7 e
- ADC_InitTypeDef ADC_InitStructure;1 T: z9 |1 |( j( W
-
; q' A; l7 m, ] J) ~0 l5 J6 l- k5 ^ - /* DMA channel1 configuration */; e5 K9 C8 c' B/ u
- DMA_DeInit(DMA1_Channel1);
/ k9 ]1 X( G9 J8 N# u) V7 M - DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
5 I$ X4 Z* Q' m! q7 s- f4 z9 W - 5 p0 t- P0 U [: q5 [8 Z7 W
- //内存地址 - i9 W6 I: T; V) A2 K0 D
- DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value[0][0];, I; }! W2 F, k. M
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
5 U+ Q) s% p2 M; i5 F - DMA_InitStructure.DMA_BufferSize =M*N;; W4 P( _. b2 d; |
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
$ l( k) V. P- K2 {8 W- x5 p - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
$ B5 Q& }" t$ n8 u! X- l& y - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;/ |+ M4 C/ z7 j e- X
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;( N) d3 Q8 V8 n/ k7 U! c
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;! [" C2 W6 r" |1 \6 G: q
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
9 c1 X/ ~( C3 ]/ T1 d - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;* c, t! K& i# F& x
- DMA_Init(DMA1_Channel1, &DMA_InitStructure);
$ O$ A9 R: d6 X( `, W: a9 K -
, J0 ^1 R& b- Q' [3 M - /* Enable DMA channel1 */
: N( S) I7 K. S - DMA_Cmd(DMA1_Channel1, ENABLE);8 t$ p. i `$ E. q
- ' {* y% R1 A, i& J- M
- /* ADC1 configuration */ : F( e5 {4 }) l6 z9 u
- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;8 J0 B; y A2 m3 w
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;
; T& A9 ?- R6 a/ N7 _ - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;6 F+ ^8 g( w# r7 F* s- s* V5 J5 F
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;3 e: v5 S3 @1 w
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;2 x# J0 {3 O6 [$ ^$ A' w
- ADC_InitStructure.ADC_NbrOfChannel = M;
3 ?) r- d4 c/ C; C& w( T - ADC_Init(ADC1, &ADC_InitStructure);) Q8 |6 c/ e' T9 E; O1 k3 f. C
- ) ], A1 `' f2 O, o+ C
- /*配置ADC时钟,为PCLK2的8分频,即9Hz*/
7 j) l7 }5 A7 b( G# r - RCC_ADCCLKConfig(RCC_PCLK2_Div8); 9 J( R& w5 R& @2 e# j( M
- /*配置ADC1的通道11为55. 5个采样周期,序列为1 */
1 [0 n# Z, M( I- i u$ P8 b | - ///ADC_SampleTime_239Cycles5 ADC_SampleTime_55Cycles5& u1 k1 T2 |0 ^4 }- n- u; d, Y- S
- ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);1 l% f: [7 u: Y+ }2 B; l
- ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);" U5 s$ w3 Q' l2 G& g! c/ l
- ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,3, ADC_SampleTime_239Cycles5);
# p' p4 _0 _3 c7 p& l+ y9 N/ z - ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);# A4 P/ b$ k% z" k% Q5 P: u# G2 U( V
- E( S( ^) g2 I' ? |9 e. a
- /* Enable ADC1 DMA */9 R& |/ p i, r* F2 u- R7 \
- ADC_DMACmd(ADC1, ENABLE);
t! l. h2 M- V) c( Y7 U -
) G5 m: |9 C8 R- m - /* Enable ADC1 */
$ @ _" o+ n! o! V) N( B8 ? - ADC_Cmd(ADC1, ENABLE);! H' t) a: I& W% D
-
- J Q+ y. u9 P: w9 Y - /*复位校准寄存器 */
$ I: x" D/ J% p' U- F$ [; v% D8 z - ADC_ResetCalibration(ADC1);9 a& m( m: F: f( l# E, [
- /*等待校准寄存器复位完成*/2 C/ }- Z6 K: k
- while(ADC_GetResetCalibrationStatus(ADC1));
$ Q! e% A1 c8 l+ V) P - G) W5 n$ f; o7 l+ B1 r: D
- /* ADC校准 */
' S/ R3 @+ w3 m/ _+ L6 ] - ADC_StartCalibration(ADC1);
3 Y9 E- P3 o* R' b5 Y - /* 等待校准完成*/
. V8 `( G( H0 S* [3 K+ ?* g; Z - while(ADC_GetCalibrationStatus(ADC1));( Z2 S: w+ A$ B% Q4 K
-
* I: k7 w0 A1 A& ?' _ - /* 软件触发ADC转换 */ ; U' u" G, N9 P: [! V
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);- X5 ?: a# w# @* a# `5 w
- }
' V5 P' W( R5 E$ r- T# l - /* ADC1初始化*/ 9 w0 d1 a0 |: _- Y2 u4 e
- void ADC1_Init(void)
! ]' S0 z) i0 m! n- J/ g - {* k/ c4 ~7 Q r% n N$ B9 t
- ADC1_GPIO_Config();% F Q4 ~, d* d
- ADC1_Mode_Config();
4 { C2 G S/ ^; a - }
复制代码- /*ADC滤波*/) h6 v8 N9 R) q. Z( ^
- u16 MultiDMAGetAdcTest(u8 ch)
* F/ x, i7 L* f& b& x - {9 A) N0 X5 w6 Y# s& m
- u8 i;* a: w3 r+ `' M5 y' I5 n
- u32 AdcMax,AdcMin,AdcSum,AdcResult,Adc_temp;
6 C( I8 S9 c" S' x - volatile u32 ADC_Data;
9 B' ^+ @, X- Z - 8 b# B" k F2 a# x" q# k: a2 Q
- ADC_Data=0;
$ T8 s% z0 t$ s6 e - ! g; c( n0 I8 G- Z' V/ C0 n
- AdcMax=0;: f4 X( ~/ j, x p" Q6 P
- AdcMin=~0;
3 X; ~9 H, B* y3 u6 b, K6 j - AdcSum = 0;
i3 L% V- p# l* F! D5 W; @ - Adc_temp = 0;) x2 V1 d) [& i n) b6 y2 J
& b, N. R4 r2 Z& v$ L- for(i=0;i<34;i++)
" Z& X, T9 m. b - {
" Y, G) ]+ J' X# P n/ G - Adc_temp =AD_Value[i][ch];/ y% n% z1 Y3 I. x
- if(Adc_temp>AdcMax)
& c9 c/ L o. G2 c1 f+ v - {
8 D8 K& T, z: q! z' [+ E - AdcMax=Adc_temp;
$ ^) r+ u" y8 o- t* v# V- C- E - }
8 f- y/ N: R# h2 P5 c1 } - if(Adc_temp<AdcMin)
+ S6 e/ z5 y/ m% g" H/ O - {
. [$ l9 q& N! u2 e) \/ P1 D9 ~8 s - AdcMin=Adc_temp;
% m/ y: a3 _7 k& Y* F# z6 d8 B - }. ?2 A- T- ~! e" Z8 u, j+ x% D
- AdcSum+=Adc_temp;6 V# B; l! i. {8 y% F, ~3 M. O
- }
3 i! O4 W3 M1 V0 o( Q - AdcResult=(AdcSum-AdcMax-AdcMin)>>5;
4 t' L! T: z0 A' M6 k6 @ - After_filter[ch]=(u16)AdcResult;+ u( i% I! x9 \; D) j
- return(After_filter[ch]);' s1 y: s6 ?, H
- }
: h0 ~2 {/ I# e, [1 v7 y. w - /*获取ADC1通道0的值*/9 ~6 m! ]- ]; I- w. O# t( `
- uint16_t AD_Leach(void)
1 C0 M4 o6 S. k( ] - {
- D" k; t I3 n9 x - uint16_t adcx1;/ b7 T% p" p6 y8 u( F6 h
- adcx1=MultiDMAGetAdcTest(ADC_Channel_0); i7 Z( i. }) R' x5 n( }- Y' C! W& M5 x0 b
- return(adcx1);# q( Z) T/ D% @4 Z6 n. c
- }0 b: w4 K9 Z; `+ s n; J. S
- /*获取ADC1通道1的值*/3 C7 b6 ?4 r) A7 t) g! E
- uint16_t AD_Leach_1(void)
, q+ Y. W, p( {+ ?2 _6 d1 b6 z' x4 u - {+ D7 U+ ]- ` Y- b4 W3 E
- uint16_t adcx2;- P/ R) V8 l e6 Z! w! g
- adcx2=MultiDMAGetAdcTest(ADC_Channel_1);
l- [6 X% a4 q, X - return(adcx2);8 k1 B) w! J3 t9 k$ B
- }. b7 M% I- j3 h% @$ Q/ j8 t0 |# W8 \9 C
- /*获取ADC1通道2的值*/ T, q- o+ q7 [4 S& e
- uint16_t AD_Leach_2(void)/ D4 U" [6 R! R2 E9 d
- {/ M! E2 h" Y* V" X6 ^+ i# n4 \
- uint16_t adcx3;
+ K- N8 S) m. A+ d3 Q, H) } - adcx3=MultiDMAGetAdcTest(ADC_Channel_2);
$ W* Z; `8 u) s) G+ I* t - return(adcx3);0 w0 x: \! M6 e6 ]
- }( v8 ~6 ]4 i- B/ h" w
- /*获取ADC1通道3的值*/; Z) C2 s8 U+ B( G: ?( g* _1 a
- uint16_t AD_Leach_3(void)* |: b- o/ u" Q) i b
- {4 r8 T9 v! E5 i' u/ _
- uint16_t adcx4;, D" a- E2 `( G7 ]0 ?2 k2 |& q
- adcx4=MultiDMAGetAdcTest(ADC_Channel_3);
# A, ]( l' ^, ]3 e W, z, M9 O - return(adcx4);
3 J1 _0 `. X2 i5 x e/ C2 S - }
复制代码 . D' C$ _5 A: r
0 Q. ~5 T4 m4 R0 ]" ]) A
目前就学习到这里,后续再写!
( N) F; ]0 g1 T1 K4 h5 }- k" P2 L
% ^/ L; ^$ V8 c" w: Y
: q/ @; F5 I- D. i# b3 \9 O- w
|