我们来看看STM32之DAC的Resume(简历简介): ● 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 ' [* N! s, W8 E% X# u( W
该使能信号只使能了模拟部分,数字接口部分由DACEN@RCC_APB1ENR控制WAKEUP- ]$ X' u/ }6 q# E7 ^ z" i
经过t WAKEUP时间后DAC通道准备就绪
. q. O, t0 I9 m- t | DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)& v Q; U% N% t; \& Y0 y+ `, l
输出通道上集成可配置的输出缓冲,以减小自身的输出阻抗; V5 s" q6 F6 T; J; l
使能控制:BOFF1@DAC_CR 2、输出通道上的缓冲: 通道内嵌输出缓冲以增加驱动能力 外部负载较大时,无需增加外部放大器 可使能或禁止该缓冲 外部有大负载,且缓冲禁止时,输出电压可能达不到预期 介绍两张图片:大家可以对比对比下,在这就不细讲了、 3、DAC的转换过程: 用户写入DAC_DHRx的值,自动或者在外部触发条件下经过一段时间后,传输到DAC_DORx;再经过一段固定时间tSETTLING,在外部引脚输出转换后的模拟信号(电压)。 (1)对DAC_DHRx的写操作
" x) E: H0 O7 `$ s8 x+ f (2)数据从DHRx到DORx的搬移
2 ]: H7 Q* \+ `" k t (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,所以这几位就不用设置,默认为0! X" g, p* M2 C3 T, [/ \7 i; p
BOFF1:关闭DAC通道1输出缓存 (DAC channel1 output buffer disable)我们关闭输出缓冲 故设置为1 EN1:DAC通道1使能 (DAC channel1 enable)我们要使能DAC通道、故设置为1 至此,我们已经设置了以上寄存器,我们就可以操作DAC了,但是我们并不是通过寄存器操作的、在这里摆出寄存器的设置,是为了大家有一个更好的了解,那我们打开"stm32f10x_dac.h" 可以看到: - typedef struct f* n, [, {0 ^* p* f( @. i
- {
, L1 N. i: o/ D# ]$ ]) x - uint32_t DAC_Trigger; /*!< Specifies the external trigger for the selected DAC channel.设置是否使用触发功能
& A7 T j- O% W/ a# b/ x - This parameter can be a value of @ref DAC_trigger_selection */
' ~$ N" U6 f3 B% t" f" `7 P
( I4 b1 J" j: b- \$ y- uint32_t DAC_WaveGeneration; /*!< Specifies whether DAC channel noise waves or triangle waves设置是否使用波形发生" Q7 k( i9 S& l& x' d' ]3 f1 \) O
- are generated, or whether no wave is generated.6 T) o9 b% W# @
- This parameter can be a value of @ref DAC_wave_generation */! Z' }4 x% r/ x3 c/ D
1 e4 Y3 h/ z( J( d0 u( w( _- a- uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or设置屏蔽/幅值选择器" l1 ~5 I' `& {4 t5 R5 v
- the maximum amplitude triangle generation for the DAC channel. . N8 [- Q, |& O
- This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */
0 [. ]: T* X# j' l" Q - ( F. N* ?. e8 l# v5 l2 [1 ?
- uint32_t DAC_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled.设置输出缓存控制位
复制代码
( i, I! {' R& J: N1 h8 ~3 @, A6 u
) n: P: G! M8 F6 F1 F) Q 根据以上说明,具体的设置请看代码、、 那好、、现在我们来看看具体的步骤: 1、使能DAC的时钟和GPIOA的时钟,并配置GPIOA 2、设置DAC的工作模式等功能 3、使能DAC通道 4、设置DAC的输出值 - void Dac1_Init(void)
' |5 k1 q D5 _. V8 K: _ - {
# `9 J# c& J) P& j+ F, T- g* S - DAC_InitTypeDef DAC_InitStructure;
/ ]8 N* O2 f" g) z4 A; |% z* P2 m/ _: g9 [ - GPIO_InitTypeDef GPIO_InitStructure;4 {' i& n; B2 B e; M4 B3 ^0 H4 p
3 U3 O j5 M7 m; o$ V4 [. R- /* Enable peripheral clocks ------------------------------------------------*/- p& n! d! \' _! [1 g% F
- /* GPIOA Periph clock enable */0 ~+ ~( ?7 O: Q5 K
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);- v6 C, B- B" z* G# h
- /* DAC Periph clock enable */
9 [) t6 L8 D1 H! p- E* I* S- M- v - RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
- z9 r- U$ F& s -
' W9 p7 ^3 U2 ]5 E M5 g2 [$ y - /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
: g( W- C. `2 q5 y9 P - connected to the DAC converter. In order to avoid parasitic consumption,
7 \" t0 r. M- j - the GPIO pin should be configured in analog */
/ Q* m" Z* j' r - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
' r L5 E2 G% w+ x2 ]- C - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;# M& g) F3 N0 A& ?! g
- GPIO_Init(GPIOA, &GPIO_InitStructure);. {9 X V% k# s& ]* j
- GPIO_SetBits(GPIOA,GPIO_Pin_4);& n2 h( G* W% Q" M. A
- /* DAC channel1 Configuration */) ?* ~( t2 u( U8 Y
- DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;: l+ T+ I' d) ?2 Y: @* C
- DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;; K1 R7 H, [9 f4 _
- DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;" i: T5 L; g$ G& E9 q: H
- DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
4 R+ K& ]1 |$ v( _. D+ H - DAC_Init(DAC_Channel_1, &DAC_InitStructure);
. l# X) S0 K6 W - # P8 C. X2 H/ F' b5 Q; A
- /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is
* U2 p; D X; k, Q+ c4 Z( j - automatically connected to the DAC converter. */
5 A3 e) x# j- \0 _0 ]3 N$ Y/ \% R - DAC_Cmd(DAC_Channel_1, ENABLE);
: O& {8 w1 g' G: l! \# E - 3 U- Q+ V! p; g. p. n, N
- /* Set DAC Channel1 DHR12L register *初始化/: s9 J- O. }! x' M8 D5 _
- DAC_SetChannel1Data(DAC_Align_12b_R, 0);8 c5 c4 |/ p) K, w( l3 a0 c
Q0 G' c" L; q; y- M+ ?, b7 R- }
. u' a6 c( }' _9 U5 m" f - //设置DAC通道的值我们可以通过按键 例如/ J9 b; [( \( V! @. B3 g( ~
- if(按键按下)
, f. }# Q. K1 q* }6 N - {' Y/ {1 W& E! F" T
- delay_ms(10);
, A, x( I9 W9 l7 R - & ~5 e3 n' g0 K! M- s; ?5 Z$ S
- DAC_SetChannel1Data(DAC_Align_12b_R, a += 200);
- B) r5 A' b: _: @1 Q" j: m& ]# h - if(a>4000)
! j: G( {" G$ {: U3 g5 c1 y - {
8 W0 G; O; Y% |7 W t - a = 0;
" f& W# }, d' d+ O - }
* j8 }+ E! }. R0 T% \ - }
- B' i- y" k4 ^# k+ |2 I* Q - ,或者由ADC转换后的值,给DAC采集
* I( t/ ]. I8 w/ m- O8 Q - adcx=DAC_GetDataOutputValue(DAC_Channel_1);//通过此函数我们可以读取设置DAC通道里的值也就是DOR里的数(0~4095); X" x9 Y0 o' N" p6 w
- DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)//根据此公式就可以计算出模拟输出电压、、/ s c$ {4 q( ?+ c8 N& `& Y2 m
- 此模拟电压又可以被ADC采集,从而输出(0~4095),你可以把两者结合起来,通过一定的编程,通过串口发送到窗口,看你设置的值和经ADC转换的值(0~4095)是否相等( f3 n/ w' Z% Q) S4 A S/ Q( s
- ( s" @, A4 a0 w5 A6 j
- PS:此步骤也可以在官方的例程里找到步骤哈、、
复制代码 + O |7 \1 Y) g! p$ V' l* Q
! c. j" _6 e5 S* j( |
, X% j( a( _9 H
* R( N) O; e' {- p! k0 p3 S |