所谓的DAC功能也就是将数字信号转换为模拟信号,一般情况下使用比较多的就是ADC功能,也就是将模拟信号转换为数字信号,多用于读取传感器的值。但是有时候需要控制某些传感器,需要用模拟信号控制,这就需要将数字信号转换为模拟信号了。/ w9 `3 ]0 t3 {4 v
7 Q8 ]6 m, Q, `* d6 r
数字/模拟转换模块(DAC)是12位数字输入,电压输出的数字/模拟转换器。或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压V REF+ 以获得更精确的转换结果。
0 ^+ F9 c* y& g. e2 K) _1 Y% t: E
# ]( n& w/ ^( DDAC 主要特征
4 Z2 t: D1 O3 y6 H0 J2个DAC转换器:每个转换器对应1个输出通道8 F$ O" E; a& s4 J* m7 ]" ]' O" T0 N/ k
8位或者12位单调输出
8 z: b! D! C5 A# J& D12位模式下数据左对齐或者右对齐5 Q) x1 ], ?0 {( L$ M; F" V, Q& N
同步更新功能+ c8 q) J" c! P/ F9 }3 w7 h
噪声波形生成
0 _) h& c3 |7 c& B三角波形生成0 d0 Z, a+ E8 ] p7 \
双DAC通道同时或者分别转换0 \# T5 m# e& k. k" I% k; j# l* @
每个通道都有DMA功能
. F1 S' m# V3 H! q外部触发转换8 F2 t: ^7 ]+ x. }! u$ v
输入参考电压V REF+# p4 M% `5 S4 d0 y
下面就通过代码来实现模拟信号输出。" ]$ [- v( m4 S" e7 |: W
) H+ t& i. J( e0 ]. }. q/ k- #include "dac.h"
/ e& }% K/ L5 H2 h4 g/ z
4 q3 d" a3 c, h* _8 K. Y5 d- void DAC1_Init(void)
. D4 G9 v, L9 G+ | s - {' F6 C+ T( P" R7 `" O+ p- X
- GPIO_InitTypeDef GPIO_InitStructure;
2 b$ r$ h9 u% u$ p$ A, v - DAC_InitTypeDef DAC_InitStructure;2 d! Q& e3 m3 Q/ Z
$ V# U7 F7 |+ h/ E9 p- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);% m/ G) d9 C1 j. b
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC , ENABLE);' Y" h( o7 ~- Y' z* l) ]
* K$ f2 S0 s# d! J& n- F1 x- //PA4设置为为模拟输入,使能DAC通道后,PA4会与DAC模拟输出相连,设置为输入为了避免了干扰
, E: ]( O2 C: A+ U( W, i* t+ J - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
" ^* t" k$ r. _) a1 O3 o% E3 M - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //设置为模拟输入 }1 C i: o3 G; e. ^: I
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
& a1 S2 \- v+ n& z! w7 Z - GPIO_Init(GPIOA, &GPIO_InitStructure);- C- i" f* A' k
! O/ H- l5 E) {8 G7 `( d- DAC_InitStructure.DAC_Trigger = DAC_Trigger_None; //不使用触发功能 TEN1=0
6 p! b" d" n5 W - DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不使用波形发生+ j) E( @0 \" _7 a. L
- DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; //屏蔽、幅值设置
( d7 O2 C/ e; D; {9 Z% X2 r3 D - DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //DAC1输出缓存关闭# E+ K; G6 X7 {6 X9 W
- DAC_Init(DAC_Channel_1, &DAC_InitStructure); //初始化DAC通道1# W, ]3 L( J! t% A! @* N
8 ^- c6 R" x, U1 I- ~% ~- DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1" \" ], F0 A: P, R$ Z) U. f, A/ }/ Z
- DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值1 H9 m0 T$ {# g+ \9 u+ t9 P
- # \: [; b( P7 Z9 n4 S }
- }
! G, K. ], N6 e3 g - //设置通道1输出电压
* c* `+ U/ h9 r% G. t - //vol:0--3300,代表0-3.3V7 P, q: ^3 F# S5 n6 @- D/ s
- void DAC1_Set_Vol(u16 vol)
( v) [' }4 C; x0 ? - {
* l4 X1 _4 |, U0 N( ` - float temp = vol;
! P0 l7 J* D! m - temp /= 1000;
7 X- b- ~1 P S! [% i0 Y. k8 f+ ~8 j - temp = temp * 4096 / 3.3;
O; W- V c1 ]7 T7 p, `
' q/ c4 X: y8 n( O- DAC_SetChannel1Data(DAC_Align_12b_R, temp);( V- o' O, p/ }' |% Y* R1 C7 ~
- }
复制代码
* w, s2 k6 y+ M1 ]在初始化的时候,要注意一个问题,STM32F103单片机的DAC输出通道有两个。8 y- l8 U& t0 @' T* `
" ^; V0 Z! u/ {3 M9 p7 O! Q( ]! o
6 I4 r: a7 c, H* A# W: q( a, D: T. n
' l8 v9 C- n2 a' o' a. C- R! m6 w* xPA4和PA5,但是在初始化引脚的时候,要将PA4和PA5初始化为模拟输入功能。这个在官方文档上也有说明。) W) I2 w$ X7 s: M- {/ ^& ]
4 W# | v" J# l# r2 e/ G1 J- `
- m+ {- U$ y# n0 Z: A! `/ a s
: a+ m T* A" a8 L' i 内部自动就会将PA4和PA5与模拟输出引脚连接起来。所以在初始化的时候,虽然用的是输出功能,但是还是要将引脚设置为输入。, W. J7 o1 q! S6 _0 R
+ R# Q# V$ \6 H* M% d. y 初始化引脚之后,接下来初始化DAC功能,在这里不使用触发功能,也不使用波形发生功能。直接通过软件来控制* h8 x: o q- }6 q# [7 I" }$ M4 ]
$ E. l# t6 S, i `9 D, e
接下里通过一个函数将要输出的电压值换算为寄存器的设置值。DAC的转换为12位,所以最大值就是2^12,也就是4096,而stm32单片机的供电电压值3.3V,所以将要设置的电压值除以3.3,然后乘以4096就是DAC寄存器需要设置的值。
" a3 N' B) a6 i9 T2 @
L8 J0 [# U7 V! u; J 如果要输出模拟电压值时,只需要在主函数中调用DAC1_Set_Vol()函数,并将要设置的电压值传递给这个函数就行了。
3 B3 u8 S* K& C5 _, b D8 p
$ V1 u8 C8 n2 U8 A. \- int main(void)
0 `+ k5 I! u/ N" R( }) Q+ C - {
- Q1 z- |% {& G. L4 N0 ] - u16 adcx;* r" R( i& p$ K* `$ ]
- float temp;
; J( |2 N1 J5 ~7 Z; `# v - u8 t = 0;6 I8 a! o% H3 G! Z
- u16 dacval = 0;% ]8 p$ V8 H& T
- u8 key;
N6 n9 S/ X! |; \4 Q
) r* d' ~( }# S C- b- delay_init();7 O+ v2 w8 T. Z. |
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);, w( T, G' w$ x+ m; K
- uart_init(115200);" x: v) \2 d" m$ _7 o1 x# c
- LED_Init(); k: ]/ R4 e( {5 Z+ ^9 S+ a" B& G
- DAC1_Init(); - i* ]8 G9 o1 _( ]
- while(1)4 i3 q: s- Z' u) q
- {
( D" [0 p) P; c - LED0 = !LED0;6 ~- n3 r U4 Z/ j
- DAC1_Set_Vol(1000);
' k0 R* P8 _2 A$ d - delay_ms(100);4 a" ]- o0 h( |7 X5 v5 z$ a. |
- }
4 K2 P0 G& z& H# A0 B1 O - }
复制代码
! h% d( s0 x3 O' a. C在主函数中设置DAC输出的电压值为1000,也就是1V。这时通过万用表就可以在stm32单片机的PA4引脚量到1V的电压值了。
: P2 F- [/ ~+ J% b1 a# |) n8 G5 S, u# [7 f0 V! i/ |& f$ R
. I+ |5 z! ^! W6 Q/ s; Z
* m- E. y, F5 a, G6 w* e
|