我们来看看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 - x1 K% p# W$ w' x4 v, Z
该使能信号只使能了模拟部分,数字接口部分由DACEN@RCC_APB1ENR控制WAKEUP
- |5 q; J) E& C) O 经过t WAKEUP时间后DAC通道准备就绪
3 F3 a5 K9 M6 B9 D- |) A( y DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)
. g7 H6 R! p x 输出通道上集成可配置的输出缓冲,以减小自身的输出阻抗1 u4 n' ^1 z7 S& n5 _" Q
使能控制:BOFF1@DAC_CR 2、输出通道上的缓冲: 通道内嵌输出缓冲以增加驱动能力 外部负载较大时,无需增加外部放大器 可使能或禁止该缓冲 外部有大负载,且缓冲禁止时,输出电压可能达不到预期 介绍两张图片:大家可以对比对比下,在这就不细讲了、 3、DAC的转换过程: 用户写入DAC_DHRx的值,自动或者在外部触发条件下经过一段时间后,传输到DAC_DORx;再经过一段固定时间tSETTLING,在外部引脚输出转换后的模拟信号(电压)。 (1)对DAC_DHRx的写操作
5 M2 d0 S- K6 @ (2)数据从DHRx到DORx的搬移
3 [7 e$ ^# }- s; N (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
- t0 Q, F0 w& z! S+ y( Q. d2 J! y9 b BOFF1:关闭DAC通道1输出缓存 (DAC channel1 output buffer disable)我们关闭输出缓冲 故设置为1 EN1:DAC通道1使能 (DAC channel1 enable)我们要使能DAC通道、故设置为1 至此,我们已经设置了以上寄存器,我们就可以操作DAC了,但是我们并不是通过寄存器操作的、在这里摆出寄存器的设置,是为了大家有一个更好的了解,那我们打开"stm32f10x_dac.h" 可以看到: - typedef struct
4 x2 p0 c% b2 O; V! D- J( N - {) o1 j9 r6 H" d2 E
- uint32_t DAC_Trigger; /*!< Specifies the external trigger for the selected DAC channel.设置是否使用触发功能$ t8 {9 _" t6 ~5 s5 k% ?
- This parameter can be a value of @ref DAC_trigger_selection */2 H0 e/ z) b3 ], S7 @
- 3 y7 B$ l8 H: J! e* y/ @( m" `2 ~7 g
- uint32_t DAC_WaveGeneration; /*!< Specifies whether DAC channel noise waves or triangle waves设置是否使用波形发生
: z9 U5 |+ z" G - are generated, or whether no wave is generated.) G0 a( Z+ R$ g1 ]: @- F2 e$ u4 v- d
- This parameter can be a value of @ref DAC_wave_generation */! Y0 E p7 A: Q& y4 ?8 {; I
8 a0 f; s7 E5 w$ e( y- uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or设置屏蔽/幅值选择器, I8 ?; M7 w/ M9 k/ L% ?$ w
- the maximum amplitude triangle generation for the DAC channel.
A- W' n1 K$ ^, z5 ]) ? - This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */9 h" f, e/ h5 j o% V
9 C6 x! L. F0 R* m+ F) E9 S- s( \- uint32_t DAC_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled.设置输出缓存控制位
复制代码 $ [' a4 z0 u- x
& T' l0 [. L) I" U" W. X
根据以上说明,具体的设置请看代码、、 那好、、现在我们来看看具体的步骤: 1、使能DAC的时钟和GPIOA的时钟,并配置GPIOA 2、设置DAC的工作模式等功能 3、使能DAC通道 4、设置DAC的输出值 - void Dac1_Init(void)* N4 P* O& t& _, X/ y3 a, h: m
- {6 J z1 N, q4 x# a0 r
- DAC_InitTypeDef DAC_InitStructure;* B$ v( Z( s; |; A9 ^2 i0 [
- GPIO_InitTypeDef GPIO_InitStructure;% Z7 i+ E3 w; u. J) ^
& L) f) ^& W& p! ~- /* Enable peripheral clocks ------------------------------------------------*/
+ e9 {9 j3 }6 ~ ~" j: P( o2 o - /* GPIOA Periph clock enable */' c: c `0 v* g) Y# u3 K/ h6 J
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);! N) N0 f* K6 N- o5 F, z( L& \
- /* DAC Periph clock enable */
. L& U! g0 X0 I+ {: y& C* l# ~ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
x8 y4 ]8 A* p7 } - 0 R/ e& f6 R9 _6 `4 l# ~
- /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically ( [* q2 q' g$ q5 _
- connected to the DAC converter. In order to avoid parasitic consumption, - q m! q0 h. @$ n8 K8 O
- the GPIO pin should be configured in analog */
1 ~# M" f! I: t9 \5 [: ] - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;0 J9 k5 {2 K7 m( n+ [7 ]
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
7 b* r8 {6 v9 C& A - GPIO_Init(GPIOA, &GPIO_InitStructure);
9 x3 B9 R7 [7 H - GPIO_SetBits(GPIOA,GPIO_Pin_4);
+ b) p& B$ S. J/ C - /* DAC channel1 Configuration */
3 V1 O9 z% Z% ~8 {* Q - DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
2 h" m, t$ b1 U2 e6 I - DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;) z2 H* B9 Z7 w7 j
- DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
5 J# G- p7 H" F% y6 p5 k - DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
3 U* e0 `4 o8 t# W1 m! J' | - DAC_Init(DAC_Channel_1, &DAC_InitStructure); S. _! t- N' b& d
- ) C @9 m* P& ~+ [$ b4 C, r
- /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is
; e ?7 j/ X4 r# H. ^ - automatically connected to the DAC converter. */
* H( R! S1 G5 W+ M# U1 I$ t, B - DAC_Cmd(DAC_Channel_1, ENABLE);4 G6 F6 t0 d3 L% b5 t( m
- # X" u$ E/ _& S8 f% N6 j
- /* Set DAC Channel1 DHR12L register *初始化/# L! Z$ n3 Q* Y0 L6 j5 a
- DAC_SetChannel1Data(DAC_Align_12b_R, 0);$ ?" }, y5 N' }1 \. g' r
- 4 e, q# }4 [ W8 _+ K$ x6 L1 C
- }% D, H' u) Y* L9 i& S5 n d
- //设置DAC通道的值我们可以通过按键 例如
$ X! F+ \6 B Z! h! l - if(按键按下)1 Y9 x' Y6 B1 w! M, w# m9 Y
- {8 f' c B' C3 }
- delay_ms(10);# ]3 N$ x- t/ f/ d( z
) ^$ u% z6 \: f: A3 q$ `- DAC_SetChannel1Data(DAC_Align_12b_R, a += 200);7 Z5 B D1 r0 c- i
- if(a>4000), T3 o5 \( s/ f
- { A& Q: X5 s& d0 J
- a = 0;
4 ?! x# m) d# a! A: N - }
( Q$ @1 U/ `1 F5 C c - }
- A \* b, H: o5 ^ - ,或者由ADC转换后的值,给DAC采集
: i$ S2 w: k+ h) K8 M$ J - adcx=DAC_GetDataOutputValue(DAC_Channel_1);//通过此函数我们可以读取设置DAC通道里的值也就是DOR里的数(0~4095)
- v6 W5 j! u% Y8 j+ r2 A" [/ R; F - DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)//根据此公式就可以计算出模拟输出电压、、
. k2 j8 s2 j6 L% J/ b& g - 此模拟电压又可以被ADC采集,从而输出(0~4095),你可以把两者结合起来,通过一定的编程,通过串口发送到窗口,看你设置的值和经ADC转换的值(0~4095)是否相等
S0 P2 }& u1 o$ {# _& P, B N
4 e3 Y r4 l `5 f, X; f- E' n- PS:此步骤也可以在官方的例程里找到步骤哈、、
复制代码 9 `: C, W% A+ x, ` ]* s
$ m( w! E1 ~+ n8 O5 o( C/ r
8 Y, z& C$ S( o6 F- y, R5 A' E5 \; G0 b% ^6 H% `; ~$ F( Z: s
|