我们来看看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 % I, T% |6 U6 J, N0 X }! I
该使能信号只使能了模拟部分,数字接口部分由DACEN@RCC_APB1ENR控制WAKEUP
, o- f/ _* E1 Q( z6 p 经过t WAKEUP时间后DAC通道准备就绪/ B. \2 x. S" l; N
DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)
" ?! p& b. P n 输出通道上集成可配置的输出缓冲,以减小自身的输出阻抗
& k( F% e4 h. o 使能控制:BOFF1@DAC_CR 2、输出通道上的缓冲: 通道内嵌输出缓冲以增加驱动能力 外部负载较大时,无需增加外部放大器 可使能或禁止该缓冲 外部有大负载,且缓冲禁止时,输出电压可能达不到预期 介绍两张图片:大家可以对比对比下,在这就不细讲了、 3、DAC的转换过程: 用户写入DAC_DHRx的值,自动或者在外部触发条件下经过一段时间后,传输到DAC_DORx;再经过一段固定时间tSETTLING,在外部引脚输出转换后的模拟信号(电压)。 (1)对DAC_DHRx的写操作
" ~ Q( F! F$ g o, K8 R% |' R (2)数据从DHRx到DORx的搬移
4 {3 T4 v6 u0 g( s4 m (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
8 [# s; k- w- _: Q BOFF1:关闭DAC通道1输出缓存 (DAC channel1 output buffer disable)我们关闭输出缓冲 故设置为1 EN1:DAC通道1使能 (DAC channel1 enable)我们要使能DAC通道、故设置为1 至此,我们已经设置了以上寄存器,我们就可以操作DAC了,但是我们并不是通过寄存器操作的、在这里摆出寄存器的设置,是为了大家有一个更好的了解,那我们打开"stm32f10x_dac.h" 可以看到: - typedef struct( i3 j& {/ e) L! a# C* i+ P% V
- {; h0 O" `1 a( y0 K1 E
- uint32_t DAC_Trigger; /*!< Specifies the external trigger for the selected DAC channel.设置是否使用触发功能
" s8 ]5 ]6 q/ f7 C7 _/ r - This parameter can be a value of @ref DAC_trigger_selection */$ ~/ N# R1 C! B& T
6 S, v3 D2 @0 j- uint32_t DAC_WaveGeneration; /*!< Specifies whether DAC channel noise waves or triangle waves设置是否使用波形发生
6 H: ?6 o! j9 e2 ^) U- k - are generated, or whether no wave is generated., ^. Z4 r) N7 l/ k5 i
- This parameter can be a value of @ref DAC_wave_generation */, V- ?8 B+ U9 W3 [/ v" Y( d4 V% h6 [: ?
- $ |0 P0 X- e! U+ C5 `8 _ w/ }% o
- uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or设置屏蔽/幅值选择器2 L3 p4 d& D" `3 r% A* B# A
- the maximum amplitude triangle generation for the DAC channel.
\1 e! g9 |5 @2 j - This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */) R" J& M' L* H0 C7 K# e
! H4 p3 L/ \+ @; u: S D: T- uint32_t DAC_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled.设置输出缓存控制位
复制代码 " R; _% e. \0 O1 @ k6 c
2 F6 \' e% b( o. c$ ? 根据以上说明,具体的设置请看代码、、 那好、、现在我们来看看具体的步骤: 1、使能DAC的时钟和GPIOA的时钟,并配置GPIOA 2、设置DAC的工作模式等功能 3、使能DAC通道 4、设置DAC的输出值 - void Dac1_Init(void)
$ Q: b o5 m; v3 F& i) v' L - {
4 ?2 W8 \' g* g: T( r. ]/ p. ^- ] - DAC_InitTypeDef DAC_InitStructure;
, q+ x. O2 V2 V3 B: u' M7 S2 E+ F1 c - GPIO_InitTypeDef GPIO_InitStructure;1 y r8 w) H! w& m) n+ T
- " `3 L" e! E7 F$ {4 w
- /* Enable peripheral clocks ------------------------------------------------*/; @4 `% p: a9 B$ R4 T0 ^) l
- /* GPIOA Periph clock enable */
3 I4 ?8 f* w- V( B, o6 k9 c - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
) W* |" [3 @1 E# Q5 c! z' | - /* DAC Periph clock enable */
! |; D3 w2 G1 H! o8 i* Y8 O - RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
# ]; z5 P; v9 e" ^ |" D1 o - 8 X' j4 B/ L- L* J6 V
- /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
1 U; x1 R0 z6 ~; t, a - connected to the DAC converter. In order to avoid parasitic consumption,
Q% t& B( Z' O+ s3 g8 N4 } - the GPIO pin should be configured in analog */6 ?' o: p3 N& U, a
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; m& n* I, {* g4 E
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
5 }' O& I. Q' [. ^* {" c - GPIO_Init(GPIOA, &GPIO_InitStructure);# H% B8 `& I+ y4 t) d5 e. A
- GPIO_SetBits(GPIOA,GPIO_Pin_4);
8 A4 [, y9 L: Y, |0 C3 T1 B - /* DAC channel1 Configuration */1 @3 w9 k8 b1 @( {
- DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;( r6 |( s" ]7 _+ _4 v# ~. O
- DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
$ ?) T* w5 o( Q4 b* _/ d" }% \+ I - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
8 _3 B0 O8 J) q: Z4 y3 K) M" E - DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
z6 K! F) F6 _ - DAC_Init(DAC_Channel_1, &DAC_InitStructure);( _& e8 C3 h' |7 ]' e" J
- 3 H ?* Y9 Z3 M) g" P5 D9 j
- /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is
& g" q5 [" }) Q! L! O - automatically connected to the DAC converter. */
# p9 O) w& J" P4 q - DAC_Cmd(DAC_Channel_1, ENABLE);
) H8 [( `1 o) y. ~& I9 f# B& ^ - 9 o0 M$ T5 _. p) {- R K
- /* Set DAC Channel1 DHR12L register *初始化/* I0 o0 s, k5 ?- A- d
- DAC_SetChannel1Data(DAC_Align_12b_R, 0);
}; q$ h7 p! C
8 j8 l# L' C3 ^" W5 Q- _0 ?- }8 f) U, \0 C1 T9 @# D
- //设置DAC通道的值我们可以通过按键 例如
3 k+ U$ e m" i - if(按键按下)
k$ _7 F: H, \ - {
% C# H. } ?- n/ `, S6 j- J - delay_ms(10);
* K& r6 ^4 f @- }3 l - - p$ E8 v" f5 h! |% ?
- DAC_SetChannel1Data(DAC_Align_12b_R, a += 200);
* v) ]7 k7 Q4 ] - if(a>4000); {+ t$ Y+ `6 C8 E2 D* q
- {
+ a/ u* P9 D$ z. ]) k d - a = 0;# }2 c+ M: ]5 S$ y
- }5 g' h# F6 q# j) `; u
- }+ U3 X, D$ `+ k1 o3 \3 E
- ,或者由ADC转换后的值,给DAC采集
* [% z' g2 k9 L9 a! W5 c5 K3 V - adcx=DAC_GetDataOutputValue(DAC_Channel_1);//通过此函数我们可以读取设置DAC通道里的值也就是DOR里的数(0~4095)
5 C9 N6 G4 E7 d3 t+ p, k7 b+ o ~ - DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)//根据此公式就可以计算出模拟输出电压、、# f# R4 B3 E1 I1 h/ G( F
- 此模拟电压又可以被ADC采集,从而输出(0~4095),你可以把两者结合起来,通过一定的编程,通过串口发送到窗口,看你设置的值和经ADC转换的值(0~4095)是否相等5 F1 X1 A0 x8 s, c, [, b' M
- * f$ v$ k8 m' L, \
- PS:此步骤也可以在官方的例程里找到步骤哈、、
复制代码 ; Q5 P7 h0 v# [9 f' n G
0 P# c: J H" Q" {3 V; o% h9 V% N! v2 N1 c4 Q( S
2 _7 e& ]5 k8 H% Q+ o. o% C w |