所谓的DAC功能也就是将数字信号转换为模拟信号,一般情况下使用比较多的就是ADC功能,也就是将模拟信号转换为数字信号,多用于读取传感器的值。但是有时候需要控制某些传感器,需要用模拟信号控制,这就需要将数字信号转换为模拟信号了。
' c L9 O$ c! _4 `2 k
9 y3 O; F5 Q5 a) X: e7 y 数字/模拟转换模块(DAC)是12位数字输入,电压输出的数字/模拟转换器。或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压V REF+ 以获得更精确的转换结果。& x. `+ j+ `' [! ? ]) q4 b
( u/ i" f7 F5 L/ T( H) c: _
DAC 主要特征
) d) p1 |+ Q( {& `# Z2个DAC转换器:每个转换器对应1个输出通道 S4 {$ z; _* _4 Z; u5 O
8位或者12位单调输出
4 F5 z; k- S) y! J, ?12位模式下数据左对齐或者右对齐5 R9 d9 D0 @# W" b, q9 @; ?
同步更新功能
6 M5 G" T7 W- S/ m$ j噪声波形生成
8 d5 ^0 t" q9 I/ ]0 P0 V三角波形生成/ K% j) s- S) W+ l5 o l# k7 `$ j- w
双DAC通道同时或者分别转换' U. Z9 D7 R8 \- M* p [+ M
每个通道都有DMA功能4 @' f6 f) V l) y! {. e8 P5 m! A$ l) N
外部触发转换
1 K; ]/ U" [6 W8 p& W: ^/ ]输入参考电压V REF+% P7 y( J: g* Q& B# _
下面就通过代码来实现模拟信号输出。$ N+ H, w4 V* V- g( R9 Z% Q
! k: ]' L" |, ~5 d" B
- #include "dac.h"/ Y- l. W K y% H
- 8 x+ c3 I9 i& H4 O+ y% L# A
- void DAC1_Init(void)
0 b8 c2 Q7 T n' S - {. j. v6 o/ P( f+ p
- GPIO_InitTypeDef GPIO_InitStructure;
2 o( e; |3 P! h6 U8 N1 a - DAC_InitTypeDef DAC_InitStructure;* {) V4 P/ s/ d- l# B, E8 ]
- : c* @0 }& M0 d( Z L
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);2 \ S* d4 Y" M# a3 L
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC , ENABLE);$ ^2 j- [/ d+ s
* S& V% X: V; @! t; H5 Y. W* ]7 N- //PA4设置为为模拟输入,使能DAC通道后,PA4会与DAC模拟输出相连,设置为输入为了避免了干扰
; G a5 O" X0 t8 f |9 [ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
' m* y) o4 _/ M* |5 Y9 @* u - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //设置为模拟输入. L5 |. W/ P% r+ K+ }0 P$ g) E
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/ Y6 Q5 B' l0 T3 p
- GPIO_Init(GPIOA, &GPIO_InitStructure);, `* m' n8 q7 M+ k) z! n
. |! Z# R% f. K: j, x- DAC_InitStructure.DAC_Trigger = DAC_Trigger_None; //不使用触发功能 TEN1=0
9 R! v" J( F0 p* L0 X - DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不使用波形发生
# L5 K, W- Q/ q+ z$ ] - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; //屏蔽、幅值设置* D% F0 m0 i. v5 V
- DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //DAC1输出缓存关闭
' P' c; L. i" u9 J9 [" [ - DAC_Init(DAC_Channel_1, &DAC_InitStructure); //初始化DAC通道13 |) Q( v$ \2 y) `7 F, W' }' D
- G. \; Y# H* j! J4 p: _
- DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1
0 m! Z5 g8 d) @- v. B - DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值3 |+ ~" c4 o, f' ]- o, y3 A* Y& I& k! L
- $ [3 k. R8 W8 i* K& }$ q! G3 ?: M1 C9 U
- }( Y/ C# K. E! @
- //设置通道1输出电压
0 C0 p: g6 N# R1 _+ U$ v - //vol:0--3300,代表0-3.3V( `2 X; v1 E# v, K8 `3 u
- void DAC1_Set_Vol(u16 vol)
( ~4 o' m; E7 Q* v$ ^; z) G1 E - {
1 o/ \7 K3 T% z! I" \: l2 ]9 e - float temp = vol;
- F6 {+ n7 ?9 Z3 _& T* E - temp /= 1000;) a! p& Y% u6 y+ o5 O+ b
- temp = temp * 4096 / 3.3;
) L) E j3 P- I* Y, D5 o0 v" `2 M - + ]1 v2 B+ @- ^- J( B0 [
- DAC_SetChannel1Data(DAC_Align_12b_R, temp);
7 c' |1 A: |) e1 E - }
复制代码
- K3 l& b1 F( L6 a在初始化的时候,要注意一个问题,STM32F103单片机的DAC输出通道有两个。
* b7 |- P/ C7 i# H2 ~
6 ?( u( y( N+ T
2 h c+ S& Q6 K! ]4 }0 U5 P. @
$ S$ ~& x# y$ T. ~: t8 v6 D- `PA4和PA5,但是在初始化引脚的时候,要将PA4和PA5初始化为模拟输入功能。这个在官方文档上也有说明。
5 p X& w5 D2 s( Y |0 w+ Q& o0 G
0 @( A+ [! ~4 j3 p3 J8 w, M' e, b. d) a# O. \! O: h; }
内部自动就会将PA4和PA5与模拟输出引脚连接起来。所以在初始化的时候,虽然用的是输出功能,但是还是要将引脚设置为输入。/ B& M/ \- d0 `- f
/ E* h& W: I* F/ [6 {: v$ k 初始化引脚之后,接下来初始化DAC功能,在这里不使用触发功能,也不使用波形发生功能。直接通过软件来控制3 V) c" u3 i8 O7 V
]6 f. n% T+ H7 F 接下里通过一个函数将要输出的电压值换算为寄存器的设置值。DAC的转换为12位,所以最大值就是2^12,也就是4096,而stm32单片机的供电电压值3.3V,所以将要设置的电压值除以3.3,然后乘以4096就是DAC寄存器需要设置的值。
* i+ L: a) f; q, L% g
, m9 k' J6 i$ _! r 如果要输出模拟电压值时,只需要在主函数中调用DAC1_Set_Vol()函数,并将要设置的电压值传递给这个函数就行了。
7 p2 Q. c4 f- P! C% n: ~; x" w5 h7 R0 X. F
- int main(void)3 o* @1 P8 z, P+ p/ Y; y0 a2 W
- {# g) v3 \! |# y
- u16 adcx;4 C" u; P' F& H' k: K
- float temp;! v' z. x/ F2 {$ K8 y0 w, g
- u8 t = 0;" n3 u& Z- h% e1 C1 \+ U O' I! B
- u16 dacval = 0;$ f; W( E# | [ i- z
- u8 key;
1 @7 u7 M# p. ~3 W/ q% s
; j/ M: o$ h& \- delay_init();: O. j1 x; e# N9 x ?/ ?2 D
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);' D# k {7 w+ N% E
- uart_init(115200);6 O; s9 a ^) G* @/ h' m( v
- LED_Init();2 `# T. d( t' B6 e7 _- A
- DAC1_Init();
, [6 J5 S1 s3 t; D5 t$ u. ^! K) ` - while(1)
- I4 J) t' L& W1 x - {
% L' S7 S8 q% j$ l+ [ - LED0 = !LED0;
' R9 W9 v3 x* f8 W+ Q0 L - DAC1_Set_Vol(1000);
1 ~) z6 @8 M6 O" N! B - delay_ms(100);
2 t5 e( d# @% r) o7 f - }
2 @8 ]2 [( J) d. p" u0 [ - }
复制代码
" G6 \! P w; T+ w p在主函数中设置DAC输出的电压值为1000,也就是1V。这时通过万用表就可以在stm32单片机的PA4引脚量到1V的电压值了。; c. Z# S! ^+ F* p+ P
: r* }5 v- J0 |8 M. L0 I- C) A
) A( B H. ?* E; |- R2 U
4 n4 C3 }' ~$ Q4 ]* l |