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

【经验分享】STM32之DAC君

[复制链接]
STMCU小助手 发布时间:2022-1-14 22:38
我们来看看STM32之DAC的Resume(简历简介):
101534479485393.png
   ● 2个DAC转换器:每个转换器对应1个输出通道
   ● 8位或者12位单调输出
   ● 12位模式下数据左对齐或者右对齐
   ● 同步更新功能
   ● 噪声波形生成
   ● 三角波形生成
   ● 双DAC通道同时或者分别转换
   ● 每个通道都有DMA功能
   ● 外部触发转换
   ● 输入参考电压VREF+
   哇、、哇、、哇、、好多特征呀、、还记得上篇博客中ADC也有很多功能吗?在这里,我觉得,因为其功能多、所以其复杂、、这也没什么奇怪的哈、、
   那我们今天要干嘛呢?DAC顾名思义,输入量是D,也就是D、、而输出量是A、也顾名思义、当然、对于聪明的你们来说D A代表哪个英文单词和普通话意思是知道的、
    由上图可以清晰的看出,DAC的输出是受DORX寄存器直接控制的,而用户的写的数据是写在DHRX寄存器里的、说明我们不能直接操控DORX,而要通过DORX间接操作DORX,从而实现对DAC的输出、
    今天我们是采用DAC的通道1,采用12位的右对齐方式,对于对齐方式,大家翻开中文参考手册可以看到:
       ● 单DAC通道x,有3种情况:
       ─ 8位数据右对齐:用户须将数据写入寄存器DAC_DHR8Rx[7:0]位(实际是存入寄存器DHRx[11:4]位)
       ─ 12位数据左对齐:用户须将数据写入寄存器DAC_DHR12Lx[15:4]位(实际是存入寄存器DHRx[11:0]位)
       ─ 12位数据右对齐:用户须将数据写入寄存器DAC_DHR12Rx[11:0]位(实际是存入寄存器DHRx[11:0]位)
       根据对DAC_DHRyyyx寄存器的操作,经过相应的移位后,写入的数据被转存到DHRx寄存器中(DHRx是内部的数据保存寄存器x)。随后,DHRx寄存器的内容或被自动地传送到DORx寄存器,或通过软件触发或外部事件触发被传送到DORx寄存器。(这段话也就是对上张图片的描述)
       接下来我们看看
      1、输入输出使能:
      通道使能控制:EN1@DAC_CR
      一旦通道使能,输出引脚PA.4就被自动连到模拟转换器的输出
      使能通道之前,PA.4要配置成模拟模式AIN
   4 q) X3 v9 d) X, D" W( z
      该使能信号只使能了模拟部分,数字接口部分由DACEN@RCC_APB1ENR控制WAKEUP
9 L" p% l* V! }: ~      经过t WAKEUP时间后DAC通道准备就绪
! X4 d/ B% W. D6 }$ ?' Z      DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)
# N/ R1 n% `3 V) |6 ?      输出通道上集成可配置的输出缓冲,以减小自身的输出阻抗
3 f; T9 q7 D, M# \' }  \7 X7 B8 T* P      使能控制:BOFF1@DAC_CR
     2、输出通道上的缓冲:
      通道内嵌输出缓冲以增加驱动能力     
      外部负载较大时,无需增加外部放大器
      可使能或禁止该缓冲
      外部有大负载,且缓冲禁止时,输出电压可能达不到预期
      介绍两张图片:大家可以对比对比下,在这就不细讲了、
