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

利用 DMA实现STM32L0 ADC 多通道多次采集

[复制链接]
eefishing 发布时间:2019-12-20 23:14
之前写过一篇非dma方式adc多通道采集,不过之前是基于stm32F1系列来操作的。当使用L0系列按照之前的操作步骤操作并没有成功,so只能用中断或者DMA的方式来实现。L0相比原来F1系列的ADC有进行一些精简改动,所以对于adc的操作就不是完全一样的。

$ r8 Z; j* k0 N3 q6 U  E* Y. n
针对adc有一些较难理解的转换模式:连续模式、单次转换模式、间断模式等这些概念还是要先弄清楚,这个可以参考我上面一篇文章的连接。然后可以再对照L0系列的参考手册,结合自己的应用看适合使用哪种模式。

1 N' h5 T  K. Q1 F. H; U
我的应用场景比较简单:有两个adc的通道,同时对这两个通道进行5次采集然后做滤波计算处理。核心就是采集两个通道,每一次进行多次采样。

- p% E- F& G& H8 I! s7 S9 ?/ Z
按照正常的思路应该是用一个for循环,在for循环里面分别对两个通道进行采集并将结果存储于数组buffer中。测试中发现用HAL_ADC_PollForConversion该函数会在EOS序列转换结束标志置位才会结束退出或者超时错误退出。这样导致我用间断模式调用该函数时只是先采集了ch2而没有触发采集ch3,最终EOS(该标志置位需要所有选中通道都采集完)无法置位而超时错误。所以干脆换了思路,不再使用上面提到的文章的方式了。
, J) N! U1 b; Z4 A, F
之前用非DMA,那就改用DMA吧,这也可以让步骤大大的简化,减低cpu消耗。实现的思路也很简单,就是使用DMA+连续模式。连续模式的意思就是针对选中的通道不停的进行扫描,比如我选择ch2和ch3。那么连续模式的采集顺序会是如下样子:ch2->ch3->ch2->ch3->ch2->ch3-ch2->ch3…… 这样假如我们要ch2和ch3各采集5次就是基于上面的循环进行5次,DMA一共传输10次。
0 T9 Y6 z. ^  v* o. X
stm32cubemx的配置如下:
, H. H. P$ b% k
+ O- D, h  Z# i+ d* K0 s
DMA配置如下:
1 f1 [% R. T# L& y

# ^4 J4 P- ^6 C8 r/ b  M2 i4 c- f* w
这里的half word并不是固定,要看你AD使用的是几位的采集模式,我用的是12bit的,所以一个采样值要占用两个bytes。当然也可以使用word,只是会造成一些ram的浪费。
0 ]6 @2 [# |: _; z- P  @
stm32 dma采集的接口如下:
# }# R# w$ R* Z# X4 m8 w: v0 g
HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);
1 F/ |# S7 w4 a: h
: ~' A% u4 v0 h; m- ^
6 c" f. v5 r0 H
  • pData就是指向你的buffer缓冲区
  • Length这个参数有些人容易弄不清楚到底单位是byte呢还是word,那个是根据你DMA配置的Data Width来决定的。这里的Length你可以简单理解就是传输的次数,你需要传几次就填几。比如上面我ch2和ch3一共需要10次传输,那么这里我就是10了,可不是2bytes再乘以10。' Y5 U, V, \: F" C

6 B* y* n2 i1 e  V# c
最终实现的代码就如下这么一丁点:
- s; w& K$ N; i% p7 v9 A& v* P
uint16_t adc_value[10];
; ^- B% I; f5 \; }, d/ nvoid        HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)9 `* J0 W3 O' g$ x
{$ S+ m' C* C$ f6 v; I; O
        for(uint8_t i=0;i<10;i++) . D# ?# x4 P8 ?/ H  Q2 x2 h: K5 c4 K
       {. L7 [3 n" l4 J; r
                printf(" %d ",adc_value);//这里为了简单演示,所以在中断回调里面直接打印了
# f* o) @( _, V3 o7 x+ R
        }        printf("\r\n");}//下面的是main函数中while循环
' S6 x9 F( E' l* }% a}
2 c. W8 c( a; Rwhile (1)
; S% H8 A3 I1 e4 A7 `- z  {
2 ~: z' K% U4 Y        HAL_ADC_Start_DMA(&hadc,(uint32_t *)adc_value,10);
8 [- `& G0 a8 n" [8 U& C2 [/ R        HAL_Delay(1000);
# P( M# F4 u; w! z: {7 v) Z( ^  }  

8 W$ v- f" `1 L- \  E$ l6 K# Y& g
如上代码在while循环中每一秒启动一次DMA采集,传输够10个以后ADC就会停止。在adc_value[0]\[2]\[4]\[6]\[8]存放的就是ch2通道的采样值,1\3\5\7\9数组位置存放的是ch3的值。拿去做滤波处理就可以了。

& r" Z4 \7 k4 t2 o$ a" J6 O
打印的结果如下图:
2 j+ `  ~3 B  r0 E
% i/ W7 f# {8 d, f
2 j  o: H& l1 O$ i7 L

7 t4 F) j, q0 ~9 o
赞 收藏 评论0 发布时间:2019-12-20 23:14

举报

0个回答

所属标签

相似技术帖

官网相关资源

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