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

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

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

* I+ B1 Z6 _! ^* y. Z# f! {- u5 M4 _
针对adc有一些较难理解的转换模式:连续模式、单次转换模式、间断模式等这些概念还是要先弄清楚,这个可以参考我上面一篇文章的连接。然后可以再对照L0系列的参考手册,结合自己的应用看适合使用哪种模式。

) D, {% C" K. O7 j. Q8 V" J
我的应用场景比较简单:有两个adc的通道,同时对这两个通道进行5次采集然后做滤波计算处理。核心就是采集两个通道,每一次进行多次采样。

+ j% m/ F3 a, p( k! @( z
按照正常的思路应该是用一个for循环,在for循环里面分别对两个通道进行采集并将结果存储于数组buffer中。测试中发现用HAL_ADC_PollForConversion该函数会在EOS序列转换结束标志置位才会结束退出或者超时错误退出。这样导致我用间断模式调用该函数时只是先采集了ch2而没有触发采集ch3,最终EOS(该标志置位需要所有选中通道都采集完)无法置位而超时错误。所以干脆换了思路,不再使用上面提到的文章的方式了。
( l5 k* R$ a/ O7 t; {9 O5 l% ~
之前用非DMA,那就改用DMA吧,这也可以让步骤大大的简化,减低cpu消耗。实现的思路也很简单,就是使用DMA+连续模式。连续模式的意思就是针对选中的通道不停的进行扫描,比如我选择ch2和ch3。那么连续模式的采集顺序会是如下样子:ch2->ch3->ch2->ch3->ch2->ch3-ch2->ch3…… 这样假如我们要ch2和ch3各采集5次就是基于上面的循环进行5次,DMA一共传输10次。
" [; l1 o' h. o& @* g( ^  i
stm32cubemx的配置如下:
0 Q% o( z5 \7 K& d% p

3 U1 H/ O& ~3 a
DMA配置如下:

: \) x3 r! p5 `1 _5 p
- Q! E6 q4 d& \. S1 \) o
这里的half word并不是固定,要看你AD使用的是几位的采集模式,我用的是12bit的,所以一个采样值要占用两个bytes。当然也可以使用word,只是会造成一些ram的浪费。

8 h7 {* d* a: r! W
stm32 dma采集的接口如下:
; S/ W" C3 T' ]  ]0 e" d
HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);2 I5 D% r0 ~1 N3 g, P$ h0 ^

& N2 A; ^1 U( O" v! b- o
; L! ^, @' n" _8 W+ O1 }7 e
  • pData就是指向你的buffer缓冲区
  • Length这个参数有些人容易弄不清楚到底单位是byte呢还是word,那个是根据你DMA配置的Data Width来决定的。这里的Length你可以简单理解就是传输的次数,你需要传几次就填几。比如上面我ch2和ch3一共需要10次传输,那么这里我就是10了,可不是2bytes再乘以10。
    & x4 `( W7 N5 M( @
9 j, P9 }  s+ a: h
最终实现的代码就如下这么一丁点:
1 X& ?. Y. t+ U; s" d+ R" B; {& X% ]
uint16_t adc_value[10];* b. K8 `" _$ X
void        HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)0 j3 t! {+ \( R6 w6 k
{3 D  e/ V6 S) `+ [  J5 j
        for(uint8_t i=0;i<10;i++) % h3 X! H& k$ O4 e
       {
1 R- ]6 s' l: ^5 M  Y                printf(" %d ",adc_value);//这里为了简单演示,所以在中断回调里面直接打印了

1 h7 g: T5 w9 v  x        }        printf("\r\n");}//下面的是main函数中while循环) z  |$ Q' D  A! I- |( w" p/ M2 X
}
+ R5 c, |) W) X" d% [! n8 Cwhile (1)
) n( M7 \. G8 X+ }+ P  {; ^+ x4 Q. l' ~0 S0 n) Y
        HAL_ADC_Start_DMA(&hadc,(uint32_t *)adc_value,10);4 Y8 `3 P5 r# m6 S% R8 Q" |% ?8 h
        HAL_Delay(1000);; R5 _- V( b0 a* b, s% u/ y
  }  

. m3 ~& ~1 h- L1 f% k' F/ V9 M
如上代码在while循环中每一秒启动一次DMA采集,传输够10个以后ADC就会停止。在adc_value[0]\[2]\[4]\[6]\[8]存放的就是ch2通道的采样值,1\3\5\7\9数组位置存放的是ch3的值。拿去做滤波处理就可以了。

/ B8 w7 q4 H1 M9 R5 r1 o+ S0 p# @$ O
打印的结果如下图:
7 Z7 e8 x3 N, m1 Z& c

7 a! R. P. `" t. k
  r/ ?6 A0 m/ i5 e
- e8 c' R, M; c  U' Z
收藏 评论0 发布时间:2019-12-20 23:14

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版