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

基于STM32CUBEIDE在DMA模式下扫描多个通道的ADC经验分享

[复制链接]
攻城狮Melo 发布时间:2023-6-14 11:38
概述
   本章STM32CUBEMX配置STM32F103的ADC在DMA模式扫描多个通道,通过串口进行打印。

# M$ D% L0 K( i# D+ U6 c5 g生成例程. E1 L2 m  S* e4 [5 h, A6 Z! \
   使用STM32CUBEMX生成例程,这里使用NUCLEO-F103RB开发板。
8 n* p4 f2 c2 U7 Z
微信图片_20230614113232.png

+ y+ ~4 r; @$ _# m1 x4 _, T
    查看原理图,PA2和PA3设置为开发板的串口。

& \+ n% ?7 d, \' x1 F1 @
微信图片_20230614113235.png
! `' H& }2 ~! g
    配置串口。
3 q0 a2 T5 O# K' `( L+ q
微信图片_20230614113325.png

7 s4 ^$ G4 J; n5 ~! M
    开启中断。
7 p8 W+ \. }- G3 Q% W
微信图片_20230614113328.png

9 ~2 p: L% E$ S
    查看原理图,Arduino的接口A0-A5都是AD口。
4 E$ c  Z* a0 O/ v4 S
微信图片_20230614113330.png
9 z  {( v9 l/ D0 N! F" l# q4 u
ADC通道配置

; L3 `0 u: ^. T/ _/ R
6 _; W4 o. Z9 I' p: k" v! x9 x! L9 s
微信图片_20230614113334.png
3 Q; o9 w5 @7 j% |0 e7 H/ i
ADC1配置。
( j# _4 @( l, ]# x7 y7 h% _
微信图片_20230614113337.png

/ A+ x# J3 v- Q7 f- C
● ADCs_Common_Settings:
  ○ Mode:
    Independent mod 独立 ADC 模式,当使用一个 ADC 时是独立模式,使用两个 ADC 时是双模式,在双模式下还有很多细分模式可选,具体配置 ADC_CR1UALMOD 位。
● ADC_Settings:
  ○ Data Alignment:
    Right alignment 转换结果数据右对齐,一般我们选择右对齐模式。
    Left alignment 转换结果数据左对齐。
  ○ Scan Conversion Mode:
    Disabled 禁止扫描模式。如果是单通道 AD 转换使用 DISABLE。
    Enabled 开启扫描模式。如果是多通道 AD 转换使用 ENABLE。
  ○ Continuous Conversion Mode:
    Disabled 单次转换。转换一次后停止需要手动控制才重新启动转换。
    Enabled 自动连续转换。
  ○ DiscontinuousConvMode:
    Disabled 禁止间断模式。这个在需要考虑功耗问题的产品中很有必要,也就是在某个事件触发下,开启转换。
    Enabled 开启间断模式。
● ADC_Regular_ConversionMode:
    Enable Regular Conversions 是否使能规则转换。
    Number Of Conversion ADC转换通道数目,有几个写几个就行。
    External Trigger Conversion Source 外部触发选择。这个有多个选择,一般采用软件触发方式。
● Rank:
    Channel ADC转换通道
    Sampling Time 采样周期选择,采样周期越短,ADC 转换数据输出周期就越短但数据精度也越低,采样周期越长,ADC 转换数据输出周期就越长同时数据精度越高。
● ADC_Injected_ConversionMode:
    Enable Injected Conversions 是否使能注入转换。注入通道只有在规则通道存在时才会出现。
● WatchDog:
    Enable Analog WatchDog Mode 是否使能模拟看门狗中断。当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断。
   DMA开启。
. r: C  w! C4 M
微信图片_20230614113340.png

0 M6 v' u8 V0 `6 L/ R( r5 h& h
    生成独立的文件。
, w$ A1 Y; I  L) K% K. u2 W
微信图片_20230614113343.png
) Y% o; Z- r9 I" q9 I
STM32CUBEIDE配置$ _: @4 h$ j* r
- w3 K2 J6 P- I
微信图片_20230614113347.png
, ]! I. f, ]; ?% P$ ?
    若需要打印浮点型,需要勾选下面的选项。
