你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32的ADC编程方法

[复制链接]
STMCU小助手 发布时间:2022-1-23 15:42
记录一下STM32的ADC编程方法!
        前面已经学习了DMA,知道如何使用DMA去减小CPU的负担,这里的ADC转换也来使用DMA---这个也是STM32的ADC转换最常见的方式。

6 q2 r' N& r$ u' V. k
---第一步是---了解STM32的ADC对应的GPIO口----如下图---不用记住,可以查询,我是将它剪下来粘贴到书本的相应章节----!
# z6 k8 R: z2 c( u
20141103230734890.jpg % H. v# ~0 w! ^  X4 z/ Z
/ @: _9 o1 s. ?) r# j, G
---第二步是---配置相应ADC转换的GPIO口----这里使用PC0--PC1
  1. static void ADC1_GPIO_Config(void)
    # H4 A6 S1 o" t: }$ t
  2. {
    3 j( O1 c3 L1 x  o. Y# m
  3. GPIO_InitTypeDef GPIO_InitStructure;0 o% Y4 ]* ?2 L0 J

  4. 2 ?2 Z6 c* I- E; F# o9 r  q/ u( Z
  5. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //打开DMA1的时钟5 |- g# I  T% U+ U' R1 P- ~
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);5 r' W5 n. [$ ]  c8 c, a2 ^
  7. 4 g5 @8 h5 b# W. J; W; f8 ~
  8. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1;; |3 l) ~: Q6 C0 W8 \
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  //模拟输入6 Q$ p; }- x! _& \! K( L- K& T" I9 Q
  10. GPIO_Init(GPIOC, &GPIO_InitStructure);+ l  e9 O$ U, \! b7 M
  11. }