101606335429495.png   
101606421671231.png
3、DAC的转换过程:
    用户写入DAC_DHRx的值,自动或者在外部触发条件下经过一段时间后,传输到DAC_DORx;再经过一段固定时间tSETTLING,在外部引脚输出转换后的模拟信号(电压)。
        (1)对DAC_DHRx的写操作7 R9 _8 V( A" |% }8 y/ u1 e
      (2)数据从DHRx到DORx的搬移
0 A8 T9 c! z8 x+ i% t) S. H- F      (3)输出电压信号到外部引脚
我们来看看寄存器DAC控制寄存器(DAC_CR)
     DMAEN1:DAC通道1 DMA使能 (DAC channel1 DMA enable),我们不使用DMA,故设置为0
     MAMP1[3:0]:DAC通道1屏蔽/幅值选择器 (DAC channel1 mask/amplitude selector)我们没有用到 故这几位也设置为0
     WAVE1[1:0]:DAC通道1噪声/三角波生成使能 (DAC channel1 noise/triangle wave generation enable)我们也没用到 故也设置为0
     TEN1:DAC通道1触发使能 (DAC channel1 trigger enable)我们不用触发,所以设置为0
     TSEL1[2:0]:DAC通道1触发选择 (DAC channel1 trigger selection)注意:该位只能在TEN1= 1(DAC通道1触发使能)时设置。我们TEN1设为0,所以这几位就不用设置,默认为00 \+ T; u$ m, r- M) ~* B
     BOFF1:关闭DAC通道1输出缓存 (DAC channel1 output buffer disable)我们关闭输出缓冲 故设置为1
     EN1:DAC通道1使能 (DAC channel1 enable)我们要使能DAC通道、故设置为1
    至此,我们已经设置了以上寄存器,我们就可以操作DAC了,但是我们并不是通过寄存器操作的、在这里摆出寄存器的设置,是为了大家有一个更好的了解,那我们打开"stm32f10x_dac.h"
     可以看到:
  1. typedef struct! A; R# w6 a- ]# D4 |9 n: o1 |
  2. {7 h, y& n+ R% R1 `" g) W0 G* _, O
  3.   uint32_t DAC_Trigger;                      /*!< Specifies the external trigger for the selected DAC channel.设置是否使用触发功能& D9 H5 ?" h' Z! g: T: B. M
  4.                                                   This parameter can be a value of @ref DAC_trigger_selection */0 G7 \' _" [2 S, \% k

  5. 5 H8 _2 G& H& A
  6.   uint32_t DAC_WaveGeneration;               /*!< Specifies whether DAC channel noise waves or triangle waves设置是否使用波形发生
    $ w# N. v7 G3 q5 w+ G
  7.                                                   are generated, or whether no wave is generated.+ X) `2 n/ ?! v  r+ [8 h' l
  8.                                                   This parameter can be a value of @ref DAC_wave_generation */0 H$ Q$ E$ l& ~/ p% G" l. Y/ y

  9. / @; d8 q3 Y3 U9 c# A& T+ O% o( a
  10.   uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or设置屏蔽/幅值选择器
    . v' I/ I  y/ x2 d
  11.                                                   the maximum amplitude triangle generation for the DAC channel. & [: o' ?( |+ g0 @1 w, s
  12.                                                   This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */5 f. F- E; A$ O6 e

  13. 6 ]- v1 J& X- z7 D$ Y% W# O0 R
  14.   uint32_t DAC_OutputBuffer;                 /*!< Specifies whether the DAC channel output buffer is enabled or disabled.设置输出缓存控制位
复制代码
. T1 b- f$ Y) p- x

; X; e+ z/ I: r5 o
     根据以上说明,具体的设置请看代码、、
   那好、、现在我们来看看具体的步骤:
  1、使能DAC的时钟和GPIOA的时钟,并配置GPIOA
  2、设置DAC的工作模式等功能
  3、使能DAC通道
  4、设置DAC的输出值
  1. void Dac1_Init(void)
    $ B2 d5 m0 m" _1 D' R
  2. {3 t% b' Q( M$ m, S! X+ f2 v# `
  3.    DAC_InitTypeDef  DAC_InitStructure;' Q% K8 A+ N- s$ q$ i/ R
  4.      GPIO_InitTypeDef GPIO_InitStructure;  U* |) Q* \* b8 ^4 `* q2 V  v
  5. - q7 J9 E8 y6 I% G( X
  6.     /* Enable peripheral clocks ------------------------------------------------*/$ i! z! M* P1 K0 I
  7.   /* GPIOA Periph clock enable */6 \+ P, S1 P( Q; X# `4 ~
  8.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    8 X* p+ u) p0 P- T7 V7 b
  9.   /* DAC Periph clock enable */
    1 `$ \$ H: ]6 @8 P' l( z% C
  10.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);- s9 K; }2 {6 m; q7 m- j. i
  11.    
    0 Q+ {+ F* `2 W, s! ?) A
  12.   /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
    ' Z9 k0 N3 ~7 K" {- G! h* {
  13.      connected to the DAC converter. In order to avoid parasitic consumption,
    9 i& q6 l8 H5 X& A% O5 [
  14.      the GPIO pin should be configured in analog */5 f3 S7 ?: G" b
  15.   GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4;* b! q2 F- F( w. X+ P& X* i7 E1 l4 I
  16.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;. n+ J) [( j$ R
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);
    8 ]6 g  p- M9 f* g& `
  18.     GPIO_SetBits(GPIOA,GPIO_Pin_4);+ M# \5 m: G. f
  19.      /* DAC channel1 Configuration *// ^, x# t* f) x/ k: m# z$ c) g
  20.   DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;2 J$ ^4 e5 o  z( N  W9 t8 ~) Y3 D
  21.   DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;: N, D9 W/ A& A: |
  22.   DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
    $ a) @, a# M4 `8 ]$ h
  23.   DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;+ ?# @8 _. B" _8 Y
  24.   DAC_Init(DAC_Channel_1, &DAC_InitStructure);
    + Y0 T7 w- o  j) u
  25.     5 f. t" I2 @, R0 m
  26.   /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is ; d1 @" A  o; s- `
  27.      automatically connected to the DAC converter. */
    ) I) z& R0 w0 ^: t  n4 h
  28.   DAC_Cmd(DAC_Channel_1, ENABLE);$ d* n, l  i3 D* t# Q, ~$ w
  29.    
      n3 `, L. ~6 g" @0 p; @& d* {( l
  30.       /* Set DAC Channel1 DHR12L register *初始化/  X8 Z5 t& n9 h  j. y& V
  31.   DAC_SetChannel1Data(DAC_Align_12b_R, 0);" `( u, C+ u6 P' W2 Q9 S

  32. 8 O: @1 k" V* y0 g; p) k
  33. }2 {/ [# S5 g; j% o
  34. //设置DAC通道的值我们可以通过按键   例如+ }: ?6 I8 Y& j+ d6 b, f# W1 N
  35. if(按键按下)1 {9 d, C/ k+ N  X5 ?% K2 Z
  36. {
    * A: O! [6 d" ]- S/ [  h
  37.    delay_ms(10);% s+ [# d) \9 u7 Q
  38. - u. C  L) N) F6 _. H! h" i: f
  39. DAC_SetChannel1Data(DAC_Align_12b_R, a += 200);
    4 L, p2 h) ~0 S) |- C
  40.   if(a>4000)
    8 E! ^  J' v" ~( i/ R! O
  41. {
    ; X+ k7 z3 S- o( ^! V( [# |; R
  42. a = 0;
      K1 |7 a2 e3 H4 v5 K/ p
  43. }3 i4 @: X5 Z' @/ {
  44. }
    6 I5 m6 V& j3 L) |& x( y9 {+ H
  45. ,或者由ADC转换后的值,给DAC采集. k  D; U8 {0 O- I' i- ~6 v& I7 x
  46.   adcx=DAC_GetDataOutputValue(DAC_Channel_1);//通过此函数我们可以读取设置DAC通道里的值也就是DOR里的数(0~4095)" [+ n/ @" g& H$ T2 b8 G& ]3 L. Y
  47.   DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)//根据此公式就可以计算出模拟输出电压、、
    0 \2 U9 T6 u+ m5 R0 n
  48. 此模拟电压又可以被ADC采集,从而输出(0~4095),你可以把两者结合起来,通过一定的编程,通过串口发送到窗口,看你设置的值和经ADC转换的值(0~4095)是否相等; e) m2 g3 F' f: b; \

  49. 6 ~6 e7 Y  z1 Y2 W2 _
  50. PS:此步骤也可以在官方的例程里找到步骤哈、、
复制代码

7 ~6 Z4 l+ x/ `; @! l, x2 @. v1 o0 N; c( M. T7 h( a2 `
+ `" y: w9 C# f. O2 a
4 T8 B! l/ h6 ^8 d- z: G/ O# F) V1 }
收藏 评论0 发布时间:2022-1-14 22:38

举报

0个回答

所属标签

相似技术帖

官网相关资源

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