所谓的DAC功能也就是将数字信号转换为模拟信号,一般情况下使用比较多的就是ADC功能,也就是将模拟信号转换为数字信号,多用于读取传感器的值。但是有时候需要控制某些传感器,需要用模拟信号控制,这就需要将数字信号转换为模拟信号了。; m! A, g9 ?% g' i
- @0 T. o8 D0 N1 S6 K! ^8 u 数字/模拟转换模块(DAC)是12位数字输入,电压输出的数字/模拟转换器。或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压V REF+ 以获得更精确的转换结果。
! E, N# u1 q/ S5 t
: i- `# B ~' v1 dDAC 主要特征* U% x H/ q! H1 ~ }% U _
2个DAC转换器:每个转换器对应1个输出通道7 X% [, X, e9 a8 y) E2 B/ F
8位或者12位单调输出, m0 \8 L& ~# M$ _" @/ w" _1 h5 a
12位模式下数据左对齐或者右对齐 j! N" F# P8 |9 q4 N
同步更新功能* q" R& N* g; z/ O. Q* _
噪声波形生成8 Q: {4 o' V O+ O. n. C% T
三角波形生成1 o; b/ E3 Q3 B9 I% k5 ]
双DAC通道同时或者分别转换. G) s9 m- ^ u) |0 Q a
每个通道都有DMA功能2 G* h8 i- n1 z* l1 x% h5 [; e
外部触发转换+ b; m# I) D7 D, \. I% m4 o% V7 G
输入参考电压V REF+
) h! i, E2 o# C) U8 h下面就通过代码来实现模拟信号输出。
# _6 P; ]) h: z4 v" i Q |4 c4 p$ k# D0 x8 i! _
- #include "dac.h"" s+ r% k1 q5 ^2 N, t( u; ?) Y; q
0 ^% m! Z4 [3 _/ p( P- void DAC1_Init(void)
) z* |9 [: v9 o" t% Z3 D - {
% H! i1 t" E# n6 o+ { - GPIO_InitTypeDef GPIO_InitStructure;
" g- ~% D, ~' P3 ]% n7 r - DAC_InitTypeDef DAC_InitStructure;
* j3 R2 [" C/ r' ?
1 b2 Y. U3 }4 I+ g+ \# E- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);. i& }0 U3 J1 l C1 r" [
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC , ENABLE);
% O1 H. `1 G$ B4 b
) d/ ^* R6 J- N* S, w- //PA4设置为为模拟输入,使能DAC通道后,PA4会与DAC模拟输出相连,设置为输入为了避免了干扰
6 h1 x% E) q0 ^- R/ z3 Q: ?# p - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
: r# k% t5 D" C$ J+ i6 l - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //设置为模拟输入. s" N- N2 d1 N) j9 m+ k* B
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;, ^. h' |- O4 N
- GPIO_Init(GPIOA, &GPIO_InitStructure);
# t: f+ Y3 h% i* p, \5 u) o - 6 P! @5 q( C6 {* p c) z/ a
- DAC_InitStructure.DAC_Trigger = DAC_Trigger_None; //不使用触发功能 TEN1=0; S+ ]0 [ p5 C& d# D% o& p) h
- DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不使用波形发生
% v9 n" z3 g2 ?3 ^, C& c, d% P - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; //屏蔽、幅值设置% F6 p7 `8 V8 e1 [
- DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //DAC1输出缓存关闭
+ M$ g+ G, a9 Q% A - DAC_Init(DAC_Channel_1, &DAC_InitStructure); //初始化DAC通道1
9 i# O% u! ~7 b9 }' `
# X8 {+ W& _' `- DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1/ v+ i6 ]- P- i
- DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
3 c% T c0 S9 e) b$ Y - . B9 N9 Z5 r3 Y; C" B
- }% W: \9 S+ {$ m$ x
- //设置通道1输出电压
' m5 p9 c* s$ t+ u - //vol:0--3300,代表0-3.3V
2 S: y$ y' w( \ - void DAC1_Set_Vol(u16 vol). A0 E* p4 S# G& v0 Q% ?
- {
8 @1 _) F4 F/ y0 N ^ - float temp = vol;. ?* \1 {0 ]: }9 a3 e+ [ u7 a" w i
- temp /= 1000;
" i3 _ Y: H, O/ R; G9 J( m3 ~/ q - temp = temp * 4096 / 3.3;
7 N! O9 V) d2 t5 h+ b. I* ?% D% t - * ~3 z# i& v6 h; M4 [0 H
- DAC_SetChannel1Data(DAC_Align_12b_R, temp);- ^7 @5 f3 k3 f4 O
- }
复制代码
8 o. X" c; r, o+ X$ @ x0 R在初始化的时候,要注意一个问题,STM32F103单片机的DAC输出通道有两个。 Q& i) r$ Q2 |, e5 O; c
" Y/ b7 ?) x* m
8 O) u' { U# q
, \/ w4 l4 { |" ^. PPA4和PA5,但是在初始化引脚的时候,要将PA4和PA5初始化为模拟输入功能。这个在官方文档上也有说明。; O: [2 n- |1 f6 T$ D
, m9 u% x* e, B/ P! x
" |! ?0 K7 f- C8 e" B) p5 l/ Q
+ f1 w* p' v$ G; h1 h; l/ N7 Z
内部自动就会将PA4和PA5与模拟输出引脚连接起来。所以在初始化的时候,虽然用的是输出功能,但是还是要将引脚设置为输入。
) v5 S* J/ \' ]6 _% p6 s
, Y" ^' n3 h! P- p 初始化引脚之后,接下来初始化DAC功能,在这里不使用触发功能,也不使用波形发生功能。直接通过软件来控制
# e0 m7 z: P; |( @! i) k7 ?% N# x! D4 f/ ~5 s7 X
接下里通过一个函数将要输出的电压值换算为寄存器的设置值。DAC的转换为12位,所以最大值就是2^12,也就是4096,而stm32单片机的供电电压值3.3V,所以将要设置的电压值除以3.3,然后乘以4096就是DAC寄存器需要设置的值。/ g% U7 ^$ f, }$ x8 i1 Z+ _
3 s3 @- X3 _ [* i j5 I6 _ 如果要输出模拟电压值时,只需要在主函数中调用DAC1_Set_Vol()函数,并将要设置的电压值传递给这个函数就行了。
" M( |9 {# t, w, D* ?( c+ I6 c! z L, Y8 S9 ~9 X: l
- int main(void)+ D+ S5 ]) h( h' ~/ d: ?
- {
8 h1 e8 C8 ^% L- }1 ]2 d - u16 adcx;
5 m }, T; ?" c2 U4 f - float temp;
7 ~+ |1 ^3 i6 h3 v1 W - u8 t = 0;
9 ]2 g# n" ?7 i6 j( }7 Y& [, o. ^ - u16 dacval = 0;
& N" E* B9 J8 G$ O# r. h - u8 key;" _$ a) Z x- I; E: a L
7 f) A- o6 y0 p' a/ o* T- delay_init();
7 p9 d9 b9 t+ b- |9 R1 W - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
$ t3 `% O5 V2 ~: k - uart_init(115200);& n6 j0 \' q0 U o- ^( F8 b, u
- LED_Init();
0 Z6 n1 \/ K+ f& m1 E, M - DAC1_Init();
* g7 D: V @( N1 B3 w3 ~ - while(1)( {& l6 |1 x0 C2 y( Z2 G; Z
- {+ T' M I- k8 f! }# v% r- n. R
- LED0 = !LED0;
& c, x6 Y3 j y- X* x! w/ k, S. n% Q - DAC1_Set_Vol(1000);" q$ s- F! Y3 L8 R1 T
- delay_ms(100);' [. |# z0 H' i! |8 M7 i1 m, Q
- }4 u2 ?0 w6 t1 D7 J k
- }
复制代码 Z! ^9 j9 e! L' {2 C2 [' V+ [* R0 X5 K
在主函数中设置DAC输出的电压值为1000,也就是1V。这时通过万用表就可以在stm32单片机的PA4引脚量到1V的电压值了。1 {0 g0 w1 F* F
2 g0 W% o4 N. M; K2 j: O ^8 |
2 X3 W7 e: A. i/ h3 U6 e- V/ V/ H R- J2 J& E
|