复制代码
6 q6 w1 ~& s% X
---第三步是---配置ADC的DMA----配置ADC通道等---
  1. <div align="left">#define ADC1_DR_Address    ((u32)0x40012400+0x4c)  //外设地址
    5 V& U# P; A, W# A( l4 \9 x; n* I
  2. __IO uint16_t ADC_ConvertedValue[2];  //内存数组</div>* d# A/ O* }( C. M- G, o& j# A
  3. <div align="left">static void ADC1_Mode_Config(void)
    . u, M) |) g+ `1 g( R: S8 n% ?* L  g# @
  4. {
    " n) z2 A& s6 U1 g5 b6 f
  5. DMA_InitTypeDef DMA_InitStructure;
    ! R2 }6 A4 ~  T2 a9 O1 s0 N% @
  6. ADC_InitTypeDef ADC_InitStructure;
    3 g+ h" i7 ?4 A: I" k

  7. . t: X4 Q/ U6 j2 V9 Q! _; F5 K' B
  8. DMA_DeInit(DMA1_Channel1);  
    ; J( h4 G. `& J4 @# o3 Y) l
  9. //---------------ADC的DMA配置--------------------
    1 e- z, \9 A( ~1 P9 |: f
  10. DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;  //ADC1地址---代表ADC1保存转换值的寄存器; f. d0 B) y; V( n3 b$ r2 z
  11. DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;  //内存地址---用来保存DMA传输过来的ADC转换值----后面直接使用的变量地址. \+ l& b% d" F  n
  12. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //外设为数据源
    9 W, o& h6 C0 k# Y' [% @; K5 r" g5 K0 e
  13. DMA_InitStructure.DMA_BufferSize = 2;  //传输总数据---2通道需要传输2个数据
    7 b' u. Y8 N9 ]& S4 n9 a* Y3 H
  14. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址固定
    , |& w) `% z# A# d
  15. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址自增---总体表示始终从外设ADC1地址处取值---依次保存到连续的两个内存变量中---- z% x, x) q+ |$ P3 p7 @
  16. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;   //外设传输数据单元---半字16位# v. p! e' ]# v
  17. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  //内存传输数据单元---半字16位
    ' K' x5 a% |$ L4 h& F/ L4 j0 V* s
  18. DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //循环模式---2个数据依次循环接收从外设ADC1传输过来的ADC值---/ k1 Q/ S, a6 d+ l7 O6 J
  19. DMA_InitStructure.DMA_Priority = DMA_Priority_High;  //高优先级8 y. P3 Y2 p9 A
  20. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //禁止内存传内存
    , P# E4 h% ^% N1 _
  21. DMA_Init(DMA1_Channel1, &DMA_InitStructure);/ n, H: ?3 j% B& [5 S" X+ f( V
  22. 7 j2 P3 s8 f4 w* Y
  23. DMA_Cmd(DMA1_Channel1, ENABLE);  //再次打开DMA1
    2 ]% V- G0 ^3 k( J. m) N3 q3 f6 g
  24. . U% ?3 Z: S# E$ m; |( m
  25.         //------------ADC模式配置------------------------3 |% Z# u. \7 Y# R, Q
  26. ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //独立模式----还有很多模式---这个比较常见8 I4 S8 \" \, c8 G! L1 ?
  27. ADC_InitStructure.ADC_ScanConvMode = ENABLE ;   //扫描模式---采集多通道使用----本程序采集2通道---所以扫描模式% b, E) G) R, s  C3 |- `$ P4 w7 ^
  28. ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;  //连续转换模式---不难理解---就是不停地采集---一次接一次
    / K  ]) N! L! G
  29. ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  //不使用外部触发转换---触发分为外部触发---比如中断与定时器。软件触发---后面有专用函数/ y- y9 V, v/ i
  30. ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;   //采集的数据右对齐---方便计算
    6 W; i6 v* z  g# s7 w7 J' c+ W3 o# R
  31. ADC_InitStructure.ADC_NbrOfChannel = 2;  //总共需要转换的通道个数---这里2个
    0 O8 T, J/ f2 e; c0 l
  32. ADC_Init(ADC1, &ADC_InitStructure);* a3 L+ ?8 v( F% {. Z! T/ I2 [
  33. / I5 |: p: v2 R* u# F
  34. RCC_ADCCLKConfig(RCC_PCLK2_Div8);  //配置ADC转换时钟---PCLK2的8分频
    - \9 ?7 C/ t7 k0 E  B0 ?7 C
  35.         //下面这个函数比较重要----配置ADC的通道与采样周期---前面说的PC0与PC1对应的ADC通道分别是--10与11。采集周期也有几种。
    ) ^! u7 W0 H1 y% k
  36. ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5);
    $ v  h4 R+ T: w' M: c% N; i: @  G
  37. ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_55Cycles5);+ E- G  q& i6 f% c+ ]4 V6 X
  38. 4 E. o! q+ Z8 E
  39. ADC_DMACmd(ADC1, ENABLE);  //打开DMA1的ADC18 U2 j* `9 R1 C" W- G) l3 E6 x7 V
  40. ADC_Cmd(ADC1, ENABLE);  //打开ADC1* e5 r) Z' L7 k7 N7 [
  41. 7 g6 T3 W% G! T! c) Y" C
  42. ADC_ResetCalibration(ADC1);  //复位校准寄存器7 {7 V8 b% }7 a% a, e5 {
  43. while(ADC_GetResetCalibrationStatus(ADC1));  //等待校准寄存器复位完成! }5 Z) R9 t8 F1 x- O3 X

  44. % d* g' `: n. A; ^3 h/ l
  45. ADC_StartCalibration(ADC1);  //ADC校准( g8 }5 W* y2 H" ]) S
  46. while(ADC_GetCalibrationStatus(ADC1));  //校准完成
    6 k, K/ r: W. r. b; v" T8 Q

  47. 1 S  k( o& Q3 w( B5 @/ j2 z5 ]( q
  48. ADC_SoftwareStartConvCmd(ADC1, ENABLE);  //软件触发转换- T6 l9 s/ Y3 V2 D0 r
  49. }</div>
复制代码

% U; M; u5 ^$ w; V; Q3 g
---第四部分是---在硬件上使用了一个通道切换芯片----CD4052----由PC2---PC3控制通道的选择CD4052切换控制GPIO配置----
  1. void GPIO_Config(void)8 ]/ `. ?4 B8 V6 a4 B  l. m
  2. {
    8 a4 S/ W. H1 \& j
  3. GPIO_InitTypeDef GPIO_InitStructure;+ K0 l$ i. E- f' D- ~' f
  4. 6 S% i! {3 N) G8 D
  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    + B& }" y# P. f1 V
  6. ' H) |, i  G9 B
  7. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;6 x" T0 g" w2 \# \' _* Q% c
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推完输出2 u; N: n- ~+ c' n) N9 ]
  9. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;, x! a) r+ Y/ [1 W: \
  10. GPIO_Init(GPIOC, &GPIO_InitStructure);' E+ {5 e; u0 M# C0 w2 W6 x. I
  11. }
复制代码

4 X' K( ?5 D- K
---第五部分是---主函数-----
  1. <div align="left">extern __IO uint16_t ADC_ConvertedValue[2];  //声明外部变量1 p5 _) S' `" R% f
  2. uint16_t My_ADC[2];  //求平均值</div><div align="left">int main(void)
    2 g/ P3 ^# F0 \7 E$ ?6 b: r- B
  3. {
    7 g! [% m% m8 F' ^% ~( B0 U+ v
  4. u8 i,led=0x01;
    # t1 O9 N% z% h- u) N
  5. % i$ ^6 u: k' \" z6 Y; ?2 p
  6. USART1_Config();</div><div align="left">0 J! L6 [- q) x
  7. ADC1_GPIO_Config();0 C. X& S+ \' y, ~; [
  8. ADC1_Mode_Config();</div><div align="left">+ k6 d, z5 b8 a0 ]0 o( Y7 X
  9. while (1): R' M* o) i0 Z5 X9 m8 f
  10. {
    3 N6 L' q* ]4 _# l7 y8 b) j  e
  11. My_ADC[0]=0;/ D# ]: B; e& ^, z' |+ \
  12. My_ADC[1]=0;
    1 w- C" U8 w& h5 X( {

  13. , q5 B, Y( l; b% v4 _  z) d5 o
  14. : K" [# Y$ D. z% H% O. i6 o
  15. for(i=0;i<10;i++)  . [" R5 t. j! B" K) U
  16. {) u* R. n# [2 B* u7 g5 o
  17.                         My_ADC[0]+=ADC_ConvertedValue[0];
    3 |5 I# g. @' S& E
  18. My_ADC[1]+=ADC_ConvertedValue[1];
    0 X6 u# Y: Z$ B  C" R
  19.                }- U+ l' e+ a/ `4 b6 E4 W. P
  20. My_ADC[0]=My_ADC[0]/10;   //采集10次求平均值& e9 ]  `  C, ^$ s, z
  21. My_ADC[1]=My_ADC[1]/10;6 A3 C7 F" R4 ?, Z

  22.   w: v7 o2 L  j0 t3 t1 c. x; P* ~
  23. ADC_ConvertedValueLocal =(float) My_ADC[0]/4096*3.3;   //转换为电压值! n% t) n+ A* O9 ?4 {! ^% i% b
  24. ) m& F5 @. K7 ?5 l4 {  e
  25. printf("\r\n The current AD---0 value = 0x%04X \n", My_ADC[0]); - S, p4 @0 V$ x8 f
  26. printf("The current AD---0 value = %f V \n",ADC_ConvertedValueLocal); 1 u. ^6 v; g5 e9 ?* w1 }
  27. & F+ b* T" j! H" ~, _, A
  28. ADC_ConvertedValueLocal =(float) My_ADC[1]/4096*3.3; % E4 C* j* t6 R! r0 s% f

  29. ' e+ ]+ k  X4 z+ y4 _
  30. printf("The current AD---1 value = 0x%04X \n", My_ADC[1]); # ^, }) a* i9 r0 o  f9 ^5 z
  31. printf("The current AD---1 value = %f V \n",ADC_ConvertedValueLocal);  3 I& h# W7 T* C3 W: x$ I; w# E
  32. }- T. _+ V6 G7 N: C- D
  33. }</div>
复制代码
& a& U1 A: u4 H; w& v) B9 b3 Q
赞 收藏 评论0 发布时间:2022-1-23 15:42

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版