STM32F1自带的DAC模块的使用。但有时候,可能两个DAC不够用,我们可以通过PWM+RC滤波来实现一个PWM DAC。本章将向大家介绍如何利用STM32的PWM来设计一个DAC。利用按键(USMART)控制STM32的PWM输出,从而控制PWM DAC的输出电压,通过ADC1的通道1采集PWM DAC的输出电压,并在LCD模块上面显示ADC获取到的电压值以及PWM DAC的设定输出电压值等信息。
8 N( @1 L6 p7 w ^2 ^9 z1 L. y! y2 z# }5 `, K( M
) T# x( o# H; s+ u/ P+ e! d
5 p$ h: E% D; u0 r: Z- h* [7 M: m; @( r+ `
' U; n. B, C: i: u* R6 R8 `
/ {7 W5 _! ^+ _. a3 j- ?
$ v+ q: L9 p4 f* U3 G4 |
" [) K* r8 Q2 s
$ P* j' O& e! o
: W! c4 @6 K2 B! O1 k/ G. ]8 q$ ^. a4 ]
$ _- _- N9 u* R7 p5 A( U
9 [, O- g# S; G5 z5 L/ {) Q
/ g+ N/ p& w6 f4 K( _) }- z
: J( K! x- V" g- c& d$ C
9 T, j; c/ H* s5 t; U6 Z0 Dmain函数
y, z7 [2 A) K2 w- f. f! }5 e5 J- #include "led.h"! R) k/ l8 e' p5 R
- #include "delay.h"9 A2 A& n0 D/ N4 g6 H% E
- #include "key.h"
8 U/ G5 g9 `2 f3 T' c# ^ - #include "sys.h"
. |- f. k |5 |( O" A+ T6 S' Q ? - #include "lcd.h"
* Q( c* r0 C/ l7 Y: ]& X0 U - #include "usart.h" 1 Q) L- E: M% x0 t3 \* ~, v; U9 C
- #include "rtc.h"
# _ T, t5 y+ ?& p. i - #include "wkup.h"* S6 A! I h9 N1 s- A* k8 K. m" b
- #include "adc.h"
5 Q- ~; {, R! q$ H5 \% {) R - #include "dac.h"
$ W) B) t+ ~8 _5 r+ [ - #include "timer.h"
. |7 `8 b) Z; n+ O# X - #include "usmart.h"! `' G! W' {6 x9 n
- + ~' {6 d/ ]6 O8 W/ c2 G7 v% a
- //设置输出电压3 J( g+ I0 G! d/ b, x! T9 E" i' K
- //vol:0~330,代表0~3.3V6 E- ?) ]5 V; r) {+ y; V8 Q
- void PWM_DAC_Set(u16 vol)
" K6 @! ?: `9 w+ S5 S; U) q, s - {- ^1 ~1 N' I+ n& \
- float temp=vol;! X+ h- _, q) f" ]8 I- E" n: j, ^
- temp/=100;
' y9 b9 m8 U! s: a/ Y - temp=temp*256/3.3;9 e3 s" i& m3 y
- TIM_SetCompare1(TIM1,temp);
0 ^& x4 a: B, B6 P8 M4 b8 _ - }
9 }' \1 Z' z4 \' s, k
3 |4 l9 R% D3 I: X }6 _- int main(void)
6 ]( @ E& X6 \6 a - {
+ T6 F9 x6 B- Z: h - u16 adcx;1 i+ X" _; e) I; L. J) O6 A* Z# M+ U
- float temp;3 n B, l9 a) V0 @
- u8 t=0; + v! C8 ]1 O, j
- u16 pwmval=0;! X+ f" Z3 I' B! Y% [
- u8 key;" K" o" e& K$ J- d
- ! n; d( W/ ]* K0 L/ j
- delay_init(); //延时函数初始化 & @1 C! a4 d* a! U1 E+ }& e
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级( p0 k2 F$ `$ U/ A! j
- uart_init(115200); //串口初始化为115200# \+ J Q8 `/ f. O M! T, _
- KEY_Init(); //KEY初始化. n) D; P+ l! q: q$ {
- LED_Init(); //LED端口初始化
% o9 ^! W9 F `! H - usmart_dev.init(72); //初始化USMART
+ q+ A2 H% I7 K. c - LCD_Init(); //LCD初始化
" @4 x% j$ E' z0 X& a - Adc_Init(); //ADC初始化! P9 h* i4 `3 i0 f- i
-
$ l2 d0 R/ s; [7 c, ^ - TIM1_PWM_Init(255,0); //TIM1 PWM初始化,计数周期为256,Fpwm=72M/256=281.25Khz.8 n8 z% E8 H& n J' p
- TIM_SetCompare1(TIM1,100);//初始值为0
# d* {/ B: w7 T6 j* r: u -
2 u4 f! K8 T! [! k# v6 K - POINT_COLOR=RED;//设置字体为红色
& n' Q/ Z* G1 e9 z* @# T - LCD_ShowString(60,50,200,16,16,"WarShip STM32");
( ~: Y s$ w0 N& B; v- S3 O9 _ - LCD_ShowString(60,70,200,16,16,"PWM DAC TEST");
1 H5 N9 ^3 B. N% e' J. } - LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
; o2 \5 A) D1 b, T5 K - LCD_ShowString(60,110,200,16,16,"2015/1/15"); H( F' m! K$ n2 N
- LCD_ShowString(60,130,200,16,16,"WK_UP:+ KEY1:-");
0 i! R+ G7 Y i5 ]! g6 l - //显示提示信息 + b" x. K, k$ r% T
- POINT_COLOR=BLUE;//设置字体为蓝色# K G* j, X2 `1 C' ^
- LCD_ShowString(60,150,200,16,16,"PWM VAL:"); , k5 |' d( ~6 P+ N* D4 B
- LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V");
: e# D0 J, A; |* a8 ]) D E - LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");$ Q. y1 @/ y8 G0 P
- 9 L7 V+ M# M+ @' k8 F5 M
- TIM_SetCompare1(TIM1,pwmval);//初始值 : w2 s. f! z! ] {
- while(1)! ]# @1 D! p6 ]2 J
- {7 ]- l3 Z4 V; `% @8 |
- t++;9 u* \& t4 z" `: t
- key=KEY_Scan(0);
4 R! \+ u3 ] d6 a& c - if(key==WKUP_PRES)
B4 P5 _0 G. w - { - ]6 k* e0 N, b% C/ S$ w
- if(pwmval<250)pwmval+=10;( S/ I& ? ^- ?" L
- TIM_SetCompare1(TIM1,pwmval); //输出& h7 C' L. h1 i' G% p1 h
- }else if(key==KEY1_PRES)
7 q, O5 B: I! @' r) v( J) e% x c - {
1 Y/ I0 d* n y - if(pwmval>10)pwmval-=10;& _/ b T: Q( u2 b. t# A: h8 T) l/ j
- else pwmval=0;
5 }) }% I$ a$ V - TIM_SetCompare1(TIM1,pwmval); //输出& ?# ]2 @ L4 h) Z; B' j
- }
3 ?3 L" ?" f \ s( g -
" e% Q7 v. r2 n3 B T, H; S - if(t==10||key==KEY1_PRES||key==WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了) q+ O/ f R% F, t5 \+ R9 q& Q
- { G0 e! f( B, ?
- adcx=TIM_GetCapture1(TIM1);! M( n( ]: q: r- o" J1 e
- LCD_ShowxNum(124,150,adcx,4,16,0); //显示DAC寄存器值* _- l9 s9 J( D/ W' |# y8 t
- temp=(float)adcx*(3.3/256); //得到DAC电压值
& e N0 r7 z) O+ A - adcx=temp;
5 X3 Y' Y m! e - LCD_ShowxNum(124,170,temp,1,16,0); //显示电压值整数部分
7 u" ?; g) L, M8 P; w1 }: T$ a - temp-=adcx;% t' @5 |+ n8 d8 J: q
- temp*=1000;
4 q( q) x1 t1 i7 l - LCD_ShowxNum(140,170,temp,3,16,0x80); //显示电压值的小数部分
2 W5 R e3 w6 t. g5 v7 ?, ] -
/ z0 m/ \) T' `6 u) ]6 b7 ^8 E - adcx=Get_Adc_Average(ADC_Channel_1,20); //得到ADC转换值 3 t7 m) q$ H& y t# p
- temp=(float)adcx*(3.3/4096); //得到ADC电压值/ U2 z+ s# {5 N- g1 F4 T7 X
- adcx=temp;8 g/ C) W/ T" l
- LCD_ShowxNum(124,190,temp,1,16,0); //显示电压值整数部分
8 ?% \, B; s Q- ] - temp-=adcx;( Q3 J* }& d$ m+ R5 g I
- temp*=1000;
N' G! h* v1 L2 q - LCD_ShowxNum(140,190,temp,3,16,0x80); //显示电压值的小数部分
9 \' @2 ^- |4 |, A0 R4 x1 H: o - t=0;
4 o0 @- b8 b, G! T9 U) E - LED0=!LED0; - p# I+ M2 `6 J1 R' Q5 [) S
- } / m; x8 j s$ n+ o5 z
- delay_ms(10); 7 R3 ?7 a! u4 P( f# R4 L7 ?0 T
- }* z z- U& h. ]1 b" g' p0 `
- }# [; D' t; y6 n- Z* U' ]* P
复制代码 : w% M7 {9 V! f5 J. ~% E
1 t2 c/ e! A9 x |$ ?- _
pwm_dac.c函数" ^0 S u: q$ C: F( U% N9 D: n
- //TIM1 CH1 PWM输出设置 ( U5 w3 F8 J& }4 ]
- //PWM输出初始化/ ?2 f) I) N# e' @; F9 V+ O: w
- //arr:自动重装值
1 a3 B' F+ \8 y7 h! b9 H/ n - //psc:时钟预分频数
" ^+ n( R6 w7 I( _7 Z - void TIM1_PWM_Init(u16 arr,u16 psc)
# S& Z4 v5 h' b4 y/ A - {
0 A$ j( ?4 O# b - GPIO_InitTypeDef GPIO_InitStructure;4 h3 ^, I9 W2 I3 M1 a3 Z
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;4 h! f/ c; C: Y: M% P
- TIM_OCInitTypeDef TIM_OCInitStructure;
4 n, U4 F6 `9 ?" K% e' E8 b: X - ( t' Z: ^* O" s# Q3 A8 o' }, J. P
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIMx外设
6 H9 C" l8 w% F! t - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设时钟使能# _9 z* w( b7 r: ]
- ! N2 D5 K7 s( K
- //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
* Z4 U; X! C, T- ~8 i( r6 L# M - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH1
9 h. y. M- C9 _' Z: c. R4 x5 c - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能输出
+ s* z7 v/ r4 W$ b9 w$ e; ?+ }" K - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
% O) H* w; G% L: U - GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO# T5 R/ W0 v, L- l. @: j
-
4 M0 ?- [/ R0 a0 _5 E, ?5 F+ m - TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载周期值
5 m% I* _: C- M7 [/ M) A - TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 不分频
1 d: s5 o. Q/ M: A" k4 D - TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim" h: _ x" J9 M+ L( Z
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式8 T( w3 C) q }/ C8 O
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx
4 v$ e* ]6 @4 t" x' K, ^ - 5 o# P0 y7 G4 d
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //CH1 PWM2模式
- t' l5 Y, t3 w& e - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
7 [( Y2 g7 o# V( u6 b$ v - TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值( O/ B% _) |7 y# I
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //OC1 低电平有效
# b9 l3 ?: Q7 ^" t' o* N1 Z - TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据指定的参数初始化外设TIMx
" j+ H# C$ k7 t! k - # K N: E& `( S& k" {6 Q* i
- TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1 预装载使能
' }; \7 T j) ? -
6 C8 R( [" }( R" r) a - TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器5 S) k# ?/ `: C, @) J! W; I% v
-
/ K5 G9 S' g; c- y* a - TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能,高级定时器必须开启这个
L, V+ [7 @/ V- I2 W2 W0 p9 H -
. R) ~& w; }& K: l8 n4 N - TIM_Cmd(TIM1, ENABLE); //使能TIMx " I# _+ X. e" N& j i7 ]" @
- } D, c4 {2 f: z, F4 _+ H! p7 h
复制代码
2 `! E& k6 n9 v# z3 Q: H/ P. o4 p, ^& p) p2 u/ s: E# |/ o y
————————————————
) \) t* i% n. x. F, a: d- b! Y- x版权声明:_Amen
3 V4 Z* c6 i/ V7 P. t+ Y如有侵权请联系删除
) D, M4 P6 ?% X- X
6 X( {, D% F, u
; k9 o4 B1 b# e+ r3 x2 s1 K |