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

NUCLEO-G071RB-DAC和ADC的简单应用

[复制链接]
电子星辰 发布时间:2019-1-14 04:17
本帖最后由 电子星辰 于 2019-1-14 17:27 编辑
9 N  m, Q* \- P# `2 @, z: ^: d! G
本文在NUCLEO-G071RB核心板平台上,使用CubeMX和HAL库,通过12位ADC,连续DMA采样和不连续转换,单通道(或双通道)采集,DAC连接外部引脚通过DMA输出的一个简易正弦波。最后通过NUCLEO自带的低功耗串口1打印采集到的一个电压。; B/ F5 _  Z& p3 O

0 g% K; E5 L0 |6 D一、Cube设置
- [. v6 h5 @7 L' j  W# ?9 A首先我是通过选择Board新建的工程,所以会有一个NUCLEO外设初始化的选择,可以省点力气。通过MCU新建也是一样的。/ O3 }9 A$ q5 _( P# n5 j+ l( ?) K
新建.JPG 初始化.JPG . w  t# q+ U/ Z- |  G' G
, i3 e0 s! t' j) b( K  J$ K
其次,RCC、SYS、LPUART都是默认的。1 O0 l+ ^0 c  d- b2 m: m0 X
RCC.JPG
7 T8 f7 t' c; c2 F6 ^, w用SWD下载的话记得勾选“Serial Wire”,要不下载之后就不能再下载了。不过这个板子有个复位跳线帽应该好整,出了问题可以复位下载试试。
6 j+ S: ~! V3 B) [! E SWD.JPG 8 ]6 D$ a3 u1 U, M6 H
LPUART1,异步模式自己改下常用参数就行了,“Data Direction”模式选择是我个人只需要发送。
' {- |* }  l6 C9 K LPUART.JPG
) E* [8 K0 o9 y# \% J) I
& _" c) y; }1 @& M7 f. c9 P  _然后是DAC和定时器。( b3 A  [# l" M& ^! @) X: ?( o
DAC输出简单点,选择仅连接外部引脚就行了,另一个连接外设的选项就是连比较器之类的。需要通过定时器做触发事件(基本定时器就够了)。1 G" W- B. z6 ]3 L: a# C& `
DAC.JPG 5 l# Y( W# O0 J+ N/ Q
DMA通道不用管,方向是内存到外设。选循环模式,到时候打开了就不用管。“Data Width”选1个Byte就够了,方便点,不用取高低位。9 N8 D8 k9 f* v
DAC-DMA.JPG ; f. P1 z( W1 c
定时器6是基本定时器,我只需要它一个计数触发的功能。, i* u5 j# e1 ]9 c! C' b: V
Prescaler是定时器预分频,定时器实际时钟频率为:主频/(Prescaler+1),
6 U. M; [* x( ~* u$ X, h0 dCounter Period是定时器周期,当定时器开始计数到Counter Period值并且重复计数寄存器(Repetition Counter)为0时更新定时器并生成对应事件和中断,
7 i- D' z# r% e" v5 v2 v最终定时器频率计算为: 主频/(Prescaler+1)/(Repetition Counter+1)/(Counter Period+1(也可能不需+1)),比如需要产生20ms周期定时,可以设置为:64MHz/(63+1)/(0+1)/(19999+1)=50Hz,即20ms周期。我现在设置16位定时器的最大数,64分频的话就是65.535ms。
& ]$ u9 Y9 Q8 f+ d1 @% m& F time.JPG & r: z* @+ ~5 |( t! w

  z( ?* d5 [. z+ z接着是ADC,我写了2个通道(但是只用了其中1个)。我没有选连续转换和DMA连续请求,所以在程序里还需要循环开启ADC转换。ScanConvMode扫描转换,是根据你的转换通道数自动设置的,转换序列中如果有超过一个通道需要转换的话,那么必须开启扫描模式,否则的话,时钟只转换第一个通道。
, U- S4 k; c. C+ _5 Q1 Q* Y0 s( g ADC1.JPG ADC2.JPG
* `/ w1 h( z2 |1 h. X+ B3 [% y! XDMA通道不用管,方向从外设到内存。选的半字“Half Word”,代码里还需对取的值取低12有效位(因为上面ADC参数我是右对齐)。! h8 ~0 f6 f& H" X3 p8 Z7 J. b
ADC-DMA.JPG
+ R$ Q7 l# H# w% R9 _: W" T0 n8 Q. J; V0 Z4 h

! D. i& x$ q$ j: V2 G( ?1 KHCLK改为64后直接回车,它会自动配置。
, Q+ F+ P" r& B% w  k 时钟.JPG . F2 l5 X' S: n+ ~' y1 M; r, F' J3 j7 i

/ W2 p# X' T: N  a最后是结果,一共6个值,0.04、0.66、1.33、1.98、2.63、3.27。符合我的预期。我的输出值是0x0,0x33,0x66,0x99,0xCC,0xFF。7 W4 d: d* \9 s, `0 I7 A' Q1 Z
串口显示.JPG 4 b) N7 S' u! j& W8 n4 Q4 M

7 L: X/ E, ?, n0 S# g4 @; c: `) `, M5 n1 r

% D% G! Q; L; O$ k* e  P
  1. /* USER CODE BEGIN PD */
    7 k2 ?# q% T" D7 `1 n& s
  2. #define ADC_SAMPLE 2//采样数( X2 U- O) Z9 g( b( o9 }( U
  3. /* USER CODE END PD */2 h: t" _: ~9 \

  4. / ]3 ~8 A9 o+ S4 p* v6 H' j, }! [
  5. /* USER CODE BEGIN PV */; d3 O! b7 r5 _3 |
  6. __IO uint16_t ADC_ConvertedData[ADC_SAMPLE]={0};//DMA取得的ADC值
    " h- j6 X# E! V. p# n/ z  c7 ^
  7. const uint8_t aEscalator8bit[6] = {0x0,0x33,0x66,0x99,0xCC,0xFF};//DAC输出量表
    6 O* w# _' L0 H& @4 u6 @' a0 A
  8. /* USER CODE END PV */0 B) R" t( v) ?/ L2 ?) C
  9. ; D$ b0 R6 T4 S* O9 D0 }0 z  F5 k
  10. /* Private function prototypes -----------------------------------------------*/; M, Y/ W; Z2 Z' S. S* O0 E3 H
  11. void SystemClock_Config(void);" D5 O- F6 `3 U, @+ o
  12. /* USER CODE BEGIN PFP */
    + Y5 N: p! n% ^& d
  13. int main(void)5 L+ t0 K& J# r/ V6 y
  14. {
    2 j& C. T$ R2 @2 _
  15.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */# E+ j" P0 a- P  I6 ^1 |. B
  16.   HAL_Init();# u! _* s! C$ i. j0 f
  17.   /* Configure the system clock */6 O  y3 ^0 ~1 T$ [5 {
  18.   SystemClock_Config();- F- P: L7 b. O2 }: K
  19.   /* Initialize all configured peripherals */' @" D* l3 `2 n2 j
  20.   MX_GPIO_Init();
    7 s( r: K: W7 v& _- E  B
  21.   MX_DMA_Init();
      k; i# M; X! T" d! g
  22.   MX_DAC1_Init();* G$ p# N' z% [
  23.   MX_TIM6_Init();
    2 F0 V* w1 @/ S2 o- t
  24.   MX_ADC1_Init();
      i2 n, B# C2 o, j& o$ F
  25.   MX_LPUART1_UART_Init();- B$ E7 Q, g8 G% s4 ~7 [9 j; i
  26.   /* USER CODE BEGIN 2 */
    : x  D/ E% l' N$ d+ u* s7 O
  27.         HAL_ADCEx_Calibration_Start(&hadc1);//ADC自校验
    0 v; }% j) p; e% d+ E7 ?
  28.         HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_ConvertedData,ADC_SAMPLE);//启动AD转换并使能DMA传输和中断。ADC_ConvertedData的两个元素都是通道0的值. C9 K$ x- z$ x* ^
  29.   HAL_TIM_Base_Start(&htim6);//开启定时器6进行触发- |! `3 U5 O8 d. u0 \
  30.         HAL_DAC_Start_DMA(&hdac1,DAC_CHANNEL_1,(uint32_t *)aEscalator8bit,6,DAC_ALIGN_8B_R);//启动DAC-DMA输出,循环输出6个8bit数        ! R! w0 h5 q6 D8 h6 `. S
  31.   /* USER CODE END 2 */
    & f. r+ X! \; ^' f* _8 |

  32. ( r3 o: I+ Z0 i6 ^9 P: F1 y
  33.   /* Infinite loop */. W5 y& A/ o1 D# V
  34.   /* USER CODE BEGIN WHILE *// Y" T. O/ `2 ?7 _8 n. k
  35.   while (1)" t# A: I/ ~8 i
  36.   {        
    ) ]6 r5 M0 L0 k% O# S/ u0 Q2 P
  37.                 printf("%.2f ",((ADC_ConvertedData[0] & 0xFFF)*(3.3/4096)));//串口不是重点,这个用法可能有隐患。取有效位和换算一起进行1 H4 g' m6 m* @* X
  38.                 HAL_ADC_Start(&hadc1);//因为是不连续转换,需重复开启# ^' ?& j- w8 F. N8 T
  39.     /* USER CODE END WHILE */
    1 E2 U" Y7 ^4 \. v$ m
  40. 4 b. c1 q9 A# L
  41.     /* USER CODE BEGIN 3 */
    : e' |, O, e% O
  42.   }
    4 ?2 \' G! R1 a8 ?- j9 I# V
  43.   /* USER CODE END 3 */3 h! F7 i+ s* F
  44. }
复制代码

' K; s: t0 a% l* P2 H
1 h- p0 g! U1 h6 m3 {3 B" b. m好了,文末放下资料。
( y$ G) W- z0 r8 M+ F2 @" W源代码和Cube工程: NUCLEO-G071_DACandADC.rar (7.98 MB, 下载次数: 1523)
收藏 评论7 发布时间:2019-1-14 04:17

举报

7个回答
STM1024 回答时间:2019-1-14 08:24:30
精度如何啊?
Kevin_G 回答时间:2019-1-14 09:25:55
DAC能输出0V和轨电压吗(带输出缓冲)?
电子星辰 回答时间:2019-1-14 17:28:41
stm1024 发表于 2019-1-14 08:24& \/ F. E" p9 i" M9 X
精度如何啊?

% ~9 {6 V2 v/ ]( |我家里的万用表很老了,精度我这测不了。不好说不好说
电子星辰 回答时间:2019-1-14 17:29:58
Kevin201707 发表于 2019-1-14 09:25
& z, M9 s4 u, U" D7 }: x) C: d! H* ]DAC能输出0V和轨电压吗(带输出缓冲)?

# j, `9 v" L3 vDAC输出来的是近似0V的值,比如说零点零几V。缓冲的话我是开的内部缓冲。
Kevin_G 回答时间:2019-1-15 09:51:17
STM32其他系列DAC输出可以达到轨电压,但是DAC驱动能力很弱,如果打开内部缓冲器,可以提升驱动能力,但是缓冲器输出无法达到轨电压(0V或VDDA)。
≯断了线的风筝≮ 回答时间:2019-8-13 20:22:48
请问是否遇到ADC不准,AD值会波动的情况,与实际值差了0.几v
阿拉蕾 回答时间:2019-10-17 13:27:45
很不错
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版