- W6 B2 d$ u! N

2 z  B+ G9 U2 F+ Y
微信图片_20230614113350.png
! @6 x! f, h, B1 M  l- X
串口重定向/ O/ ?& R4 `  A* _* d; o0 h
    在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。
  1. /* USER CODE BEGIN Includes */
    9 n# r. t/ n1 W: X
  2. #include "stdio.h"; c' a) i( S+ p$ @  q
  3. /* USER CODE END Includes */
复制代码
7 X! @' D! t0 Z0 N" Y
    函数声明和串口重定向:
  1. /* USER CODE BEGIN PFP */
    " U2 s: i, B3 l3 {. D
  2. #ifdef __GNUC__                  //串口重定向
    + x( x3 U' W# o" j. C
  3. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    , L. {2 t) e! ~* b
  4. #else
    # \9 F0 B/ ~* X) y3 L5 a. Y  v
  5. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)  D8 K5 X1 P" ]! O' a1 d! K
  6. #endif
    1 R0 ^) e2 C7 _) T% k$ k5 I
  7. PUTCHAR_PROTOTYPE
    ; L2 X8 x0 J- t8 W0 L" @, {
  8. {
    1 k, P$ w! {9 \+ y- R" f& T
  9.     HAL_UART_Transmit(&huart2 , (uint8_t *)&ch, 1, 0xFFFF);
    - K9 ~+ q$ q% Z' R6 D& x: U& T
  10.     return ch;, I: |9 h, p% f. p  k
  11. }% l4 P* O( l( J$ L
  12. /* USER CODE END PFP */
复制代码

0 W+ q  ~. N  Q, v8 L+ W
3 J3 v. h4 s. x
代码
  s1 r3 \' t& `5 C) i
