STM32F1自带的DAC模块的使用。但有时候,可能两个DAC不够用,我们可以通过PWM+RC滤波来实现一个PWM DAC。本章将向大家介绍如何利用STM32的PWM来设计一个DAC。利用按键(USMART)控制STM32的PWM输出,从而控制PWM DAC的输出电压,通过ADC1的通道1采集PWM DAC的输出电压,并在LCD模块上面显示ADC获取到的电压值以及PWM DAC的设定输出电压值等信息。
% N, o8 T9 L+ t+ C& ~! {" d8 k6 V
( }1 V _! \# \0 i) U# u. T. |7 o& f3 J2 B4 r
8 E4 {* @8 i( B8 B+ M
0 F, h7 j& W9 O* l. [5 Y# e6 x1 U( R9 G+ _% @9 ~+ T g6 ^
' W3 m0 b* k7 t% n
( L' ^' @ f, d: F( U: N( Z8 @4 I8 u. |
3 Y" T/ X8 |% X3 e9 ^% Z2 x" Q6 B& o5 x" d& N* c& n
' @8 B( R/ r6 z5 }0 ~, L
$ l0 ?) _9 X J# h! u8 h3 u# S$ a* w! r) J6 H0 d+ ?7 p1 B. P# A- V. M
: d: A; q( ~6 r3 S7 r8 ], v0 T
+ h: C1 K! _/ U+ Z {7 {# a" y6 {; ^& M: F7 f# o- ]
main函数
/ I p+ @0 B5 c. |) X- #include "led.h"4 V: G# {8 B/ B# b" g
- #include "delay.h"
9 O! l2 n1 Y# x - #include "key.h"/ ~) z% [3 j' c8 ]
- #include "sys.h"
3 D; z& T+ \* O! p) y @ - #include "lcd.h"! u/ G' J+ F0 x5 X
- #include "usart.h"
) e B0 o8 w+ Q0 B: p0 c - #include "rtc.h" " N, U6 X7 r9 M& q
- #include "wkup.h"
! z9 y( z) p% v2 O i* A, N0 d j: K - #include "adc.h" / L( [7 C! } Y, `* [
- #include "dac.h"
9 k% F! n% U9 a8 V - #include "timer.h"
5 [+ Z. r' O6 E q) N8 t) R - #include "usmart.h"
6 K) C' I" l8 l- ]
4 [( s1 D% r! s) M7 q- //设置输出电压
5 g- t: q6 q! k2 [ - //vol:0~330,代表0~3.3V/ ?3 A) |, O7 {9 I
- void PWM_DAC_Set(u16 vol)# ^! m' _8 ]# @6 e6 b+ y _2 }
- {9 c; C. u1 Z, R* p/ E' ?
- float temp=vol;
+ `+ `! g$ d! q( h - temp/=100;& B" j. `5 y! w. o+ |# Q5 i; P
- temp=temp*256/3.3;4 Q, ?# J( ]- F2 y( o
- TIM_SetCompare1(TIM1,temp);- z6 a$ ^, B" N' ?
- }
) j [0 e+ {) b G
4 F0 d: W6 u4 ~9 c/ {- int main(void)# h1 y1 ~' C0 R v
- {
, m0 O! r% P! b1 N& E3 l - u16 adcx;3 K0 \9 K+ S/ B# p/ s
- float temp;
, o+ `7 _9 ~. a9 j+ c$ S - u8 t=0;
) f0 q8 x, ~1 w& A0 d1 d$ g! ^* T" g - u16 pwmval=0;) y: `6 ]# s# J ^8 j% K: D+ b4 x
- u8 key;
$ W6 n0 O# O, L. p8 p5 r - , r- Q9 m, W0 }5 \& K k
- delay_init(); //延时函数初始化
! R8 m" u7 w6 g! y1 E! H5 G - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级+ L1 O9 v5 i/ i5 p) E5 ^1 J, f X
- uart_init(115200); //串口初始化为115200
% }5 x5 q! ]2 h$ S7 y( H% E/ b - KEY_Init(); //KEY初始化
b a2 R* i4 e) b - LED_Init(); //LED端口初始化: g! ^; f5 k0 U7 t( v( J& \& ?
- usmart_dev.init(72); //初始化USMART
/ ~% _9 ^6 V- p. D* a - LCD_Init(); //LCD初始化
7 q8 @7 T9 R) f( _& v1 d3 W - Adc_Init(); //ADC初始化9 z6 t0 e" {* T
-
! v' v, u" Q) i# B7 _ - TIM1_PWM_Init(255,0); //TIM1 PWM初始化,计数周期为256,Fpwm=72M/256=281.25Khz.. B' x: p# Z9 f
- TIM_SetCompare1(TIM1,100);//初始值为0 . L# c7 `1 n5 o& x
-
: M5 l. F* s* l# ~/ W7 q - POINT_COLOR=RED;//设置字体为红色 * l& y9 R2 g6 Z# a
- LCD_ShowString(60,50,200,16,16,"WarShip STM32");
* r) h: t/ L* m - LCD_ShowString(60,70,200,16,16,"PWM DAC TEST");
. f, j: Q8 U. E6 x& B. S7 ` - LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
" m- `, g9 [+ O% [ - LCD_ShowString(60,110,200,16,16,"2015/1/15"); 5 R |4 y1 y7 E% V: y& U
- LCD_ShowString(60,130,200,16,16,"WK_UP:+ KEY1:-"); * w2 ?2 B! c5 T, { E5 [' ^
- //显示提示信息 3 D7 F* l. m/ D5 V7 C
- POINT_COLOR=BLUE;//设置字体为蓝色
# Z4 o( \" B- K, Y7 | - LCD_ShowString(60,150,200,16,16,"PWM VAL:"); : H& i Z! ^& d) g6 F9 r
- LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V"); - N8 O( N) L3 H$ X2 t# I. K
- LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");7 f2 r7 W/ R4 ?/ S) P, s! C& f
- ' \: u9 h3 \3 W" b& ^$ y: m+ L8 ^
- TIM_SetCompare1(TIM1,pwmval);//初始值
+ E" d {) r5 @( _4 j ^ - while(1)* ^7 @1 k* ^% [: x
- {" @5 H7 }+ h& j7 W4 Z* w# r
- t++;: h0 ?# Z# i1 C p% l' ^( U
- key=KEY_Scan(0); ! r3 A' Y* k: e" A
- if(key==WKUP_PRES)
. T+ C. a0 n. X' k6 \8 u5 E# l - { 9 }4 M. O8 K3 f( q1 E
- if(pwmval<250)pwmval+=10;6 ~% r: ^- S. n7 z* c; z+ X- R. B3 t5 t
- TIM_SetCompare1(TIM1,pwmval); //输出+ `1 r( N( ^! E% o, Y% y
- }else if(key==KEY1_PRES)
& b; `; [# X5 X7 a - {
2 G r% m5 H L( _& M - if(pwmval>10)pwmval-=10;
% u4 o* G/ W0 y/ d& P4 s/ ~ - else pwmval=0;
; I, ?. ]: t4 Q7 l+ D9 Z: T' G - TIM_SetCompare1(TIM1,pwmval); //输出1 |$ T' S# _% F+ o) v# p' [
- }
k6 E; L) W" J - 5 D( a2 B! L' `/ L) N
- if(t==10||key==KEY1_PRES||key==WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了; Z, r3 i- ]( @4 w6 V( f! g Q
- { , Q* G( L9 w& { U5 f
- adcx=TIM_GetCapture1(TIM1);& ~7 f: J0 [- F0 M
- LCD_ShowxNum(124,150,adcx,4,16,0); //显示DAC寄存器值4 A9 z) [/ k- A
- temp=(float)adcx*(3.3/256); //得到DAC电压值( C) z) n$ a4 `' M+ h
- adcx=temp;
1 I$ V% c, N2 ]3 b - LCD_ShowxNum(124,170,temp,1,16,0); //显示电压值整数部分7 ^+ k2 y7 b2 M" v" C; C
- temp-=adcx;
8 [' T( k h" A2 ]7 s. I - temp*=1000;# m$ u9 }9 f) f! U
- LCD_ShowxNum(140,170,temp,3,16,0x80); //显示电压值的小数部分6 W/ f$ r, x2 ~+ L
-
7 P( H: F8 a; d! o; q8 C- Z% p - adcx=Get_Adc_Average(ADC_Channel_1,20); //得到ADC转换值 $ [; v- ^- W8 P( O: ]8 m1 B: w
- temp=(float)adcx*(3.3/4096); //得到ADC电压值3 c" \/ n# u5 G9 }/ r
- adcx=temp; [5 g/ n9 F0 v+ ~4 b
- LCD_ShowxNum(124,190,temp,1,16,0); //显示电压值整数部分0 N$ J" @$ g, D: x$ Y% n4 B
- temp-=adcx;
) E% e) i# L' j& S4 v: t, g - temp*=1000;
+ f' L/ S& l8 e3 |/ L: I" M1 @+ E - LCD_ShowxNum(140,190,temp,3,16,0x80); //显示电压值的小数部分( v2 @) ~+ \8 w) z/ t$ w
- t=0;
4 G5 y! E- i* o( [' s! |/ t; x8 d - LED0=!LED0; & }% L9 \" m$ b* T
- } . y8 n, X- |$ c. S
- delay_ms(10); 8 M' \1 R+ v- I: M3 h! u2 h
- }
3 L f1 Y1 z2 H7 z" B! w3 ~4 |7 @ - }9 X& c8 e! s' ?9 k
复制代码 9 V: o1 Z) O- e
. S/ [' A q; R9 C% X
pwm_dac.c函数
8 j0 H* X+ U0 R6 w8 R- //TIM1 CH1 PWM输出设置 7 j Y; {) t7 \& ^
- //PWM输出初始化
8 E2 }. B- q% w6 k$ ? - //arr:自动重装值
, D9 f5 \% }6 H, D1 }) u - //psc:时钟预分频数
9 o. V a3 Q0 M4 {# K/ A - void TIM1_PWM_Init(u16 arr,u16 psc)
1 o" i) N/ e. C S& l# Q) Y8 D - { ( p8 _7 f+ Y% }- i1 U4 ]5 q2 h
- GPIO_InitTypeDef GPIO_InitStructure;
1 E. N+ v d# t+ G/ J9 F n - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
* Y3 h- {/ {) X* k* U - TIM_OCInitTypeDef TIM_OCInitStructure;; s2 ?$ R0 ?' ~7 b9 \
- 6 U. |& n% m7 W3 Z2 V
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIMx外设
0 I, A9 a) |$ k; b - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设时钟使能
: H. c+ P, y/ J$ \7 L: w) F - 8 `$ K) h0 e2 H4 `( |
- //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
& |& F- B4 ], q$ P( S# M - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH1
, u: ^. L) H& B g, |7 r8 c - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能输出9 `8 E0 h( L. E& i7 |5 l
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
3 Y( Z7 X- U' {& I - GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO
5 f- m( _+ Y* j$ @. K$ e - ; f* Y1 W/ [2 }1 F+ L
- TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载周期值& _* s. k- k0 K5 Y7 J
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 不分频. r! P! O1 Q1 |2 J( z4 C0 X/ f; l
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
" U F3 [7 T/ {; R/ ^6 C - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
& X# {4 m) ~8 u! j9 q7 R - TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx
4 n" [' m# z9 j& q: B4 M -
7 C* v( u% z1 T( n3 Y - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //CH1 PWM2模式
% Q8 Y- q0 ]# V0 J - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能1 x6 ^" q* _' g* [- `
- TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值/ y# j- g7 t9 V+ d9 J b
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //OC1 低电平有效 5 x' s8 a( t- y( k6 n
- TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据指定的参数初始化外设TIMx
! c! J8 [8 r" A0 Z2 O/ ^, q3 _
/ F& S0 B& h6 u# d# A5 J- TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1 预装载使能: X ?9 n4 v! K$ f# T! Y% V
- - v! d9 V( F1 ^8 H8 P2 m
- TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
' ^ h$ g# ~% s -
% K) ?3 X! p" S O; Q - TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能,高级定时器必须开启这个
0 ]& [3 t7 I' Q -
( k0 \' P, w9 S - TIM_Cmd(TIM1, ENABLE); //使能TIMx
# Q& ~$ c, G- ]! a o' | - }
3 T" ~* A4 e* z5 c* y7 Y
复制代码
- \/ c2 ]0 X& K) ?* Z; h5 @; L9 T0 Z- r8 L9 V
————————————————; ?% f$ i" B, V# V
版权声明:_Amen
* a- h0 w* j! a, X0 ~2 g如有侵权请联系删除
- {( H# c, ~1 ]8 e4 ?- z
) S* q5 p4 y# N- n, n' l5 b$ B5 P) `( `- O; k1 T
|