本期我们介绍使用ADC的多通道采样。
0 {+ A" Z A: I8 r; ` |
0 R P' c4 J. `' I
7 @: {& T' L* S. O' q
0 C x6 }% V8 n$ a. s% k首先我们需要明白一个ADC外设通常有许多个通道,合理的使用这些通道可以实现多个采样点的采样和利用多通道弥补采样率不足的问题。
, U. E% d) J8 o, C
# i9 b0 n9 n4 L/ U) a7 n首先我们需要知道,我们并不能直接获取某个通道的值。
# Q3 a/ I8 `( J" |# ]
5 l) `+ h3 o, ~8 i6 c
4 ]. Y2 F( Z3 i. z8 |2 ~. ^
" X! S( s1 [1 M# s
我们HAL库中的函数的函数仅有一个参数需要传入,因此我们不能直接的获取ADC的值,这时候我们就需要明白我们的ADC的转化规则。
2 R; X0 s4 \+ K$ @8 {% d# {& g8 d T# c
- W8 U0 E4 x5 s: R# ?3 G
8 f8 d! }/ @2 F' C7 W+ }5 I在CubeMX中我们开启两个(或多个)ADC通道' F/ N9 ^9 s# u+ W8 B
8 K# W0 Q+ h' y4 o/ k% s
+ S4 a3 u' L3 _- C4 `$ W6 s' k% c
+ v9 {0 `) A' v. h
开启扫描模式和离散转换模式,重点是这个离散转换模式。
- }; Z5 w. }1 A( t# L
: ]4 z2 F8 X! m% U; K, x2 Y允许在单个触发事件中执行多个ADC转换,而不是在每个触发事件中执行一次转换。这对于需要连续获取多个通道的数据时非常有用,因为可以在单个触发事件中获取多个通道的数据,而不需要多次触发。
' r+ }1 ]' }; o2 O9 T" I2 C$ h8 Q5 e! I% H9 h
这里的触发事件我们可以选择软件触发
3 n9 G5 ~; M* z3 p. g9 m+ o6 ]5 m/ D! Y* q& i9 J3 W1 k& r8 n$ S
$ D% k" Y* M: a
* A7 h! ?4 M/ w$ y& d4 V这样子我们调用HAL_ADC_Start的时候就会开启ADC转化。
3 y6 T8 G& N- H9 t: I5 @
& n y) X# E+ n3 y* m$ q
$ j# G) b/ N2 ]
( [' a8 d2 q; f在下面的规则中规定我们的转换规则,这里我们是先测量Channel13再测量Channel11,我们调用HAL_ADC_GetValue的时候就会按照13->11->13->11.....的顺序获取我们的ADC的不同通道的值。
, h: J) i" s7 c. P0 p5 B
$ N% F! e/ H% [/ Q1 L0 b所以假如我们开启了4个通道,那么我们的多通道采样代码即可这样子写:
f& m' C( t: G: P9 l, k; n3 N- uint32_t adc_values[4]; // 存储4个通道的ADC值
% r- _3 S$ G7 {" n* }5 O - / R' e+ K: L+ |/ j9 N
- while (1)- F/ E. t# u- Z$ W% C$ V, }
- {
b1 L2 V7 [; s - // 开始ADC转换 H* e' [+ L7 f8 ]0 b
- HAL_ADC_Start(&hadc1);
/ t; h# T- ]7 Z - 0 [( M5 |4 h. M+ d1 Z
- // 依次转换4个通道
2 C" b+ u6 R- c# s6 P7 g1 P0 q9 k - for (int i = 0; i < 4; i++)
! {0 \. m/ F* b8 s: B - {
+ d# `$ [! ^/ H6 ~4 a' P - // 等待转换完成
" s, k/ ~+ }, v' R7 b9 {: | - HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
3 `' [! v7 m9 ? s; b* e - // 获取ADC值; b6 g) p, x$ g' n& |4 n
- adc_values[i] = HAL_ADC_GetValue(&hadc1);
, P: @& y. a! D+ p! H - }+ _' z' T2 O9 D6 G/ g% }
- & j7 L% e+ e# _% g& Y% |6 Z
-
+ x. K- R, T1 ]% o - HAL_ADC_Start(&hadc1);//再次开启采样
, x- ?6 ?, Y/ z - 9 `' [3 s. H5 w7 H. m4 s5 m P+ w# w y
- // 在这里处理ADC值1 i0 ]2 J$ a: s/ s Z
- // adc_values数组包含了4个通道的ADC值! a' H9 R# a2 r2 z5 _/ Q; W
- }
0 N6 m+ t" m) q* b8 t - }
复制代码 8 J7 p. F5 l& R: a3 j/ g3 z/ m
这样子我们就可以获取四个通道的ADC采样的值了。
x# ]* v* U) v2 f, e$ I" Y( x: O0 d4 h
DMA( I- d- O0 Y) S4 U$ H8 L+ }
同样,如果当我们配置了多通道DMA的时候,并且设置定时器实现采样率设置。
$ `& f+ p/ x5 F, L% }2 K; U
& A: K1 X9 B/ ]- A* `' e我们需要明白的是,DMA只是帮助我们为ADC的数据提供存储区,这样子就不需要利用MPU进行读取数据存放数据的操作了。
. O' ?& o4 S/ G/ h
2 a; G p7 b2 \; ^4 O因此配置DMA并不影响ADC的采样规则,只是存入DMA缓存区的顺序发生了变化。; N$ ?: F; B6 L6 ?; n) Z
- for(int i = 0;i<Lenth/2;i++)/ z$ e2 g* k4 K( Z+ q' t. z& _
- {
, p9 ~* `! j6 T9 Y* n i3 @ - ADC_V1[i] = ADC_Value[i*2];0 R, t. ]6 K# y# U% M6 o
- ADC_V2[i] = ADC_Value[i*2+1]0 V4 a6 W; q M# S5 d3 G5 R/ ~- q
-
1 L# y7 i4 O8 i8 I# J) h - }
复制代码
8 v/ b: f- ~* t/ ?因此了解DMA的本质与多通道ADC采样的规则就可以实现多通道的ADC连续采样啦(不过这样子采样率会减半)。
5 U. k1 V+ h; X* N+ r
# d6 l5 r: J% N4 J) m0 C/ Y4 o8 Y4 X1 O, s
转载自:电路小白1 ?9 O# E" Z. @5 H2 U4 h/ Z' r
如有侵权请联系删除
0 d$ @1 f: r9 u9 m3 O' i1 R7 b* q+ v( ] e
/ N0 E! N/ l1 l6 N
# Z, s( }; Q5 a/ T7 v2 f+ k |
stm32F104测试,四个通道数值都一样,感觉不太对,而且接3V3后,只有最后一个通道数值有变化

data/attachment/forum/202407/12/142159m8ssww2jk1269m3j.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
[md]没读取一个通道都要开启一次ADC,把他也放到for循环里面试试