01. DAC简介/ |, l( X! y7 H, s% x z6 f
STM32F4的DAC模块(数字/模拟转换模块)是12位数字输入,电压输出型的DAC。DAC可以配置为 8 位或 12 位模式,也可以与 DMA 控制器配合使用。DAC 工作在 12 位模式时,数据可以设置成左对齐或右对齐。DAC 模块有 2 个输出通道,每个通道都有单独的转换器。在双 DAC 模式下,2 个通道可以独立地进行转换,也可以同时进行转换并同步地更新 2 个通道的输出。DAC 可以通过引脚输入参考电压 Vref+(通 ADC 共用)以获得更精确的转换结果。' Y! Q0 Y9 i* d& o
$ i# _8 u: {) _8 V1 _STM32F4 的 DAC 模块主要特点有:8 Q1 a+ v# {' p+ Q& k; }9 w1 ^6 K; i, D
① 2 个 DAC 转换器:每个转换器对应 1 个输出通道
/ @* i0 v4 o3 s② 8 位或者 12 位单调输出
9 M) E) F7 t! ^1 d! \③ 12 位模式下数据左对齐或者右对齐 C$ z% J. w0 H7 m3 O8 i
④ 同步更新功能' c: T; j) G) d/ A/ z; N
⑤ 噪声波形生成
0 Q3 u Y9 r. F' l! Z* F⑥ 三角波形生成* r. G9 ^5 R c3 S
⑦ 双 DAC 通道同时或者分别转换
. G. x/ t y ~' Z+ ]⑧ 每个通道都有 DMA 功能
4 }5 r( K# K8 O r% z
. Q' g8 p$ |4 N7 B F+ `, U02. 硬件模块
+ w* c3 D5 b/ [: F' h) P1 P2 ]# x用到的硬件资源有:
! G2 M$ k# M& J, P( s1) 指示灯 DS0* d9 V, D; d. C$ S0 \: ^
2) KEY_UP 和 KEY1 按键- c' D: b% @' S$ B
3) 串口+ p: @1 j- I3 H- S
4) TFTLCD 模块, g; N; O& \6 X8 c& o& X
5) ADC1 s3 Y( A( j) `/ b0 n. J# L
6) DAC
1 ^" @" a# i5 z0 R1 u' ], \2 k8 X) A" q( U& c' f
03. 程序设计
) U) u. o8 r/ O" G! y2 udac.h文件7 j/ f1 A5 M) j+ T p7 {: T
' K# v8 }% `( I: H7 R# A; h/ M
- #ifndef __DAC_H
( o! K- K* H" _' M. ~4 z - #define __DAC_H
6 S( g* n# |* ^. e& w* s - #include "sys.h" + p! ~$ V+ S: w2 n$ b* l8 v
+ k" p: w0 k/ T$ G+ c- void Dac1_Init(void); //DAC通道1初始化 $ m9 d% U* O' k7 o: |" a" V0 e
- void Dac1_Set_Vol(u16 vol); //设置通道1输出电压$ ?: z% E( M1 e8 @
- #endif
复制代码 - l3 {2 E! F) ^
dac.c文件& ~: B7 M U' D$ a s4 `% C N' j
, {. s! y0 ]% |8 v! p% ~- #include "dac.h"9 D# }2 J: I, m2 A4 o5 t
- ( g4 o [" y% ~) }/ ^! ]
- //DAC通道1输出初始化
8 b+ P+ T4 E% E# T& O9 m - void Dac1_Init(void)
d' }% l( V; w+ d$ d4 r - { / H) ?+ ^# u3 H+ {
- GPIO_InitTypeDef GPIO_InitStructure;
. [& \3 `$ {$ n2 q) B7 P' [5 D - DAC_InitTypeDef DAC_InitType;# F5 b! v0 Y' S1 ^
- 7 P0 p1 _/ k, Q& L% Q. v
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
: _! f. ~0 P! ?6 [7 M - RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使能DAC时钟
v5 b. [7 M9 B' ?' F/ {2 e
& L# A8 O& R8 ^9 z/ t; a3 x q- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;2 C" Q5 v; M( w8 J0 }
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入$ C5 e: i/ N6 E5 `# b7 p) v
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉
' ?% w3 j8 S/ n, s; R+ @ - GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
$ l8 N: _. N2 Y, R6 s; Q
, X8 I/ Q" i5 z& {. s0 N- DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 TEN1=0% `. |& x" i( {) s" W' }3 ^1 g9 s
- DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
8 m! P# `1 R9 i; R& u' J - DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置- ?% }, j, b- V6 A& v
- DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
2 |' V- e; T! d! R - DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化DAC通道1
& z% y* I j; ^8 S - ' o$ j9 `0 L$ r& C, ?7 @
- DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC通道1
: r$ r& A4 M$ {4 E$ o7 t - 9 J! D* ]7 Y. ]1 m
- DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值! E9 l! Z1 w9 T6 j
- }7 b8 P0 D6 C( E' H3 m
- //设置通道1输出电压. v9 Q3 |1 E8 J! I" l) N
- //vol:0~3300,代表0~3.3V
- j7 E3 E3 B/ z - void Dac1_Set_Vol(u16 vol): T6 N3 d1 W. h4 s
- {* N$ F; {* f0 r; O& F. `
- double temp=vol;
0 m' a* h- M' ^ - temp/=1000;
# I3 Z4 O7 U \8 i/ p - temp=temp*4096/3.3;
( E2 b$ Q- Z: c. h: ? - DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值
, c: g, w: ^% T! ?+ t2 ~ - }
5 {) F! B/ I4 t. i
复制代码
, E) r" f* j4 u! N' Dmain.c文件
; e9 S6 t3 O& O- X; p
! @4 U. ]* L- X) k, P- int main(void)
z& D' V5 ] z5 p. t - {
5 Z) E4 \8 w2 O - u16 adcx;
; q9 M% r6 z: D1 D - float temp;
9 z' y ~4 B- e1 U - u8 t=0; * Y) s8 ~ [0 z& e: C; w7 F
- u16 dacval=0;6 F" C/ U" C: a
- u8 key;
3 L" |' ~# ?9 K9 Y: l, ]% m6 u - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2; X& F$ j: i5 r, A, z$ t
- delay_init(168); //初始化延时函数
f" U% s$ V$ s' U" L - uart_init(115200); //初始化串口波特率为115200; n) O% B) w3 t0 Z
-
( J+ T0 `3 |/ I1 d% O - LED_Init(); //初始化LED / r- c( O- @8 f1 p
- LCD_Init(); //LCD初始化
, t1 R* i+ y& [& w - Adc_Init(); //adc初始化+ h# U6 C3 e7 ~0 c
- KEY_Init(); //按键初始化
6 G" J5 u; N- T) U - Dac1_Init(); //DAC通道1初始化
/ C: i3 p9 |6 S7 w$ F - POINT_COLOR=RED;
}1 n7 M! j( I% N - LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
# K; q' q2 X" ?& Q2 {# M; r - LCD_ShowString(30,70,200,16,16,"DAC TEST"); ! }! h& j( S' B
- LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
( [ M+ I2 `9 ^1 i# I" q/ C - LCD_ShowString(30,110,200,16,16,"2014/5/6");
4 Q, O$ a: M, Y H4 {( `# ]. o; y% y1 Q1 d - LCD_ShowString(30,130,200,16,16,"WK_UP:+ KEY1:-"); v1 {) g5 d! z8 M( M8 B: n. Q- @# K
- POINT_COLOR=BLUE;//设置字体为蓝色
) D* M- H6 L( Q - LCD_ShowString(30,150,200,16,16,"DAC VAL:");
: E+ p) O) Y: G% b* J - LCD_ShowString(30,170,200,16,16,"DAC VOL:0.000V"); ; \+ Q) f; c7 W0 ~ k+ R6 f
- LCD_ShowString(30,190,200,16,16,"ADC VOL:0.000V");3 s1 `3 Q" z, d, r% [
- % J6 ~0 m' l. G( ~
- DAC_SetChannel1Data(DAC_Align_12b_R,dacval);//初始值为0 $ t; C! Z! J' {8 N2 U8 t5 I
- while(1)
* B3 q j' R8 C& @ - {
, D9 f& M% t% P, E% c7 g F - t++;
/ y, `! q+ S9 k$ p2 d- V' T - key=KEY_Scan(0);
! b4 c! S/ v9 }) n$ _ - if(key==WKUP_PRES)
0 \0 @6 r* ]) y3 N, o } - {
$ r+ I4 t8 \* R/ S& F8 L% P7 S+ k - if(dacval<4000)dacval+=200;
- K" e7 c3 G3 [0 g; x% ^% Z - DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值: [! I& m2 I! q$ q, w
- }else if(key==2)
8 O7 x' }. f5 Z1 ]# c - {5 j# W0 C0 e6 r2 U8 j
- if(dacval>200)dacval-=200;
6 J! x) I0 P3 ~) [7 X - else dacval=0;
2 J7 u) q( ]0 l; a - DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值
7 t0 z6 X& ]. V1 Q! u - } 7 T5 Y% k( Y& u- v
- if(t==10||key==KEY1_PRES||key==WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了2 k5 r2 w! P/ O% G
- {
# g' b; u2 o, v: l - adcx=DAC_GetDataOutputValue(DAC_Channel_1);//读取前面设置DAC的值 M! S: l, H+ L2 M$ x
- LCD_ShowxNum(94,150,adcx,4,16,0); //显示DAC寄存器值# J6 t0 [ o2 I! X6 t4 V5 l
- temp=(float)adcx*(3.3/4096); //得到DAC电压值
3 \ }& q% W9 l' o - adcx=temp;' L0 m( u$ O; Z; o
- LCD_ShowxNum(94,170,temp,1,16,0); //显示电压值整数部分
2 E: S* V3 r- { - temp-=adcx;
- [+ F# e3 j+ z0 j9 w# M+ f- i - temp*=1000;, m* q# K4 \. N, Q1 ~7 b) N+ F
- LCD_ShowxNum(110,170,temp,3,16,0X80); //显示电压值的小数部分
. t$ n {5 ` y, U - adcx=Get_Adc_Average(ADC_Channel_5,10); //得到ADC转换值
- r5 U7 u1 U) a: _# V - temp=(float)adcx*(3.3/4096); //得到ADC电压值
$ f2 u* u5 x: V7 L" ?7 C - adcx=temp;
8 S' Y' l! f( ? - LCD_ShowxNum(94,190,temp,1,16,0); //显示电压值整数部分' k- Z z4 v# E+ {6 ~2 p
- temp-=adcx;; y2 a3 U! b5 B8 ^3 Y1 Z7 a& j
- temp*=1000;$ |$ |9 E5 {, v; D
- LCD_ShowxNum(110,190,temp,3,16,0X80); //显示电压值的小数部分& K0 o9 p& }8 I4 L# F- r) c
- LED0=!LED0;
& M/ H* i7 S8 S9 y s. P - t=0;8 b. V( q8 M3 U* C6 w5 }
- }
! R+ Z1 ]1 T! ]" N0 o# w - delay_ms(10);
. k& e9 v4 B2 { - }
2 \& ^8 P% v1 p2 _- s; c& G+ I - }* x5 \9 `" M- H' ^8 H7 J" H
复制代码
0 n# H: p" C! M( V04. 结果验证. p% d3 O! G: {: M4 b+ G6 _
同时伴随 DS0 的不停闪烁,提示程序在运行。此时,我们通过按 KEY_UP 按键,可以看到输出电压增大,按 KEY1 则变小。" d- r. R; f6 g# d) h# v
6 g8 S. _7 J0 j2 a) @
0 V- P. B0 E! y: j& ?0 ]+ F7 J% E( x% {$ e( v: f
|