我们来看看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
' A1 t: b$ p. q$ R 该使能信号只使能了模拟部分,数字接口部分由DACEN@RCC_APB1ENR控制WAKEUP; N/ t9 A# ^! p9 s" r: ]6 @" K$ ?
经过t WAKEUP时间后DAC通道准备就绪
' } K: v1 e8 k& O DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095), `6 V2 [+ s! T8 U+ N7 A
输出通道上集成可配置的输出缓冲,以减小自身的输出阻抗
% \7 W" e% h; ]3 }& ?1 ] 使能控制:BOFF1@DAC_CR 2、输出通道上的缓冲: 通道内嵌输出缓冲以增加驱动能力 外部负载较大时,无需增加外部放大器 可使能或禁止该缓冲 外部有大负载,且缓冲禁止时,输出电压可能达不到预期 介绍两张图片:大家可以对比对比下,在这就不细讲了、 3、DAC的转换过程: 用户写入DAC_DHRx的值,自动或者在外部触发条件下经过一段时间后,传输到DAC_DORx;再经过一段固定时间tSETTLING,在外部引脚输出转换后的模拟信号(电压)。 (1)对DAC_DHRx的写操作$ K8 s" p; R* {6 t e
(2)数据从DHRx到DORx的搬移& w% a! T/ z# g
(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
2 f- k" j7 V% q1 i- ^: r& ? BOFF1:关闭DAC通道1输出缓存 (DAC channel1 output buffer disable)我们关闭输出缓冲 故设置为1 EN1:DAC通道1使能 (DAC channel1 enable)我们要使能DAC通道、故设置为1 至此,我们已经设置了以上寄存器,我们就可以操作DAC了,但是我们并不是通过寄存器操作的、在这里摆出寄存器的设置,是为了大家有一个更好的了解,那我们打开"stm32f10x_dac.h" 可以看到: - typedef struct! A0 d4 g* o0 J
- {2 G- J4 l' g. c& x3 l* d
- uint32_t DAC_Trigger; /*!< Specifies the external trigger for the selected DAC channel.设置是否使用触发功能4 w0 [2 D: L: G0 g0 }+ `
- This parameter can be a value of @ref DAC_trigger_selection */4 \4 f! @: e' D$ U5 F
' h: J& J G% c; A3 s- uint32_t DAC_WaveGeneration; /*!< Specifies whether DAC channel noise waves or triangle waves设置是否使用波形发生# J5 F9 [! x' p8 i8 q# w# }
- are generated, or whether no wave is generated.
0 @8 E+ G2 D; \5 n) R - This parameter can be a value of @ref DAC_wave_generation */- Y1 \+ A$ k/ ~; ~1 R
- 1 e, f( _3 h: Z4 U# B y1 V1 T0 [
- uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or设置屏蔽/幅值选择器
- R' b# E9 j4 s: H3 T: v) P - the maximum amplitude triangle generation for the DAC channel. , d3 b/ C; t5 P6 ], T- g% ]* ^) u
- This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */
4 i( N9 k2 A" n' _* k( p+ R$ P
9 q, W! ^! B: Y7 j% r- uint32_t DAC_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled.设置输出缓存控制位
复制代码
" c! M7 ?! P2 g* v6 C7 C+ {: ?
! ~8 t; E3 B+ z4 I 根据以上说明,具体的设置请看代码、、 那好、、现在我们来看看具体的步骤: 1、使能DAC的时钟和GPIOA的时钟,并配置GPIOA 2、设置DAC的工作模式等功能 3、使能DAC通道 4、设置DAC的输出值 - void Dac1_Init(void)
# A0 L+ w( k E8 e7 p* q) b1 c - {
; \; ] q% D- d9 j F; W - DAC_InitTypeDef DAC_InitStructure;2 \, \2 ?' V$ W: R/ b" R
- GPIO_InitTypeDef GPIO_InitStructure;+ _% r% _8 T* |+ L
- " q4 C/ k5 @. G
- /* Enable peripheral clocks ------------------------------------------------*/9 n/ Y; r* k! x7 ]+ M
- /* GPIOA Periph clock enable */% w9 i, s+ E: t4 U) e8 O1 [6 i
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
) h4 ?1 ]# S7 A5 P; w7 {8 M. a0 J - /* DAC Periph clock enable */! o8 Y; R" T2 b% r- f( ?: D
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
9 s! B& |% E& H7 \( T1 K- M8 g - " l- l8 g4 x! Y9 L
- /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically & V) S/ m i8 O2 B* _8 g# {
- connected to the DAC converter. In order to avoid parasitic consumption, % J! H4 }) T6 P$ i, q4 {* B1 C$ D
- the GPIO pin should be configured in analog */* B; Y# Q/ F9 o: [- }, Z2 ]
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
2 q( a! r8 R2 c9 a; ]( s3 \ - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; C( ^ k v# g1 a
- GPIO_Init(GPIOA, &GPIO_InitStructure);$ {' m1 V* |% a1 F, |% O% E
- GPIO_SetBits(GPIOA,GPIO_Pin_4);
- l y3 k) b: @& \% h, a - /* DAC channel1 Configuration */
) @4 }; y- x/ y! f$ P2 ] - DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;% d# |; m# K& {( T4 k
- DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
1 [! Z, o+ ? T/ h) B" a - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
& p; v6 Q' n) n5 x - DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
" H, i7 V4 h& Q( e - DAC_Init(DAC_Channel_1, &DAC_InitStructure);; \" y& ]: E( d; l
- 0 B% S/ z$ J2 f4 z& J9 A! U
- /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is ' s& \7 S& L+ w8 h" a
- automatically connected to the DAC converter. */- b* Y }' f2 K; w( S
- DAC_Cmd(DAC_Channel_1, ENABLE);
! H7 g& ^8 `9 p( {7 o) x -
5 g- K& `9 B! l' @; ~ - /* Set DAC Channel1 DHR12L register *初始化/
8 D% N/ q1 a J8 n) t+ T+ m - DAC_SetChannel1Data(DAC_Align_12b_R, 0);
7 b& W, l8 M* _ - 3 U# Q! p: G P( P3 X H
- }7 f0 x# k! q3 f/ I% p/ Z& `7 U
- //设置DAC通道的值我们可以通过按键 例如% x8 P3 h% n+ c* `1 T3 T/ e8 J+ t% O P
- if(按键按下) l! H7 ^ b ?1 Z% z
- {
* [! P' j/ _1 A" k* b - delay_ms(10);
' Q9 T! z- N# W; R8 C! F. Q
* M3 @' }+ W4 Z- DAC_SetChannel1Data(DAC_Align_12b_R, a += 200);
1 ^, C. e" ^! A: }, D# L - if(a>4000)9 X& c* r# H# \2 n' y
- {
* L1 p# k% u" w; Y, d4 h# L& p - a = 0;
' c3 I% l4 {1 w - }8 P6 I0 b3 v1 }1 k" M
- }
3 H) i+ _" [( D& n. O; d6 Q - ,或者由ADC转换后的值,给DAC采集
7 b& d+ p& y# w+ t6 n# E+ N - adcx=DAC_GetDataOutputValue(DAC_Channel_1);//通过此函数我们可以读取设置DAC通道里的值也就是DOR里的数(0~4095)
# a* S) L4 c7 ^9 Q. | - DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)//根据此公式就可以计算出模拟输出电压、、 Q, W1 Y$ m- Y2 [$ R/ B3 Y
- 此模拟电压又可以被ADC采集,从而输出(0~4095),你可以把两者结合起来,通过一定的编程,通过串口发送到窗口,看你设置的值和经ADC转换的值(0~4095)是否相等
% X/ u9 S' L+ p D1 |3 Q
/ ` P- {$ f9 z& p/ o- PS:此步骤也可以在官方的例程里找到步骤哈、、
复制代码
; ~% W4 G Q' \
2 j A+ w, N4 ?. D
% }8 I+ y( n. |% V* H# z& |, w3 \9 c G% W- M/ [2 Z
|