STM32F1自带的DAC模块的使用。但有时候,可能两个DAC不够用,我们可以通过PWM+RC滤波来实现一个PWM DAC。本章将向大家介绍如何利用STM32的PWM来设计一个DAC。利用按键(USMART)控制STM32的PWM输出,从而控制PWM DAC的输出电压,通过ADC1的通道1采集PWM DAC的输出电压,并在LCD模块上面显示ADC获取到的电压值以及PWM DAC的设定输出电压值等信息。
, \! D+ C! O- S/ u7 f6 d2 Y$ m" H5 z
h$ |# T" a- Q3 p% {1 @
, N$ M* j5 B Y) k# [
/ P8 S9 N# O. ] s: s
$ ^) d6 U2 J0 ~2 C1 s
8 j4 M: K: |) l) Q6 e/ D5 O" w/ d
0 J6 R' t# r7 r# K% A
! `% e1 y: G9 Q; {3 U" A4 @
+ ?" z% R e6 }1 S( j
1 f& C3 W3 d C) e W7 b( X
1 t' r4 G; H5 z" p
1 w8 x* H% l* y; Q. t* [/ z/ H: K6 D+ m- C/ d! ]
, N& u4 {* }9 ~1 K( n) h
- G" c* Y# f' U6 R; m( H
. m; k# c) J& ^' ?( m. Mmain函数
$ x4 M2 v: v( P1 E7 C g- #include "led.h"
/ w/ i7 v# v% l! W7 ^ - #include "delay.h"( Y/ m" f( ~5 }3 ]; W! {: ~' m
- #include "key.h"
& ]: u4 H' A- r/ l { - #include "sys.h"( q' B, }- d- H! q& c
- #include "lcd.h"- y9 {4 t. A! K) ^3 {; m
- #include "usart.h"
$ ~8 {; y" E- d0 n - #include "rtc.h"
. R2 d' R/ s8 o" c" u# p - #include "wkup.h"
' o( f: s- \/ b; a - #include "adc.h" " B" `5 |% j) H! [- ^# T
- #include "dac.h"
$ B/ l9 i p! m/ W - #include "timer.h"
2 c0 H# ]! D8 \( @- J% J - #include "usmart.h"2 {' J R* T5 K8 q
- I% D6 ^0 w% H6 M+ M7 W9 _- //设置输出电压0 y9 e. B$ g9 U: t
- //vol:0~330,代表0~3.3V
# w4 j5 v2 E- I8 |# u/ Q) H4 H - void PWM_DAC_Set(u16 vol)+ ?$ a# G1 k& J' ?
- {
( A: X I7 g0 J6 l1 _" U - float temp=vol;
$ I# d- X* l; a; s; Z( W: N) g - temp/=100;. L0 A9 z: \/ f- u5 S3 }. j
- temp=temp*256/3.3;
6 O6 B2 n) n: r - TIM_SetCompare1(TIM1,temp);/ }! @ [; A& K- @
- }7 x+ T8 W0 u) j4 |
- ( w! E7 E- J' a
- int main(void)
& K, m# T) g& c- `3 d - { : ]; J& i' u: D3 N! i- F: R
- u16 adcx;! o- r) {2 x* U D
- float temp;
: _' M6 @6 C6 J3 d, z, U3 ], V - u8 t=0;
2 e3 b2 I. n( i8 T) l2 y; H# c - u16 pwmval=0;
; [# F# A" U" H, n5 e5 Z L+ V8 Q - u8 key;
' ~4 j1 \% J$ I. y9 t -
* e0 C* w0 }' f+ y1 d9 c7 i3 [ - delay_init(); //延时函数初始化
* ^! a0 y* x% z+ |- q) s7 ] - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
! h! Z7 d- c8 n2 X0 ]6 V- k - uart_init(115200); //串口初始化为1152008 V: P/ h. l) X4 G, g( | j9 m% r
- KEY_Init(); //KEY初始化) r$ f# X" M4 r9 g X9 }
- LED_Init(); //LED端口初始化# Z. c: p! t5 k- P1 B1 O
- usmart_dev.init(72); //初始化USMART : ]* C/ O5 v" W ~
- LCD_Init(); //LCD初始化
0 H" M7 U: q7 L, T- W) z; c - Adc_Init(); //ADC初始化
5 D; J- i) q' C; J -
1 m0 s! e) q0 a; R - TIM1_PWM_Init(255,0); //TIM1 PWM初始化,计数周期为256,Fpwm=72M/256=281.25Khz.
& w' N" P7 t. h; c- H% e - TIM_SetCompare1(TIM1,100);//初始值为0 + ?& {& W# F: z4 b. g4 I# T, U
-
; Y2 E# B5 ?, S3 p$ _( r - POINT_COLOR=RED;//设置字体为红色
& w) _: J- J% l3 x& [ - LCD_ShowString(60,50,200,16,16,"WarShip STM32");
7 A u. |/ R6 M - LCD_ShowString(60,70,200,16,16,"PWM DAC TEST");
2 a L& C# y8 b - LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
$ ?) B7 t. ?2 a+ n, D - LCD_ShowString(60,110,200,16,16,"2015/1/15");
- w2 ^0 \3 o' C* s" \2 Y2 S _' ? - LCD_ShowString(60,130,200,16,16,"WK_UP:+ KEY1:-"); 4 e! V: G S# f" ]) A1 @
- //显示提示信息
3 {# i7 Z& {% z - POINT_COLOR=BLUE;//设置字体为蓝色, n; _5 H; V p5 B- K! ^7 K
- LCD_ShowString(60,150,200,16,16,"PWM VAL:");
; q( T$ f, \+ b. k" L - LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V");
2 }6 p/ y) I( N& ]- U3 T - LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");" G5 m/ j* S5 i
- " q7 e$ F1 E) n; v/ Q! C# u& Q( |. \
- TIM_SetCompare1(TIM1,pwmval);//初始值 ' R/ ~+ Z3 P9 }, k1 g
- while(1)9 w6 P2 e2 z ]4 i# V/ a. ~6 }
- {6 k! C% H: j4 C0 ^' d6 Z
- t++;4 Q/ {! P. q$ u' H! u @
- key=KEY_Scan(0); - t: x7 d% _( O8 `# h
- if(key==WKUP_PRES)
. g1 a# _, f) T2 j, A - {
5 |9 D2 O1 M/ d6 R# @ - if(pwmval<250)pwmval+=10;
, E% J, s( k5 t3 D$ Z - TIM_SetCompare1(TIM1,pwmval); //输出
& }9 P* {" v+ E# v# F6 W! u - }else if(key==KEY1_PRES)
$ [. A# d9 O2 \, I9 ` - {
; v# }" N# G9 b2 u2 u, \4 D - if(pwmval>10)pwmval-=10;
+ b1 s. n. ]8 C E - else pwmval=0;
- d+ o+ K! R, G. J( t - TIM_SetCompare1(TIM1,pwmval); //输出
- `1 [& {4 f: z - }
' w& N$ y' I# I, @; D -
$ F' [ ?$ c6 c - if(t==10||key==KEY1_PRES||key==WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了
: t- F5 v- p5 _; C. s' m4 W - { $ A+ x" v) r P; R* }
- adcx=TIM_GetCapture1(TIM1);" [- H$ S S* I
- LCD_ShowxNum(124,150,adcx,4,16,0); //显示DAC寄存器值% ~3 Q: h3 K/ {3 v* N# e+ j" ]
- temp=(float)adcx*(3.3/256); //得到DAC电压值3 D/ L: A$ H7 m- f' k8 I- a+ p# ~& b
- adcx=temp;; r; m8 a8 U a' R, Q
- LCD_ShowxNum(124,170,temp,1,16,0); //显示电压值整数部分
9 w% t. Q n) Q1 U, B8 `: W - temp-=adcx;
J! \& E7 k6 y* [# C7 {* [ - temp*=1000;$ L. ^' c" H ?" z
- LCD_ShowxNum(140,170,temp,3,16,0x80); //显示电压值的小数部分$ c9 {) p$ w3 z; r
-
( m5 [% A5 I5 t: p0 q) c - adcx=Get_Adc_Average(ADC_Channel_1,20); //得到ADC转换值 - {/ U3 K/ ]- L. [! j5 S2 ~3 r
- temp=(float)adcx*(3.3/4096); //得到ADC电压值# N$ e: R! K1 ?' |( K& l
- adcx=temp;( r) D1 K3 F+ \1 n! m: b
- LCD_ShowxNum(124,190,temp,1,16,0); //显示电压值整数部分( l& B) E g: O1 m! `; s. ]
- temp-=adcx;
% a5 i3 U2 J: Q3 j0 i* \ - temp*=1000;( h/ `: R) F d( c" l
- LCD_ShowxNum(140,190,temp,3,16,0x80); //显示电压值的小数部分
7 x$ E( v }7 m" P& U# f; N: L - t=0;
+ U% @# R3 @# } - LED0=!LED0; : U1 V7 h. |- m# A# A' o/ p: [
- } ! T% F+ F( F3 d# R3 p) }1 j
- delay_ms(10);
8 d) C) l+ U; n/ e3 ` V - }
, R8 l! B) N9 X) R9 s* _: f - }2 c9 g1 H3 v( H* v1 W! r% B3 ]) H
复制代码
9 {7 S& X7 V/ g" I
3 u/ [$ o# W. Q+ Q" Mpwm_dac.c函数
5 z% t9 B5 P# h) \- //TIM1 CH1 PWM输出设置
* ^2 ~9 j8 l% M% |% d - //PWM输出初始化
' [9 n3 p/ C! E4 f" ~ - //arr:自动重装值
( P4 L6 o, g6 C- C! { - //psc:时钟预分频数; e* N. |7 Q9 V# a& r& ~& t
- void TIM1_PWM_Init(u16 arr,u16 psc)
+ B+ T2 h0 j v+ v8 z$ e4 m - { 3 {0 _5 w0 N3 Y) ^; h; U
- GPIO_InitTypeDef GPIO_InitStructure;
% k. w9 t6 x/ `+ c9 ~" ^( }0 }4 w - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
3 f( k( W. Q8 C1 e - TIM_OCInitTypeDef TIM_OCInitStructure;3 p' d: t: v2 M+ \8 x; C% `* _
- / W6 g- G! a, E. d7 f! w( }* M
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIMx外设
" Q# Z5 l: D' W - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设时钟使能: C. i( N' k7 D2 D3 y1 j
-
) T2 {$ ~) U! B; Y* F. w) \5 R: O - //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形. a& }6 D. m7 H2 S
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH1
& |5 ]: s+ w6 v! _+ I2 c$ e - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能输出
' w8 i4 T3 C. n% }. g - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;, S3 X4 b- h1 ]0 P+ W9 a
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO I, |$ P" v9 E9 r- f5 B
-
$ |2 o3 s6 r, ^! i; M3 V: u - TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载周期值1 U# S W3 D9 [& E5 ^
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 不分频
' C* u9 S2 W( Q+ r' ~+ \) O - TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
5 I6 ]$ q }# B, B/ x7 R3 L; r# E4 D - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式5 f3 Y9 w0 }/ Z& F* n7 ]
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx e' }5 k/ k5 \
-
L) V, ~" D6 N4 m9 P6 n - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //CH1 PWM2模式
5 W4 c( y( c& P( U. @/ [ - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能0 {2 A' a: y. v" H/ B
- TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
/ X# c" O$ S1 o( K, Y3 p) c9 k0 ~: ? - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //OC1 低电平有效 ; Y) r- a* a9 H6 s# a; a
- TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据指定的参数初始化外设TIMx/ X6 v" V$ U' b& V; V
% u) T: t! [0 |0 O. d! x7 ^- U- TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1 预装载使能
- B. x) G. x) b -
- M$ w+ f; q, G- t3 ^% ` - TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器4 o3 P5 p, S: N' B8 s: s/ X* I v
- ' }3 d" Y" w* _' [' t
- TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能,高级定时器必须开启这个 2 |3 C2 P+ D8 Y% f
- / Z' z/ ^; Y- C
- TIM_Cmd(TIM1, ENABLE); //使能TIMx
9 o2 `4 ?' p$ v. C2 v - }
' _$ }3 z2 V9 _7 [8 D. A4 X
复制代码 % _; L e- V5 \' [ H* l1 f+ J
$ h! ]- a; Y5 d8 O————————————————
- ^6 z) Q- ]; ^+ {版权声明:_Amen: o; U. j7 `, U& [; B
如有侵权请联系删除+ x' Z& u4 j' c7 K) ~( `: M# q" z; ^% v
( U* f. k! x$ _6 P2 j! s
2 g( N0 G5 s$ A ]' t
|