. y* I6 g% f5 d+ E4 o
    定义变量,存放采集到的数据。
  1. /* USER CODE BEGIN 0 *// w/ C% M! G* D( V' X( J
  2. uint8_t i;
    # @; M; Y5 D( X8 N) X
  3. uint16_t adc1Buf[3];//ADC1数组
    4 Z* b& o; J3 \8 [5 A
  4. uint16_t adc2Buf[3];//ADC2数组0 X# b1 R: S0 W# y) R/ v/ Q

  5. / U  T/ H$ l& N: L5 X- f
  6. /* USER CODE END 0 */
复制代码

! L- g1 ~$ v! P# u% g3 V
    使能ADC传输。
  1.   /* USER CODE BEGIN 2 */, w. t: k' M* r# y6 O3 J5 z
  2.   HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC1_Value,30);    //使用DMA传输9 @$ D5 P: R1 |% v/ [* h* u: a
  3.   /* USER CODE END 2 */
复制代码
/ w" S  N. i* C( N' k5 N
    主循环。
  1.   /* USER CODE BEGIN WHILE */7 o3 w) R: e  ~  L
  2.   while (1)
    ) K% p# x5 f# c; k# X1 `$ z& p; x& Z9 ~
  3.   {* T+ u- _" E+ w8 T5 O( j
  4.     /* USER CODE END WHILE */
    $ ~% X5 U. o1 P
  5. $ M. T- r- k6 `1 z: d! Y
  6.     /* USER CODE BEGIN 3 */
    / l# E1 z& |/ h6 Y
  7.     if(ADC1_Flag==1)( V; K. R; }* `
  8.     {
    ' D/ n+ f) x/ ]5 t& j! u
  9.       ADC1_Flag=0;
    5 k6 a3 ?# S. _2 C7 L
  10.       ADC1_1=0;
    + a& d. T" E1 ?0 d7 W  K* P
  11.       ADC1_2=0;
    * x5 Z/ `' E1 r" h: o$ q
  12.       ADC1_3=0;
    * _$ ?8 j8 u- u. T$ j
  13.       for(i=0;i<30;)1 i5 a6 K6 x( i3 W# {
  14.       {! j/ }5 U1 ^  e" `! W
  15.         ADC1_1+=ADC1_Value[i++];
    % A8 }! b( a9 x# p6 d6 t
  16.         ADC1_2+=ADC1_Value[i++];( M9 U6 n# i. v/ d" ~9 m
  17.         ADC1_3+=ADC1_Value[i++];2 e+ x2 M% S! X6 ^6 F# S! }
  18.       }
    6 d7 ]3 }1 b6 v2 N
  19.       printf("\n");
    2 D) F: M5 F" H% p
  20.       printf("adc1_IN0(PA0)=%4.0d,ADC_IN0=%1.4f\r\n",ADC1_1/10,ADC1_1/10*3.3f/4096);0 P8 [. F0 r$ @/ q, x) l* t
  21.       printf("adc1_IN1(PA1)=%4.0d,ADC_IN1=%1.4f\r\n",ADC1_2/10,ADC1_2/10*3.3f/4096);1 J0 i$ Y* h7 `, U% a- G1 s, j
  22.       printf("adc1_IN4(PA4)=%4.0d,ADC_IN2=%1.4f\r\n",ADC1_3/10,ADC1_3/10*3.3f/4096);
    1 j7 J, ]4 @2 ~- p9 K
  23.       HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC1_Value,30);    //使用DMA传输. E& D3 C9 x4 f4 M- m4 z
  24.     }' ^! y& e; ]2 g; j3 @+ E/ _$ ~
  25.     HAL_Delay(1000);
    # K, Z/ u- ?9 C* K& A+ R$ t7 d' G# ^: R
  26.   }
    3 z* d8 ^( E/ H4 ^( C8 F
  27.   /* USER CODE END 3 */
复制代码
# \& b0 M& g# i. O
    ADC回调函数。
    DMA传输的时候如果读取内存片段,会有仲裁器的问题,加了一句关闭DMA的语句HAL_ADC_Stop_DMA(&hadc1);

  1. 7 f' x6 D" W4 [+ Y  X2 P2 j
  2. /* USER CODE BEGIN 4 */
    ' g9 ]3 d- z" `+ n9 |/ I5 {
  3. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)! E0 b1 p: _$ `6 O* l7 }- o
  4. {. K; s4 r; \, _( ]' \
  5.   if(hadc->Instance == ADC1){& `  }7 \* A* S: X; p( a( w
  6.     ADC1_Flag=1;$ s7 {# ~4 Y3 g6 s( z# }' U) \$ S
  7.     /*
    9 ?8 c$ k: s* j2 J. \0 g
  8.      * DMA传输的时候如果读取内存片段,会有仲裁器的问题,加了一句关闭DMA的语
    : N$ Q& M+ y# g8 k0 Q' R1 k$ K, a9 Y
  9. ' G- d! A+ ]" _8 m- k' A
  10.      */5 s$ d# s/ h* R' X( \- a- w
  11.     HAL_ADC_Stop_DMA(&hadc1);9 B0 d8 c  E9 v4 T# _2 Y& A
  12.   }
    : ^1 j- h+ `% @/ B0 g3 H8 i5 ?
  13. }
    5 H0 }& I1 v, U' _% T" ^3 H
  14. /* USER CODE END 4 */
复制代码

. F9 c' t/ X: `1 f测试结果  ]3 o* d. n' Z* A6 Z) C* e% l' Z
    输入固定电压进行测试。
6 {3 p2 x- ~2 ~) ~) v& g- J0 y

- X+ T4 z" t9 s' x( E. p: _- J
微信图片_20230614113352.png

- D( e6 |/ T: {1 E7 _
' m6 j% O% X( `  D
    Normal下测试结果如下。
1 _( [( Q+ K, v, Q2 V' l
微信图片_20230614113355.png

4 K, I' R' p: A/ }
    若不试用关闭DMA的语句HAL_ADC_Stop_DMA(&hadc1);
    会造成数据错乱。
* C7 {* o$ V( `
微信图片_20230614113401.png

8 V" S& R2 A2 G* D
    Circular可以下可以一直进行采集,不需要HAL_ADC_Stop_DMA(&hadc1)都可。
+ y. c. U, `) R# t4 G( }4 N

# v- L. |, e1 v+ D4 s
转载自:记帖
如有侵权请联系删除

9 V! J, N9 c5 ~
4 v' H4 t" w1 W" K" z
微信图片_20230614113418.png
收藏 评论0 发布时间:2023-6-14 11:38

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版