STM32f103的数电采集电路的双ADC的设计与使用 STM32F103C8T6拥有3个ADC,其独立使用已经在本文的3.1.3里面有详细的介绍,这里主要是介绍双ADC的同时使用,即STM32的同步规则模式使用。在此模式在规则通道组上执行时,外部触发来自ADC1的规则组多路开关(由ADC1_CR2寄存器的EXTSEL[2:0]选择),它同时给ADC2提供同步触发。此功能必须使用DMA通道。同时两组数据是公用一个寄存器,ADC1数据在低16位,ADC2数据在高16位。由于保证数据稳定,在双ADC同步规则模式的情况下,还添加了多通道同时采样。; R' R# H& D: M5 L
, W& V# y, |% p" }) v# ?9 u
8 n( b1 q" E- O- |1 X4 vADC1和ADC2,工作方式采用了同步规则模式,使得两个ADC可以同时对不同的AD输入进行采集和数据存储和传输,而且相互不影响,也可以确保采样时间的减少,同时两个ADC都是使用4通路同时采集,确保了数据的稳定性。
: G. M% J' e5 X0 m9 c/ G% q6 l$ U) X9 P6 P
( S- d4 P" m. N8 w4 h6 f多功能采集显示平台使用的芯片是STM32F103ZET6,片上资源提供了ADC123共3路ADC模块,为了布线方便以及使用的习惯,多功能采集显示平台采用了ADC1的Chanel 4~7,占用IO口PA 4~7,以及ADC2的Chanel 10~13,占用IO口PC 0~3。
4 [$ P; m! j5 f" T' ?9 V3 d8 W# H$ U+ o9 |/ ~" A0 ~5 S0 P
9 ]. ] v1 v" g3 R
使用时有几点需要注意的:
* _9 n4 y6 P5 [ p3 R; }0 W7 z, }6 n, D; K4 {
1 t1 m/ t3 j) D. l6 ?0 J
1.选择正确的模式:ADC_Mode_RegSimult,即DUALMOD[3:0] = 0110,ADC2在双模式中,这些位为保留位
1 @2 J. |! T) j0 H, Z
9 ?" U$ k n% }3 E* d0 r n' T% z
2.开启ADC的DMA,在双ADC模式里,为了在主数据寄存器上读取从转换数据,必须使能DMA位,即使不使用DMA传输规则通道数据。只有ADC1和ADC3能产生DMA请求。所以只需设置ADC1的DMA:ADC_DMACmd(ADC1, ENABLE);5 }6 R) J6 e* L
. L0 q/ [% d9 i8 }7 b. j7 D$ j/ K( a& l/ J+ `. e) }
3.ADC2的转换数据存在ADC1_DR的高半字;
6 k* D z) w, F& b x1 g! u/ J& |( o' M/ l, \2 \% M
N3 g8 R" ~+ b% K
4.不要在2个ADC上转换相同的通道(两个ADC在同一个通道上的采样时间不能重叠)。/ [" l1 L$ g @
% S* f x8 {2 E1 u% I3 L( o
3 v0 ^+ C2 Z: `% N5.ADC2的CR2寄存器的第20位——EXTTRIG:规则通道的外部触发转换模式必须开启(软件启动的时候也要),这样才能利用到ADC1的触发信号。不然的话,需要手动再软启动一次ADC2,例如ADC_SoftwareStartConvCmd(ADC2, ENABLE);
/ G; z5 }) p. K5 r% s5 p" K0 P8 N& I+ o; [" j% r
+ u4 H: P9 h5 h: s' I
但是,假如你设置了这个位之后,就不需要手动软启动ADC2了,所以考虑到同步,这样比较好。用ADC_SoftwareStartConvCmd(ADC2, ENABLE);为什么可以,一方面它 也设置了EXTTRIG位,另一方面也设置了SWSTART。但我觉得先用ADC_ExternalTrigConvCmd(ADC2, ENABLE);的话,一会只要ADC1一启动,两者就同 时启动了,这样更正确一点。
. H" Y& b; r! ^+ j! q* p. ]5 p7 {; o
8 R; I1 n# o: Q" w7 [5 [0 {, `1 N
以下是ADC1配置代码和使能代码:% {2 B* K- [7 t! N$ n
- //初始化ADC1 ; v! ^, [- Q" g- p- c @: x
- //这里采用多通道连续采样,并用DMA1的通道传送
4 L Y' o( h3 H - //我们默认将开启通道4~7
% ?7 Z+ ?* F! s) O# v+ a. E8 G - //相应管脚PA4~7 1 T/ B/ F( B D% N
- void Adc1_Multi_Init(void)
1 ~; C1 l9 u: t, b* o1 D - {
' j& a% v. P: p Q# C% z - ADC_InitTypeDef ADC_InitStructure;
* n1 o: R5 {( Y0 J* X - GPIO_InitTypeDef GPIO_InitStructure;
" y) J9 c* U3 Q5 N4 x }% e - 8 q0 o2 L3 M8 M* p0 o2 K
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟
/ { e" \. t. X+ Z - 7 E1 W4 a. U, F% Z( ?# ~* r
-
4 A4 W! s5 K0 C1 S ~' `" E: W - RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
7 C) f8 M5 L5 F; \ -
7 T/ W& x( b! d3 q0 Y. N - //PA1 作为模拟通道输入引脚 3 I6 z6 h% q7 U4 u/ ~/ x, D0 A) G
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
6 l$ Z5 h% I4 ^7 |3 H - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
9 @% |# `: H5 I! ~ - GPIO_Init(GPIOA, &GPIO_InitStructure); * R6 l. S/ [. W6 i" u- z' K
- 2 t3 ~% d7 A6 V2 T9 }8 ]
- ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
0 m7 ~ C/ ]8 T) A3 |0 N - * T3 c" ]. H6 l
- ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; //ADC工作模式:ADC1同步规则组模式 w# A6 j: c0 r" |3 D0 r4 J
- ADC_InitStructure.ADC_ScanConvMode =ENABLE; //模数转换工作在扫描模式
* S* ]2 @" i$ C - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //模数转换工作在连续转换模式 ( W) c/ j { F1 h4 [" v
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动 . d8 d$ J+ l! K* w0 K' J
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
2 @2 P# x5 Z% @* z1 L% ~$ U - ADC_InitStructure.ADC_NbrOfChannel = 4; //顺序进行规则转换的ADC通道的数目
% c$ o3 B' T8 f6 K7 E: _7 o# y9 C - ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
2 ^' @: s9 y, X; n8 A3 D; P5 V -
/ Z* ?2 b. e+ ?. I - ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_239Cycles5 );
2 ~6 B& w3 X( H. i) Q - ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_239Cycles5 ); $ Y) E& U0 F: W8 L
- ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 3, ADC_SampleTime_239Cycles5 ); : `) F* T+ ^# ? j
- ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 4, ADC_SampleTime_239Cycles5 );
3 l% f3 C7 b: ^7 s0 L -
2 b8 Q* \1 R0 `2 X- T. _ - // 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数) . }( ]/ ?& r. t( k$ _
- ADC_DMACmd(ADC1, ENABLE);
4 i5 @& B; _ v5 C - } & }9 m; t8 Y2 n* H1 Z" r2 C4 X
- //计算多通道ADC值
/ M! t6 S3 k o0 |* } - //AD_Value[]是DMA目标地址的数组空间
( b2 m, Y8 f) V; D& X" R( C - u16 Get_Multi_Adc1(void) ! ^7 [6 \! x( I9 b; w
- {
+ `+ t* B; ~' O: p% a - u32 temp_val=0; 2 r' a- P8 C D$ U) [
- u8 t; / n) ^0 l+ x6 h# |2 E/ i6 I
- for(t=0;t<4;t++) * y) T0 Z9 t/ O$ m
- { 6 s( Y5 r7 E( `& E4 I1 X9 E* i
- temp_val+=(AD_Value[t] & 0xffff); $ i, u% \- X( }
- }
0 N' |* ]% y0 t" k+ ~: I! w - return temp_val/4;
6 l' U; J/ N0 S6 L - }
复制代码 主要需要修改的是这句话,使得ADC处于同步规则组模式。
- G& ^2 |) V' p+ @8 H4 r; y1 i- <strong>ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; //ADC工作模式:ADC1同步规则组模式</strong>
复制代码 AD_Value[]是32位的,用于DMA传送的目标的ADC数据数组。其中高16位是ADC2的数据,地16位的是ADC1的数据。
" N& x# B/ @8 L V4 q3 K. A2 W" l
; y! Y r& U$ P2 ~ [0 h1 `! T3 B
) } k7 O/ {' T6 s( a8 V% d7 k4 e4 i/ I7 b5 {
其次是ADC2配置代码和使能代码: q& Z9 I7 U" _" x# Y
- //初始化ADC2
; j* d9 i1 G3 V4 m - //这里采用多通道连续采样,并用DMA1的通道传送
$ _, g" y% Q$ i! B4 ]) S) h7 R - //我们默认将开启通道10~13 * u, C& O1 V; J* E9 d
- //相应管脚PC0~3 % Y5 ~- \9 Z; G
- void Adc2_Multi_Init(void)
) e5 f) z R ]5 W2 {; G% v - {
6 B" v# e" [6 i. ] - ADC_InitTypeDef ADC_InitStructure; ) \$ J9 n0 ^8 L4 }+ P. C5 C1 g" K5 X
- GPIO_InitTypeDef GPIO_InitStructure; % e0 \( ^+ V9 Z& p$ K) t
- 0 D7 K! Y9 i+ a2 N5 |
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC2 , ENABLE ); //使能ADC2通道时钟
: M7 R) }& o8 w5 X& x -
% e9 p/ V! U% o$ f. V* t" ] - : L2 w$ E4 a* O% U0 H
- RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
2 t! [9 }% w# _% f9 f -
" f; f D' z, R. F. ^, b( j I o - //PB0,1 作为模拟通道输入引脚
3 _% I, _# q: M6 t. N5 a - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; 4 a [3 L k; @% N, V9 Z- a
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
0 C5 `# B- k9 Q8 o0 C/ ~3 {1 o% O - GPIO_Init(GPIOC, &GPIO_InitStructure); 7 p7 k" s" V C+ v/ @7 E& M' a
-
4 E, K, s) n% A8 L% K# x" Z8 V - ADC_DeInit(ADC2); //复位ADC2,将外设 ADC2 的全部寄存器重设为缺省值 - |. Z( g! q0 c- Q! v
-
5 F7 I% d- R' P - ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; //ADC工作模式:ADC1同步规则组模式 & S7 |+ A& q1 O/ P# _: k9 e2 t
- ADC_InitStructure.ADC_ScanConvMode =ENABLE; //模数转换工作在扫描模式
' l0 E4 _! E9 V3 R& w* E - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //模数转换工作在连续转换模式
+ }5 R, A. K% T( I7 i - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动 0 v! j* x/ w+ v+ p8 ]$ J& G
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐 - W8 @) f3 F, f K) b+ d
- ADC_InitStructure.ADC_NbrOfChannel = 4; //顺序进行规则转换的ADC通道的数目 ; Z9 ?7 D4 w6 p
- ADC_Init(ADC2, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
% }# b. t7 Y; _) o/ J - , {$ `# F, @# e
- ADC_RegularChannelConfig(ADC2, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5 );
. L) V# S8 m7 p8 Q; G# H* y - ADC_RegularChannelConfig(ADC2, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5 );
3 R9 { U- u& I: D5 W3 E - ADC_RegularChannelConfig(ADC2, ADC_Channel_12, 3, ADC_SampleTime_239Cycles5 );
1 i) d C6 y% c. D+ c/ C - ADC_RegularChannelConfig(ADC2, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5 );
% p$ }. h. }4 S% U F -
8 _, s% K F$ P; P - ADC_ExternalTrigConvCmd(ADC2, ENABLE); //使能ADC2的外部触发模式
* |' Y0 |! _7 Y2 L" X' U+ Z% h -
n! b5 d4 b8 D/ p - // 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)
- R: v4 p& t! t4 I/ a4 k! G - //ADC_DMACmd(ADC2, ENABLE);
3 R8 ?3 o- T/ _* e. t7 Y5 V! r - }
复制代码- //计算多通道ADC值
! G, ^. o9 O s n2 b - //AD_Value2[]是DMA目标地址的数组空间
# O; g! ~2 t% L, ? - u16 Get_Multi_Adc2(void)
# x' G2 I$ {$ L u7 c% r - { 2 R# L- t7 c3 x4 C
- u32 temp_val=0; 9 w+ b) x+ C' o2 u+ k' S, M! ?/ t
- u8 t; ' X* c" M+ o1 [; e+ b/ c! o/ n
- for(t=0;t<4;t++)
8 `0 G9 X: B0 S! X6 i! S - {
0 ]" `9 ~8 V4 f! A2 L1 j - temp_val+=((AD_Value[t]>>16) & 0xffff);
2 m; p# c% W" d$ W - }
, Q1 F% _7 k6 R8 T r - return temp_val/4; % h% Z% s8 W! d9 {" H
- }
复制代码 ADC2主要需要添加下面语句,用于ADC1触发ADC2的工作。
9 U3 l6 W* U) M- ADC_ExternalTrigConvCmd(ADC2, ENABLE);//使能ADC2的外部触发模式
复制代码 AD_Value[]是32位的,用于DMA传送的目标的ADC数据数组。其中高16位是ADC2的数据,地16位的是ADC1的数据。这里使用AD_Value[t]>>16进行移位操作,获取数据。4 T' l5 E4 B/ n" N) V7 I
' R3 @+ _3 ]3 |8 l1 [. Z/ c# _# p! \
& t0 t0 R/ Z9 s" D |