我们来看看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 
4 ^5 p, Z) k5 I$ t! P8 i" [1 q+ u 该使能信号只使能了模拟部分,数字接口部分由DACEN@RCC_APB1ENR控制WAKEUP* |. u0 z M3 y+ N$ S
经过t WAKEUP时间后DAC通道准备就绪
! j! P/ a# P: h& l9 @ DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)
J, A: V6 O& {0 S2 r 输出通道上集成可配置的输出缓冲,以减小自身的输出阻抗
. ~# W [) m5 w& d% J 使能控制:BOFF1@DAC_CR 2、输出通道上的缓冲: 通道内嵌输出缓冲以增加驱动能力 外部负载较大时,无需增加外部放大器 可使能或禁止该缓冲 外部有大负载,且缓冲禁止时,输出电压可能达不到预期 介绍两张图片:大家可以对比对比下,在这就不细讲了、 3、DAC的转换过程: 用户写入DAC_DHRx的值,自动或者在外部触发条件下经过一段时间后,传输到DAC_DORx;再经过一段固定时间tSETTLING,在外部引脚输出转换后的模拟信号(电压)。 (1)对DAC_DHRx的写操作
0 m* N# h; F% _6 w, _+ i8 ] (2)数据从DHRx到DORx的搬移 n' p# `& [% t+ o* G$ J% S
(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
% D$ l+ ]0 h( X u% K0 o BOFF1:关闭DAC通道1输出缓存 (DAC channel1 output buffer disable)我们关闭输出缓冲 故设置为1 EN1:DAC通道1使能 (DAC channel1 enable)我们要使能DAC通道、故设置为1 至此,我们已经设置了以上寄存器,我们就可以操作DAC了,但是我们并不是通过寄存器操作的、在这里摆出寄存器的设置,是为了大家有一个更好的了解,那我们打开"stm32f10x_dac.h" 可以看到: - typedef struct
6 n5 ~9 w6 u ]0 R+ s$ e - {/ q+ R9 m, m1 i4 W4 k3 p5 V
- uint32_t DAC_Trigger; /*!< Specifies the external trigger for the selected DAC channel.设置是否使用触发功能& X7 ^! J0 ?% Z* J% ~
- This parameter can be a value of @ref DAC_trigger_selection */# y" r2 W+ r' x+ [% }! `
- 9 M1 y3 ?8 c, [
- uint32_t DAC_WaveGeneration; /*!< Specifies whether DAC channel noise waves or triangle waves设置是否使用波形发生
/ }' z& s7 b# i; o5 T - are generated, or whether no wave is generated.; V" W/ g9 S' K4 q4 D% k/ Q
- This parameter can be a value of @ref DAC_wave_generation */: @2 k1 [& a4 r* j
) V- t8 x; G" s; ]; N- uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or设置屏蔽/幅值选择器! d# l% F! C8 A+ ^
- the maximum amplitude triangle generation for the DAC channel.
: U7 j; \/ A+ p- x - This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */
" T2 k% Z6 M% F/ A+ h& [ - ; C3 B: E7 { j. P) e Y
- uint32_t DAC_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled.设置输出缓存控制位
复制代码
2 e" j* L2 W$ Q: h4 {! m& I0 F. j7 A1 H% Q( X/ {" R
根据以上说明,具体的设置请看代码、、 那好、、现在我们来看看具体的步骤: 1、使能DAC的时钟和GPIOA的时钟,并配置GPIOA 2、设置DAC的工作模式等功能 3、使能DAC通道 4、设置DAC的输出值 - void Dac1_Init(void)
, e6 U5 y C; r9 G9 g- p - {
! T, l% N9 R# e5 `, Y/ K; k - DAC_InitTypeDef DAC_InitStructure;
! v! a6 [ A- k* f B" N3 z - GPIO_InitTypeDef GPIO_InitStructure;6 z; j7 \5 T4 [+ u% D2 c
$ Y" y- c$ @0 a7 e+ b- D- /* Enable peripheral clocks ------------------------------------------------*/% Q u2 N& x* N8 [. Z
- /* GPIOA Periph clock enable */% ?' }& c. A; z6 _ R
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
' O' B: Y- U% Q. Z9 A' I! z - /* DAC Periph clock enable */
" A: W+ k: H9 |, x0 O D - RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
0 Q; h( I0 W* n" d - 2 |% P. z9 n ~( N
- /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
$ n, J" g4 `7 x+ p6 k4 g - connected to the DAC converter. In order to avoid parasitic consumption,
. i6 M5 R2 L* x - the GPIO pin should be configured in analog */& e0 p$ y# F9 W
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
/ F) A; W- c& r! e6 g1 `' t - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;3 X" _% i) U S5 e( J: ~1 _
- GPIO_Init(GPIOA, &GPIO_InitStructure);5 V$ \. x5 X0 U4 H5 Y
- GPIO_SetBits(GPIOA,GPIO_Pin_4);) }' A) O" F6 e2 W# w) D
- /* DAC channel1 Configuration */
: F& `+ v& c( A - DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
, r1 q2 O& t b, x+ j - DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;9 _- `; f( R. c: U! u1 a
- DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
2 V3 ^* |; ^- U% T2 I3 ~ - DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;+ Y% b( Y8 `) |/ t/ Z
- DAC_Init(DAC_Channel_1, &DAC_InitStructure);
7 y+ S: h: {! t; H -
& N) T' m+ C: g - /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is ; k, |( B4 ?1 s& v
- automatically connected to the DAC converter. */
' n$ B( S8 K6 W8 _, ^ - DAC_Cmd(DAC_Channel_1, ENABLE);& l: S2 A+ [6 e: i# v( N
-
4 G) ?. w* Z( r - /* Set DAC Channel1 DHR12L register *初始化/; k; S( P% u9 [9 Z$ e* L& t
- DAC_SetChannel1Data(DAC_Align_12b_R, 0);
+ V7 ~; x8 `( N
! ?9 r: U! ^ A3 e) }* p- O6 K: A) Q8 M9 c$ D- }
! u$ _- U) ]9 o# G - //设置DAC通道的值我们可以通过按键 例如
9 Z4 M; x9 {$ r7 Z M+ l - if(按键按下)# P: D$ K! z* J: K) p8 Z
- {+ l0 [% u' p# d$ N' f( j1 [
- delay_ms(10);6 j1 b3 S( o9 V" ?$ W
- # b _3 ~; A) w' H/ b. s. C
- DAC_SetChannel1Data(DAC_Align_12b_R, a += 200);( ^" {& b9 j: _, x
- if(a>4000)2 S1 F0 ]( M. f4 k* Y- A
- {
+ \& p# k) q; {) Z4 l/ l - a = 0;+ M7 I; P- ~8 U4 K; v4 W8 v( j
- }) J# F" G9 g& d$ r/ X& j
- }
9 o, c5 ]5 g; |$ }* H - ,或者由ADC转换后的值,给DAC采集: A6 C9 I# S& \, a5 t; ~2 B( B
- adcx=DAC_GetDataOutputValue(DAC_Channel_1);//通过此函数我们可以读取设置DAC通道里的值也就是DOR里的数(0~4095)
6 E2 \' b4 x, o$ |# @1 d/ Q# g - DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)//根据此公式就可以计算出模拟输出电压、、
$ v5 J, L" I8 ^& e d - 此模拟电压又可以被ADC采集,从而输出(0~4095),你可以把两者结合起来,通过一定的编程,通过串口发送到窗口,看你设置的值和经ADC转换的值(0~4095)是否相等; K3 H+ H8 t' {: x/ }; t6 n e
- * y/ Z( Q* `; o$ } V# ]6 ?1 b
- PS:此步骤也可以在官方的例程里找到步骤哈、、
复制代码 ; O" g; n8 Y& k
5 e' H' Y* T/ ]2 @; g, T; L
/ [3 N/ q' r7 }4 _: Y
s. z a9 }. ?/ _ |