我们来看看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 3 }8 l2 r F/ t! u q
该使能信号只使能了模拟部分,数字接口部分由DACEN@RCC_APB1ENR控制WAKEUP
" x- E$ |; p" I* k 经过t WAKEUP时间后DAC通道准备就绪+ N$ r* Z: A0 h" {& B
DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)
$ V: f7 E5 H& q8 ]9 @7 p8 d$ o 输出通道上集成可配置的输出缓冲,以减小自身的输出阻抗7 g- K7 d. C! S1 W( |7 w
使能控制:BOFF1@DAC_CR 2、输出通道上的缓冲: 通道内嵌输出缓冲以增加驱动能力 外部负载较大时,无需增加外部放大器 可使能或禁止该缓冲 外部有大负载,且缓冲禁止时,输出电压可能达不到预期 介绍两张图片:大家可以对比对比下,在这就不细讲了、 3、DAC的转换过程: 用户写入DAC_DHRx的值,自动或者在外部触发条件下经过一段时间后,传输到DAC_DORx;再经过一段固定时间tSETTLING,在外部引脚输出转换后的模拟信号(电压)。 (1)对DAC_DHRx的写操作
! ]5 k4 _( L& z# p1 ^ (2)数据从DHRx到DORx的搬移
. n' ]) k5 C0 D( D" H. H* Y+ _ (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
; t# g- O# |5 z0 B5 v% P BOFF1:关闭DAC通道1输出缓存 (DAC channel1 output buffer disable)我们关闭输出缓冲 故设置为1 EN1:DAC通道1使能 (DAC channel1 enable)我们要使能DAC通道、故设置为1 至此,我们已经设置了以上寄存器,我们就可以操作DAC了,但是我们并不是通过寄存器操作的、在这里摆出寄存器的设置,是为了大家有一个更好的了解,那我们打开"stm32f10x_dac.h" 可以看到: - typedef struct9 a5 L: o- ^3 m1 {: _6 q
- {
. \7 }0 l1 S/ T, p - uint32_t DAC_Trigger; /*!< Specifies the external trigger for the selected DAC channel.设置是否使用触发功能
2 Y4 C- G, u O1 g# R2 W - This parameter can be a value of @ref DAC_trigger_selection */! U1 i- A* g }" V
- ; v/ h% s/ H5 Y6 C V6 p
- uint32_t DAC_WaveGeneration; /*!< Specifies whether DAC channel noise waves or triangle waves设置是否使用波形发生 t6 T. l4 i' f+ J0 |; }3 I% b
- are generated, or whether no wave is generated.2 E' k4 T) x4 I" `8 Y$ r: B
- This parameter can be a value of @ref DAC_wave_generation */& T, U3 `! v) f
) i; k5 i* Q) E: E0 K3 T" T/ c- uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or设置屏蔽/幅值选择器7 B5 E* p/ Y0 k8 d/ Y
- the maximum amplitude triangle generation for the DAC channel.
4 M' t" U9 R. M2 @0 l k - This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */
4 O5 R6 L; R2 c0 c# v- l( t - ( V! ^5 f4 P8 U: s1 V( q R x+ j
- uint32_t DAC_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled.设置输出缓存控制位
复制代码
; P$ L3 @% F/ p, I. t5 a- V3 ^& n% Q7 u# K2 C# h0 [
根据以上说明,具体的设置请看代码、、 那好、、现在我们来看看具体的步骤: 1、使能DAC的时钟和GPIOA的时钟,并配置GPIOA 2、设置DAC的工作模式等功能 3、使能DAC通道 4、设置DAC的输出值 - void Dac1_Init(void)
8 E1 z$ T% s- o A# a% E0 h - {5 p1 n) W5 ]& z9 m* n! \" Q
- DAC_InitTypeDef DAC_InitStructure;6 M" M' Z& Z8 i/ m
- GPIO_InitTypeDef GPIO_InitStructure;
0 j9 ]: M1 k& \3 d
8 V( Y) S# c' T) E- /* Enable peripheral clocks ------------------------------------------------*/. v( C% e8 p8 U2 C, }0 U
- /* GPIOA Periph clock enable *// w) U* b8 h2 l! ~4 U+ [
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/ ^. V/ D% T$ l - /* DAC Periph clock enable */8 u7 A% C% x1 R3 i- I( O
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);" M% g. W+ |4 y* m o# v( i
-
' U8 ?$ V5 _: Z8 A% I- V; b5 B - /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
& ^" a) e, m$ `9 u. ^: L4 e/ o u - connected to the DAC converter. In order to avoid parasitic consumption,
) W/ p+ `; z+ D/ q# G/ ` - the GPIO pin should be configured in analog */
: A& y/ i) `) p% f5 b) q - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;9 }+ ^( B$ O; c- }: a
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
! ]4 m0 f# p, M! ~: u$ E - GPIO_Init(GPIOA, &GPIO_InitStructure);( Q+ z1 }& X1 ]9 ]8 W
- GPIO_SetBits(GPIOA,GPIO_Pin_4);/ A7 ?1 x5 Q4 I" S
- /* DAC channel1 Configuration */
. v- v; m/ n2 k0 T - DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
4 c3 S# H9 e9 _6 o }, E - DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
" {- K; B0 _9 u2 z# v - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;$ c7 b8 x. e8 |% H9 c- K$ `
- DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;# U9 ^5 P, R8 e1 d5 Y2 ?3 P1 }3 S$ `
- DAC_Init(DAC_Channel_1, &DAC_InitStructure);
/ F6 X9 \$ t; ^; B+ ] - 9 C( m. p; }' |! u y8 w
- /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is
0 K$ z+ X, d4 i% Z5 c6 y3 F- A7 Z1 R - automatically connected to the DAC converter. */& `4 _ p6 b/ P; D6 q; s6 @ F
- DAC_Cmd(DAC_Channel_1, ENABLE);6 ~% c# a1 D( Q# _
-
# }- V4 x/ ]- z2 x: S - /* Set DAC Channel1 DHR12L register *初始化/5 N7 w# G. J! c5 N1 r; H! f. o! [1 ]
- DAC_SetChannel1Data(DAC_Align_12b_R, 0);; E8 J! p. n- N4 v9 y
( C% c" I9 V- U' r8 v' h9 d7 g8 x- }
1 h6 l+ y6 L2 e7 ?, t& [ - //设置DAC通道的值我们可以通过按键 例如; _& @+ d+ S( s+ t
- if(按键按下)
8 }' A6 s7 x+ \! t5 d! D - {
! _- I4 C# Y7 q% X) K - delay_ms(10);
E V8 X* Q- N. i) K! [( n
* U8 l4 H1 z$ F! g# D- DAC_SetChannel1Data(DAC_Align_12b_R, a += 200);- @& J! ]' a# _! g1 C, S
- if(a>4000) O& c! ^8 U3 c1 f4 x' t9 B
- {; R* E- r! Z1 F9 S: A; `* @
- a = 0;
( t4 R) t5 v) q7 \ v0 ] - }3 e: h7 n1 Q) `8 C
- }
, T$ Q9 P0 p w% p$ a/ {9 ?3 i1 M8 B - ,或者由ADC转换后的值,给DAC采集
% Q( g- l0 ^& ?; @( } - adcx=DAC_GetDataOutputValue(DAC_Channel_1);//通过此函数我们可以读取设置DAC通道里的值也就是DOR里的数(0~4095)
7 ]9 T6 P: h H" ^ - DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)//根据此公式就可以计算出模拟输出电压、、/ ~8 J- b; E+ u; e4 M
- 此模拟电压又可以被ADC采集,从而输出(0~4095),你可以把两者结合起来,通过一定的编程,通过串口发送到窗口,看你设置的值和经ADC转换的值(0~4095)是否相等
. j+ b1 s, L8 L8 Q1 n. }. B1 J
1 x& m! a o3 g. ?! O- PS:此步骤也可以在官方的例程里找到步骤哈、、
复制代码
4 S7 _* b; }% v u. n. @4 ~
- n" C2 r, o0 W6 d7 t1 j0 R' [; e3 ?& t% S) F% ] ^* n% N1 m' H
- |& Z& I0 @4 |9 o- l
|