我们来看看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
) G# i& {$ t% N3 n7 T6 L2 d# R 该使能信号只使能了模拟部分,数字接口部分由DACEN@RCC_APB1ENR控制WAKEUP
9 I4 z% R6 @( ]1 V 经过t WAKEUP时间后DAC通道准备就绪
8 O# w8 @) w% R$ C D" s DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)& Y9 o f4 K0 Z. c5 J7 k; p
输出通道上集成可配置的输出缓冲,以减小自身的输出阻抗/ j* |+ e! n3 E5 z1 S, L) w6 F0 p
使能控制:BOFF1@DAC_CR 2、输出通道上的缓冲: 通道内嵌输出缓冲以增加驱动能力 外部负载较大时,无需增加外部放大器 可使能或禁止该缓冲 外部有大负载,且缓冲禁止时,输出电压可能达不到预期 介绍两张图片:大家可以对比对比下,在这就不细讲了、 3、DAC的转换过程: 用户写入DAC_DHRx的值,自动或者在外部触发条件下经过一段时间后,传输到DAC_DORx;再经过一段固定时间tSETTLING,在外部引脚输出转换后的模拟信号(电压)。 (1)对DAC_DHRx的写操作
4 g; C( K$ n+ ~: v (2)数据从DHRx到DORx的搬移
! { Q) d, `+ N4 A (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
! Z6 @0 k) b8 x+ t1 f I- f BOFF1:关闭DAC通道1输出缓存 (DAC channel1 output buffer disable)我们关闭输出缓冲 故设置为1 EN1:DAC通道1使能 (DAC channel1 enable)我们要使能DAC通道、故设置为1 至此,我们已经设置了以上寄存器,我们就可以操作DAC了,但是我们并不是通过寄存器操作的、在这里摆出寄存器的设置,是为了大家有一个更好的了解,那我们打开"stm32f10x_dac.h" 可以看到: - typedef struct8 }9 G8 H) ~7 H; n" w
- {
6 U$ N) |" d7 }6 ?: ^/ r' F - uint32_t DAC_Trigger; /*!< Specifies the external trigger for the selected DAC channel.设置是否使用触发功能- b0 t- B) W& L7 x: o
- This parameter can be a value of @ref DAC_trigger_selection */
, ~0 @0 b$ `4 N0 M7 l8 O5 v, A9 L - 3 j0 t6 y$ O& ?- F5 G0 j3 Y2 N
- uint32_t DAC_WaveGeneration; /*!< Specifies whether DAC channel noise waves or triangle waves设置是否使用波形发生' |% Y) [* B% k1 E4 V4 g7 m5 C
- are generated, or whether no wave is generated.
0 x) _2 X$ b3 L/ w% p - This parameter can be a value of @ref DAC_wave_generation */# \9 t; c7 P) _2 B1 n- K. X
' c( ~- W- c3 p! ]" w- uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or设置屏蔽/幅值选择器
7 l, G( ?4 [( z( z+ z - the maximum amplitude triangle generation for the DAC channel. 4 ^4 G/ l! n* D
- This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */
7 \+ V8 t4 g% i - 2 g) |9 g$ J" K8 p7 P9 g& w8 c) T
- uint32_t DAC_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled.设置输出缓存控制位
复制代码 ( m: X- J& a6 j4 S9 h* W
6 l; ^: Q. c. \- A1 o W 根据以上说明,具体的设置请看代码、、 那好、、现在我们来看看具体的步骤: 1、使能DAC的时钟和GPIOA的时钟,并配置GPIOA 2、设置DAC的工作模式等功能 3、使能DAC通道 4、设置DAC的输出值 - void Dac1_Init(void)
% \" M1 x& C9 m0 Q1 H$ }" n! g - {* D( ^7 x3 b. I4 C% l3 m+ s7 V
- DAC_InitTypeDef DAC_InitStructure;2 m% H# J7 J; m1 `6 n6 w0 l# E
- GPIO_InitTypeDef GPIO_InitStructure;
/ Q: ?. Z! b& @& n x8 |5 ]; c3 a - ' {) `+ }. c4 {$ `9 f- j$ ]+ J3 m# h
- /* Enable peripheral clocks ------------------------------------------------*/7 K6 L2 m" [7 ?; H+ S8 A
- /* GPIOA Periph clock enable */" `: B2 f6 X1 [* r. x
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);% B9 L' [. Y7 M9 Z1 l4 F
- /* DAC Periph clock enable */
$ X3 }" x) W5 D& H - RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
, R; g/ D# y, h# S -
3 H$ u R. S/ B" ? - /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically . E5 T) N1 `" f6 l3 Z6 v$ G0 e
- connected to the DAC converter. In order to avoid parasitic consumption, % ?' \) D" t. \" V) k
- the GPIO pin should be configured in analog */
7 M# I" Y. U2 W% U- h9 v - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
( u. Y3 F; s% O& k7 H - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
$ X/ [* p: ^5 S, {2 s - GPIO_Init(GPIOA, &GPIO_InitStructure);3 E$ N$ r4 X0 @, o
- GPIO_SetBits(GPIOA,GPIO_Pin_4);
; B7 ?0 v8 |7 u1 u6 h5 F% l - /* DAC channel1 Configuration */
+ U! u+ O- X9 X& A - DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
4 Q3 I& C6 Z6 F% Z, P, f - DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
* O9 r/ n) J- G. P - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
( L9 {8 h. L! s) c - DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;+ z, Q' D% X/ q2 b+ }+ c7 o
- DAC_Init(DAC_Channel_1, &DAC_InitStructure);1 y1 Y- u6 R6 A0 x8 Q% b
- 0 {- X4 P7 }, I, i+ C' n% A. z3 E
- /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is ! g( N8 x# Z$ V
- automatically connected to the DAC converter. */
( [6 F3 f/ W" g - DAC_Cmd(DAC_Channel_1, ENABLE);, Y2 r" l+ t) A, ^4 ]# _4 G! ?# f
-
. f% }3 N* j0 Z& _6 e% Z4 f5 J - /* Set DAC Channel1 DHR12L register *初始化/' N& ] I; A6 S" I F
- DAC_SetChannel1Data(DAC_Align_12b_R, 0);2 l( I- H. a$ h
) o: E1 h+ V9 Q* j+ P( o* p- }: f* z7 K i3 S/ _* l
- //设置DAC通道的值我们可以通过按键 例如
H" V d" y/ {) ?+ \; F3 T, h V8 B! ? - if(按键按下)! v9 x8 i& G" P" x
- {! J& s+ |: t; Z/ F2 v
- delay_ms(10);
0 Y( ?& h6 [' s. _6 W - 0 H( q4 C* }' }! v
- DAC_SetChannel1Data(DAC_Align_12b_R, a += 200);
$ w7 d# N6 b& ?- C8 U! n - if(a>4000)
7 x% o1 u+ C3 l1 w: \1 R - {. T* Z. U9 W4 v: M5 W, ~2 y
- a = 0;
9 [( M) z5 l* m, z1 U: A - }
- }3 A, k3 ~ t s+ a* @- v - }
3 p1 c7 A5 s, x+ M8 A! l - ,或者由ADC转换后的值,给DAC采集
9 a. l& X/ v" x& _& m! Y - adcx=DAC_GetDataOutputValue(DAC_Channel_1);//通过此函数我们可以读取设置DAC通道里的值也就是DOR里的数(0~4095). @' X- i% @" a: M0 h, ]6 J
- DAC通道上的引脚输出模拟电压 = VREF+ * (DOR / 4095)//根据此公式就可以计算出模拟输出电压、、
* \, z9 _+ |. l9 N* N- L - 此模拟电压又可以被ADC采集,从而输出(0~4095),你可以把两者结合起来,通过一定的编程,通过串口发送到窗口,看你设置的值和经ADC转换的值(0~4095)是否相等
* R9 ]# o& J" q' c
4 k: L7 U( Q$ U: y0 s) w0 E j- PS:此步骤也可以在官方的例程里找到步骤哈、、
复制代码
; I& c0 L7 R; |8 u
. u6 Q8 Q8 \* ^/ V
# r5 \! {" F% @
1 F h5 O' n0 e3 O& A" h |