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

【经验分享】STM32使用HAL库的ADC多通道数据采集(DMA+非DMA方式)+ 读取内部传感器温度

[复制链接]
STMCU小助手 发布时间:2022-4-10 22:06
ADC模式介绍:
2 n3 o: d- m# G  [% Z& {扫描模式: 使用STM32CUBEMX配置了多通道后,这一项默认开启且无法设置成关闭。这个模式就是自动扫描你开启的所有通道进行转换,直至转换完,例如你开启了CH0、CH1、CH2、CH3这四个通道,启动转换后ADC会自动将这4个通道全部转换完,但是这种连续性是可以被打断的,所以就引出了间断模式。
# g; X' t- l. D4 Q2 |- |( Q3 H连续模式: 在CUBE中选中ENABLE就是连续模式,DISABLE就是单次模式。这个模式顾名思义,还是以CH0、CH1、CH2、CH3这四个通道为例,如果开启了连续模式那么就是一直在扫描多通道进行采集,也就是采集完这4个通道后又重新开始采集,不会停止;如果关闭了连续模式,多通道扫描4个通道各采集一次后就停止采集了不会从头再来。$ ]. L% O( T8 o' s
间断模式: 可以将多个通道进行自动分组,例如你开启了CH0~3这4个通道,假如你设置了间断次数为4,就相当于将4个通道分成了4组,每组1个通道,那么要想采集完这4个通道就需要手动触发4次ADC采集;如果设置了间断次数为2,那么采集完4个通道就需要手动触发2次ADC采集。6 J5 ^5 ~% h- [4 L# @8 a9 |/ T9 a
案例一:轮训方式多通道采集; `/ C' R. L5 I2 w4 c
方式一:自用ADC的间断和扫描模式
9 }$ N2 P* W( M0 I
我开启了通道0、1、2以及内部温度读取通道一共四个通道:0 f' G5 ?. X; z9 R3 L) S

! r+ ]4 `$ E2 S; M4 w4 N- A" I' ? G_@1@@LE7M}WJ67HM53W5DP.png ' ?4 v* `+ J. l$ h4 d; y

* Q2 u: L- ?' X. g8 z如果想使用轮训方式并且不使用DMA的多通道采集,那么就要配置为 【单次模式+间断模式】,并且将Number Of Discontinuous Conversions为1,也就是每个通道分成了一个组,配置如下图:5 v6 k1 M' g8 [7 @8 t+ i

6 ]. `- m6 ^5 H }841P)B1{AU$BB1MO5B`WHV.png 3 P0 `2 h/ d. Z8 b9 X
: o. f! Z  U. l" y6 h3 _+ F3 o
由于我这里设置间断数为1,也就是将4个通道分成了4组,那么我每次采集的时候都需要手动去触发ADC采集,也就是调用一次HAL_ADC_Start函数,完整代码如下:% S8 }1 T5 S  C) Y
/ Z$ W/ V+ J+ v) ]5 x6 S
)IESJ6K@52ZUV9W$`S07PBF.png 8 K6 l& E, O) i6 T& [3 J+ V

2 e; A) [/ _, d, g2 j我将通道0分别接到3.3V和GND上,4通道采集运行效果如下:

, M1 c- W2 z6 y' R
5 j: P& R( J5 b %DPWF_AA5P1{E]H4D5C78OG.png 8 _# e, D! U( q3 m0 I

3 o  m: B, Z5 m- S( v4 u方式二:完全轮训
; B  I2 L' E: D3 p* j
完全使用轮训的方式不能使用扫描模式,但是使用STM32CUBEMX配置多通道扫描模式不无法被关闭的,所以我们先用STM32CUBEMX配置成一个通道:
7 \+ e9 X  V  M+ \
2 `. D2 v/ k" _  h- R LN1]B)GP2)P(~%_(Q{M85@K.png
: y* z) a" P2 }* C* H, }" s- T. A; s. r3 A, M7 A5 Z
然后读取ADC采集数值的函数是这样:" O$ i; N3 Y# M4 y- ~

8 r3 v8 C/ ~9 l% `& ]
  1. uint16_t ADC_Read(uint32_t Channel)1 r3 c- G9 m) G( E. p. O3 W
  2. {/ G9 I' v9 U( _; k6 g) Q$ V
  3.         ADC_ChannelConfTypeDef sConfig = {0};5 _7 R1 t( ]% m- T& s1 ~
  4.         sConfig.Channel = Channel;                                         /* 通道 */
    / P' R0 I' Q- N& V) v* s
  5.         sConfig.Rank = ADC_REGULAR_RANK_1;                              
    7 D- c3 r( l6 N4 _. H# A: \- t
  6.         sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;                  /* 采样时间 */; j& b8 L5 b( X6 H! A. P
  7.         if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)             + {; C$ q7 f, n# s5 e, B. m* R
  8.         {
      V! r2 O+ H# _
  9.                 Error_Handler();
    ! H2 i6 O* ?. u
  10.         }! K( B  w/ _* s& ?$ e3 J8 ?  g! ?4 [
  11.         HAL_ADC_Start(&hadc1);: I) {+ D# [8 E0 B
  12.         HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);3 |, L2 _# |: v3 _; Y
  13.         return (uint16_t)HAL_ADC_GetValue(&hadc1);
    , t  T0 j3 w/ ?- P& H
  14. }
    - v' ?4 q6 {( D7 X+ ]( P3 ]

  15. 4 i6 m. S* u; k1 {8 U$ }' C
  16. /*, q! b4 ^: C. I6 \% P$ h" E
  17.         uint16_t ADC_Value[5];
    + b( D" ^" `" e' b9 C  r$ k2 ~
  18.         
    $ s+ ^+ i3 p- x7 T
  19.         ADC_Value[0] = ADC_Read(ADC_CHANNEL_1);  // 采集并读取通道1
    + ~5 h7 e* _: @- _
  20.         ADC_Value[1] = ADC_Read(ADC_CHANNEL_4);
    * m. s, T3 q! X* v- X5 T  U
  21.         ADC_Value[2] = ADC_Read(ADC_CHANNEL_5);
    ' Y/ y2 ^" Z* B8 Z3 h. J
  22.         ADC_Value[3] = ADC_Read(ADC_CHANNEL_6);5 g2 G) }0 s% r
  23.         ADC_Value[4] = ADC_Read(ADC_CHANNEL_7);) g' P% c6 n. [( m7 \5 z4 A* x$ C
  24. */
复制代码

( E# J+ [% u# @$ B4 `2 U案例二:DMA实现多通道采集
0 P; ^8 L! s4 `! g! P% r通过DMA实现多通道数据采集,要将连续模式和间断模式关闭;如果连续模式开启,那么通过DMA传输到的数组中,每个通道所采集到的值对应数组中的一个位置就是不固定的,例如你开启了IN0~IN3这四个通道,ADC_Value这是个大小为4的u16类型数组,你在第一次采集的时候IN0的数值通过DMA被放在ADC_Value[0],第二次采集的时候IN0采集到的数值就被放到了ADC_Value[1],这样的话就极不方便我们对每个通道的数据进行分析和提取。
  o3 N& y/ }8 j9 Y* A3 }" |
6 Q/ }1 G' J6 m4 p3 r配置如下如:! z1 Q* O' y$ A" V' o1 x
5 M' ]7 d3 r) I5 s" V- b; }
20200820152200735.png 3 x" @8 u% J3 u. E7 c: D

& y3 i1 S2 Y8 r* x; o开启ADC中断:

6 C/ j- E' H. `7 B$ E
" Y' W( b+ S0 p  ~ 20200820152219329.png 5 d% R9 g2 K) Y
' ?! ^: o7 p* Y- E2 z
开启DMA:
' q0 b! _( x; o& n
$ v5 u  d. F  ]. }6 x9 D6 e: Z
20200820152311694.png 6 l) b  x8 v/ [

% G  f+ P5 g9 W" t1 D# n2 J  j; r代码如下:
# @! h9 p" E" B0 N

+ j+ Z0 L6 Y+ o# O4 d* D! ^) x @UG1L~GDS78SIS16]1GLOCK.png
: s7 Q% b' g( L* w; ]
  o) ~$ s2 h% t" P$ U& ]: O$ p1 T4个通道采集运行效果如下:

9 v% ~, l+ l* T5 q3 y4 R% q; J; Y
4 I( B0 G4 p" ]2 i: t 20200820152427227.png
" u. m6 k4 U6 x0 H* \$ _. W& n8 _) E
补充:内部温度传感器ADC通道
. l8 j8 q" W" T+ m
7 X% s7 {# J  j# Y1 E7 {
GAKR7@JJ[T~]Q~DM}HO$VWS.png * D: g2 z" H- z5 ?$ \
3 d- ]. M% t6 D
上面图片是截取在STM32F103RC的datasheet中的,中文意思就是:温度传感器必须产生随温度线性变化的电压。转换范围在2v < VDDA < 3.6 V之间。温度传感器内部连接ADC1_IN16输入通道,用于将传感器输出电压转换为数字值。
5 t6 A' V: o: o" |
6 B5 F4 C9 }7 ^内部温度计算公式:
! q5 C/ k7 M, d0 Y$ N
6 D7 ?% Q% L4 C) L* z8 e/ c; }【Temperature = {(V25 - VSENSE) / Avg_Slope} + 25】5 E' O6 K) @# l0 h
+ V, m6 j5 Q' v* h
字段说明:
% J3 H. G5 A. m0 d$ U* i2 k6 ]: p" q! V% O. e: ]9 E  e4 X8 P
V25: 最小1.34V,最大1.52V,典型值1.43V
" X- D( {5 [! d2 b' YAvg_Slope: 最小4.0,最大4.6,典型值4.3mv/℃( H3 R& j  y: F/ u
VSENSE: ADC采集到的电压
, L2 B3 _  W) D( I9 H' L+ x0 i
- i3 d, r/ v# Z* T$ d SH{S`{3CYXOCF@_1}806GKJ.png 8 T; F& Y, a: ~: Y, n' _( ?
* |0 Z( o. Z- @5 Y/ [% K' x2 @/ R. ?
ADC值转电压值计算公式:【电压 = ADC采集到的值 * 3.3 / 4096】
6 w' L6 @+ l+ U: W! B
4 W# H  g2 V0 d; s7 u看上图我采集到的值为1703,先转换为电压值:1703*3.3/4096≈1.37
4 x- E/ T  p* z* @9 {2 N
7 W# t. N/ v# E, j) L7 {  b1 C转换为温度:(1.43 - 1.37)/ 4.3 + 25 ≈ 25.01℃' u5 f6 r% f2 H: `' p

& ]5 o0 A# @  |% W6 w0 |8 |5 s2021年8月24号修正:上面这个计算有误,应该是:(1.43 - 1.37)/ 0.0043 + 25 ≈ 38.95℃# [0 D% E. _( U8 m5 ~7 ^+ v

% |7 I( d- E  ^
- z" @+ m% N/ U# p. E
; \* z4 A, W4 p6 }5 u
赞 收藏 1 评论0 发布时间:2022-4-10 22:06

举报

0个回答

所属标签

相似技术帖

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