我们来看看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 2 p2 s; v# A6 |! p" s5 p/ R
该使能信号只使能了模拟部分,数字接口部分由DACEN@RCC_APB1ENR控制WAKEUP
- p0 _, c% W3 L 经过t WAKEUP时间后DAC通道准备就绪
+ c }! O5 w3 s& N DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)
: h, F! X% r4 h- y2 {. k 输出通道上集成可配置的输出缓冲,以减小自身的输出阻抗: L' v8 _7 ] T
使能控制:BOFF1@DAC_CR 2、输出通道上的缓冲: 通道内嵌输出缓冲以增加驱动能力 外部负载较大时,无需增加外部放大器 可使能或禁止该缓冲 外部有大负载,且缓冲禁止时,输出电压可能达不到预期 介绍两张图片:大家可以对比对比下,在这就不细讲了、 3、DAC的转换过程: 用户写入DAC_DHRx的值,自动或者在外部触发条件下经过一段时间后,传输到DAC_DORx;再经过一段固定时间tSETTLING,在外部引脚输出转换后的模拟信号(电压)。 (1)对DAC_DHRx的写操作
4 X; x# N( y( Y- p (2)数据从DHRx到DORx的搬移0 v& e0 ~: w0 K* @. Z
(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
( c5 D5 n: C% D8 S6 ^: F7 r5 e BOFF1:关闭DAC通道1输出缓存 (DAC channel1 output buffer disable)我们关闭输出缓冲 故设置为1 EN1:DAC通道1使能 (DAC channel1 enable)我们要使能DAC通道、故设置为1 至此,我们已经设置了以上寄存器,我们就可以操作DAC了,但是我们并不是通过寄存器操作的、在这里摆出寄存器的设置,是为了大家有一个更好的了解,那我们打开"stm32f10x_dac.h" 可以看到: - typedef struct) B! P2 r: p, \( Q N5 {
- {
1 C$ I" R) \4 l6 o( O+ t - uint32_t DAC_Trigger; /*!< Specifies the external trigger for the selected DAC channel.设置是否使用触发功能
- i0 c7 f( ^8 j; R - This parameter can be a value of @ref DAC_trigger_selection */0 E& T0 e/ {8 }8 N) n' j' W% `; l
- ) p1 W0 T0 f+ c r% h5 Q
- uint32_t DAC_WaveGeneration; /*!< Specifies whether DAC channel noise waves or triangle waves设置是否使用波形发生. r' f; l$ T5 E! T. a1 a9 f; A
- are generated, or whether no wave is generated.
/ F6 R3 X+ T3 u) ?) H6 D - This parameter can be a value of @ref DAC_wave_generation */% V! L4 ?, j( ?
- " y1 ^9 N% g8 W9 r! Y
- uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or设置屏蔽/幅值选择器0 t: w; A3 {- N6 E1 s
- the maximum amplitude triangle generation for the DAC channel.
, _/ k: j; t( W: i+ b7 P1 I8 |3 F- O" m - This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */ E7 E6 D4 p% G
+ m6 q% j3 ]$ D! m9 i; g- uint32_t DAC_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled.设置输出缓存控制位
复制代码 ( R+ D1 I4 O! Q
% o. i) j+ C5 w3 `6 ?& D 根据以上说明,具体的设置请看代码、、 那好、、现在我们来看看具体的步骤: 1、使能DAC的时钟和GPIOA的时钟,并配置GPIOA 2、设置DAC的工作模式等功能 3、使能DAC通道 4、设置DAC的输出值 - void Dac1_Init(void)) O0 u' f, ?/ n9 w; ] j7 B1 I
- {
, g8 {7 v* {& U - DAC_InitTypeDef DAC_InitStructure;
) m* Y! }* `1 N4 |% I/ z - GPIO_InitTypeDef GPIO_InitStructure;0 U' B6 _* @4 E7 t- ^
- 4 E3 u# Z* ]/ @
- /* Enable peripheral clocks ------------------------------------------------*/% v/ }# b/ b; a* \0 T. s$ r
- /* GPIOA Periph clock enable */! i, E# \& z8 N$ {0 e; S0 n4 v
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);3 ~* k0 }, t( m% q# S
- /* DAC Periph clock enable */
; G6 S# E/ V. h& l: N - RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);% x! }7 n# R1 Y. |# h" F" o' n
-
! a4 M5 x9 P5 S7 ~: c; ^3 Y - /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
1 e# B7 B% w/ O& G; Z - connected to the DAC converter. In order to avoid parasitic consumption, / \/ Y1 e( V2 }
- the GPIO pin should be configured in analog */
1 v; a' b" x4 h/ w- s& D2 X6 @2 T - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;9 B5 p3 p v1 O. P+ }
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
4 {2 i, p/ J2 S, U p! V$ Z - GPIO_Init(GPIOA, &GPIO_InitStructure);4 T! L/ N* v4 |: o& D
- GPIO_SetBits(GPIOA,GPIO_Pin_4);
! Q# ]+ s% E% c- ? - /* DAC channel1 Configuration */
2 B/ `! D0 k% ~% y% X: A, m - DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;$ @. ]0 `5 s1 U3 ~! ~# | d; v
- DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
% L5 J3 Y9 q, u% N - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
* X) V' e* z* A n6 ?% I' H$ @ - DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;0 T3 V3 ^; I+ C, Q
- DAC_Init(DAC_Channel_1, &DAC_InitStructure);: `$ E" Y( l* N) @+ x
-
" K7 Y) m5 Y) V' k2 R) S( F x, y - /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is 3 }# ^1 g2 {2 s
- automatically connected to the DAC converter. */# N6 f' v. d8 H8 E. l O
- DAC_Cmd(DAC_Channel_1, ENABLE);
8 |* s+ q9 M: ?- ^9 b& U - ! L( s+ c( E# u4 _3 K* [
- /* Set DAC Channel1 DHR12L register *初始化/
, X5 x& Y/ \8 d+ |- b* q2 P6 j - DAC_SetChannel1Data(DAC_Align_12b_R, 0);0 I- a; e- g' d% |9 A
- 1 Z. w8 y* m( ]# Z5 p; S3 s
- }
4 f2 m0 W! |2 e( S3 q' s# t - //设置DAC通道的值我们可以通过按键 例如( d, Z$ e: r7 G* |% b+ ^
- if(按键按下)8 J+ w. D5 @0 M7 j' I' c1 h, T
- {
+ I: j& S/ A& c R% l# Y" E' D0 m - delay_ms(10);
8 `1 _' R% \2 s8 L* f% }
" _0 w9 {! c8 ]9 o# r1 X- DAC_SetChannel1Data(DAC_Align_12b_R, a += 200);
9 q9 N6 D% |; R - if(a>4000)9 ?9 L! R U0 S% A% ]2 k
- {! c+ h# t) u' U) R
- a = 0;
* ?# ?# ` k$ L - }
4 |* O$ Q1 N" C& D - }
- M/ A' g) S1 N - ,或者由ADC转换后的值,给DAC采集
R& C1 L$ J' K0 i$ C# U - adcx=DAC_GetDataOutputValue(DAC_Channel_1);//通过此函数我们可以读取设置DAC通道里的值也就是DOR里的数(0~4095)
- O$ r1 [$ p. p. ~: k - DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)//根据此公式就可以计算出模拟输出电压、、
" Q% T/ o: N$ J1 i) L - 此模拟电压又可以被ADC采集,从而输出(0~4095),你可以把两者结合起来,通过一定的编程,通过串口发送到窗口,看你设置的值和经ADC转换的值(0~4095)是否相等8 X* U5 l# l3 T, d- X4 s
- 1 }# F9 E v! M- H
- PS:此步骤也可以在官方的例程里找到步骤哈、、
复制代码
( s% M! \. U/ Q# H
& l$ _( K+ H% m' \$ C2 p+ ^" m; J' P L3 N
% V% D* x" L8 `; [9 Q0 R |