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

STM32 DMA 多通道 ADC 采集

[复制链接]
STMCU小助手 发布时间:2023-1-6 16:55

1. 本次实践目标

    a. 完成外部 ADC 的采集, 连接引脚为 PC2

    b. 完成 STM32 内置温度传感器 ADC 的采集

    c. ADC 的采集必须以 DMA 的方式工作,通过 FreeRTOS 系统中创建的一个进程读取采集结果,并打包通过网络发送至上位机


: x  ?: t) m2 o6 u0 b- L* T

2. 查看 datasheet

    2.1 确认 STM32 内部温度传感器 使用哪个 ADCx , 使用哪个 channel

         经确认,STM32 内部温度传感器使用 ADC1 的 channel_16。


' B6 d) }: Z1 |$ @) N

20170827165319724.png


% E5 q( A; o3 Y2 O

   2.2 查看 PC2 引脚作为 ADC 输入时,使用哪个 ADCx, 使用哪个 channel


/ [5 x7 y0 }+ e. h0 u( O7 Z4 @7 L

         经确认,STM32 的 PC2 引脚可以使用 ADC[1,2,3] 的 channel_12。


) C( D( z/ z4 {7 ?8 g

20170827170131825.png


, G- L& P9 [8 w8 J' J& R

    2.3 通过上面的分析,可以选择 ADC1,进行 DMA 多通道采集 ADC


) t, E7 ?$ K" g( Y# y  P2 g

         确认,使用 STM32 的 ADC1,后需要确认使用哪个 DMAx


# e- H& n. [  `- E, |6 d

         经过确认,ADC1 使用 DMA1

4 R8 E" H6 s( e; e4 u

20170827170742159.png

7 G% X3 N9 s+ x  d+ Y  h

    2.4 确认外设的时钟源

5 ~3 Y; o' c( T  P: a

          确认 ADC1 的时钟源为 APB2 时钟分枝,并且 GPIOC 的时钟源也为 APB2 时钟分枝


6 B+ @4 q- r% u

20170827171400794.png


3 C/ ^- ^7 f+ j( d

    2.5 研究 STM32 DMA 多通道采集的方法


" p3 v& A2 J3 R

   2.5.1 位分辨率

' B6 U0 ?  I& v8 x

   在STM32所有系列芯片中只有少部分是16位的,如:F373芯片。


% x0 X! [6 f  g/ N

   12位分辨率意味着我们采集电压的精度可以达到:Vref /4096。


+ o) f) n& f4 s

   采集电压 = Vref * ADC_DR / 4096;

" }7 C0 V6 k& j2 c, p+ H) W

   Vref:参考电压


) F  D. [( b, I

   ADC_DR:读取到ADC数据寄存器的值


  V; F9 a/ R& S( Y" R7 p0 B" g

8 y7 m$ s3 @+ S9 p4 g/ x

   由于寄存器是32位的,在配置的时候分左对齐和右对齐,一般我们使用右对齐,也就是对低12位数据为有效数据。

  V% J# A3 N( H1 ]: {9 c+ p

   2.5.2 转换模式

3 v6 O" t  G/ G) m% i3 C/ k7 Q

   A.单次和连续转换

! i2 ?+ v( }1 m4 p

   单次:单通道单次转换、多通道单次(分多次)转换;


9 J* T* y: w1 n$ g) Y. h+ u

   连续:单通道连续转换、多通道连续(循环)转换;

# n( W$ c# H0 x6 j0 X

   B.双ADC模式

; L2 c9 X4 l' [$ P6 D0 u: g

   也就是使用到了两个ADC,比如:ADC1和ADC2同时使用也就是双ADC模式。在该模式下可以配置为如下一些模式:同步规则模式、同步注入模式、独立模式等。


, Y& }  m9 x$ v& [# c# b0 @1 _2 ]


, c- [) I! u! r" M

     2.5.3 引脚配置


7 j' `0 U7 f) |6 F' ~

20170827172512722.png

0 z/ R9 @; W9 u4 A, L! Y

     2.5.4 ADC 配置

; ^' G9 ^+ N' z* Y/ P

20170827172911002.png


% q3 L- n6 `5 f1 ^7 B3 z

    A.初始化基本参数:

; v' q6 l# j, n  n1 V# O- ^3 p

    DMA_PeripheralBaseAddr = ADC1_DR_Address;


5 s4 ?2 Q: Z0 j) C* _# |- K

        #define ADC1_DR_Address    ((u32)0x40012400+0x4c)

        #define ADC1_BUF_SIZE       2

        #define TOTAL_CONVERT_CH_NUM  2


2 K) c! n2 V3 j3 Q' ]& Z

        vu16 ADC_Buf[2];


5 Q/ K# u. g6 p0 Q, i

    其中 ADC1_DR_Address 可从数据手册中查得

* U, h$ ~# e) X0 O, `" r

20170827175202411.png

5 H6 w+ s  @5 j5 J! e3 y

20170827175222394.png

* [3 U5 o% {# v

    第一个参数 DMA_PeripheralBaseAddr 用来设置 DMA 传输的外设基地址,比如要进行ADC采集,那么外设基地址 ADC1 数据存储器 ADC1->DR 的地址,表示方法为 (u32) & ADC1->DR,当然也可以通过数据手册直接算出外设的地址。

    第二个参数 DMA_MemoryBaseAddr 为内存基地址,也就是我们存放DMA传输数据的内存地址 = (u32)ADC_Buf。

    第三个参数 DMA_DIR 设置数据传输方向,决定是从外设读取数据到内存还送从内存读取数据发送到外设,也就是外设是源地还是目的地,这里我们设置为从外设地址读取数据,所以外设是源地了,所以选择值为DMA_DIR_PeripheralSRC。

    第四个参数 DMA_BufferSize 设置一次传输数据量的大小,我们需要采集两个通道的数据 所以设置为 ADC1_BUF_SIZE

    第五个参数 DMA_PeripheralInc 设置传输数据的时候外设地址是不变还是递增。设置为DMA_PeripheralInc_Disable;

    第六个参数 DMA_MemoryInc 设置传输数据时候内存地址是否递增,由于我们是多通道采集,因此需要递增

    第七个参数 DMA_PeripheralDataSize 用来设置外设的的数据长度是为字节传输(8bits),半字传输(16bits)还是字传输(32bits),这里我们是 16 位半字传输,所以值设置为 DMA_PeripheralDataSize_HalfWord

    第八个参数 DMA_MemoryDataSize 是用来设置内存的数据长度,同样设置为半字传输 DMA_PeripheralDataSize_HalfWord。

    第九个参数 DMA_Mode用来设置DMA模式是否循环采集。

    第十个参数是设置 DMA 通道的优先级,有低,中,高,超高三种模式,这里我们设置优先级别为高级,所以值为DMA_Priority_High。因为开启多个通道,这个值非常重要。

    第十一个参数 DMA_M2M 设置是否存储到存储器模式传输设置为 DMA_M2M_Disable。


; T$ V: I* D0 p8 L* ^/ k

    工作模式:ADC_Mode = ADC_Mode_Independent;


7 @% H+ @8 h4 h0 ^7 g" q

    总共有10种,主要都是针对双ADC下使用。针对初学者这里不多描述,感兴趣的朋友可以先自行研究一下各个模式的使用。


$ A9 Z, S1 p* H; b4 n! ^" }

% O3 X2 R4 @. @6 L1 a

    浏览模式:ADC_ScanConvMode = ENABLE;


3 l4 |5 e$ g0 i

    主要是针对多条通道而言,也就是说你是否有多条通道。


. i# D* j+ ~  ?$ B9 ]8 R

    多通道:ENABLE;


8 }( v& c0 N9 B3 b; p$ y+ c

    单通道:DISABLE;


) ?! `, u; n! |- O% G


' ~, W- u$ H3 z- Y0 e

    转换模式:ADC_ContinuousConvMode =ENABLE;


& O7 a9 [8 u: q  U( @* x( e  Z

    这里是配置是否需要连续转换。

/ y. _9 f6 ]0 a$ H

    连续转换ENABLE:也就是只需要启动(触发)转换一次,后面就不用再次启动(触发)就可以连续工作了。

. g; b5 i( T$ l7 d


" l( r; M3 a* q$ s8 r

    单次转换DISABLE:也就是根据一次转换完后需要再次启动(触发)才能工作。

0 Z- @, b  o( ^1 `  d( v. d- m- o/ ^


# \$ |$ h% m) J- M

    触发方式:ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;


; C+ F( `' R: D( h" _  o

    触发方式也就是使用什么方法触发ADC转换。哟定时器、外部触发、软件触发,一般常用软件触发。这里有很多种触发方式,详情可以参考其参数。

7 ?1 W; k' g- l# c: {0 U" V8 ]; ]& @


7 `1 Q9 @) I: Y9 Y9 p8 h# a) j

    对其方式:ADC_DataAlign = ADC_DataAlign_Right;

* |4 h5 q: b9 @  L& j" ?2 B: ^

    右对齐:低12位数据为有效位(常用);

- i/ u3 E- Y5 ^! ?. `( ?$ d

    左对齐:高12为数据为有效位;

& N) j# I( P( e& z


% g4 N& k2 \& ?: o- e

    通道数:ADC_NbrOfChannel =TOTAL_CONVERT_CH_NUM;

7 H8 K( b1 s0 R6 b, J

    这个参数比较简单,我们定义工作的通道数量。

1 ~3 K6 B7 e% J4 ^2 @& o1 R) O


/ u$ K, E' `4 I4 [, n/ m+ j

    B.设置规则组通道:


0 Y$ l8 Q4 \) D9 m. R+ V

    ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_55Cycles5);

( ^9 w3 U, Z- _, ^

    ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_239Cycles5);


4 k7 ?$ h2 Q$ |7 ]) I7 ^

    我们定义通道12的转换顺序为第1、通道16的转换顺序为第2;


# [! t( M4 O3 H2 }# A

    至于为什么 ADC_Channel_16 的采集周期要设置为 ADC_SampleTime_239Cycles5,是因为 STM32 的内部温度传感器要求的,现在 ADC1 的时钟源为 APB2 时钟分枝 8 分频,即 72MHz/8 = 9MHz。而要求采样周期 ≥ 17.1us, 所以 17.1 * 9 = 153.9,而最接近的也就是 ADC_SampleTime_239Cycles5

  Z0 K+ q# P) I2 l+ r

20170827173635398.png


3 {- j) A( m( P# i3 Q/ m; F9 c9 H

     2.5.4 读取采集结果


" Y0 b9 w' _; n! M

20170827181215133.png


' j7 Y; F/ a7 M8 n

转载自:xqhrs232

0 Y1 m$ `" b8 L" o2 |
2 b; ^! {5 Q3 p8 R5 g
收藏 评论0 发布时间:2023-1-6 16:55

举报

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