STM32F1自带的DAC模块的使用。但有时候,可能两个DAC不够用,我们可以通过PWM+RC滤波来实现一个PWM DAC。本章将向大家介绍如何利用STM32的PWM来设计一个DAC。利用按键(USMART)控制STM32的PWM输出,从而控制PWM DAC的输出电压,通过ADC1的通道1采集PWM DAC的输出电压,并在LCD模块上面显示ADC获取到的电压值以及PWM DAC的设定输出电压值等信息。
* @( h6 [4 Q8 J, N' z
2 B- d# v; k: [) e& @1 K$ X: ?$ d( `' s8 m, q F+ [
# S" d% `; a) B% k/ j! }
3 X/ {/ o; g: l! l; F ~. F0 p7 B, D
# G0 f" O+ q# j
2 @7 g9 x; H. w2 k+ y
/ y! c5 M: [. ?* b) b
# k5 b9 y1 \* m% U# B' b. Z
8 b* b. w9 c% U: M0 A* @: x
) L# c ]% c* R- ?" \8 y! b
j% f6 @/ X; m
& }% }1 M; c2 T7 d0 R
/ E. x' ?# z# O
! x. T8 X8 @1 m- ~2 F
$ x% K9 T$ Q5 E% m3 L; [6 omain函数5 u6 M. V! Z2 K4 A
- #include "led.h"
! C* v3 G7 d, P. t - #include "delay.h"0 n% I* O. h1 y5 X7 r) V
- #include "key.h" k `& b3 k, N, v
- #include "sys.h"
R" B( t# ^" n' x" B - #include "lcd.h"
+ `9 @4 U$ P8 x/ v - #include "usart.h" : ], g8 x' z" ]0 n9 l* I
- #include "rtc.h"
5 G2 j3 y9 s4 t# p/ \ - #include "wkup.h"8 b2 ]# o% H+ H+ k2 m$ D! d/ y
- #include "adc.h"
- {5 D2 ~% s5 {8 B: P2 @9 A3 s - #include "dac.h"
! \, @2 _! I( `7 U' ?- { - #include "timer.h"$ D: {6 d3 ]: Q/ e" C) ^
- #include "usmart.h"
- X6 b% W2 F% e: t1 R - ! _& x c0 H1 u% P; v& k
- //设置输出电压* q. W+ ]" E$ t* [9 n
- //vol:0~330,代表0~3.3V9 O- |5 R9 ?$ Q9 y! R! ~! d# B
- void PWM_DAC_Set(u16 vol)
, t x4 c! @; R2 \/ Z - {
( k+ V @& j# X3 \7 j% o - float temp=vol;
: h% h+ N$ Z. Z8 j# @& J9 M5 f - temp/=100;
. r$ D5 G( R( r8 `; n" t* M+ y - temp=temp*256/3.3;3 F; T. o& h m' i) e( j5 i
- TIM_SetCompare1(TIM1,temp);2 J. T/ d3 n' {% W6 }+ f
- }+ R; Y, Q, [ t- t; I$ S* `+ ?
- h0 j& m: m& c: v/ e2 p- int main(void)
& z5 y# T! `7 }$ H6 R) y- x - { 9 G3 D/ L8 y: U: Y# y
- u16 adcx;
# O1 K8 O. ]# `% ]- f - float temp;
4 ]* L$ v+ o- j) X6 f$ y - u8 t=0; + ?, T0 z1 G4 z7 P/ F
- u16 pwmval=0;
# w0 n* L$ O( s7 g, K& y2 G - u8 key;1 e+ g D: @9 l
- 4 l& _8 y" q2 x. H7 L7 D6 s5 ^
- delay_init(); //延时函数初始化
; h. d) Q# t* w0 v) c! z2 L8 S0 k - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
( S' o3 J+ K7 \ - uart_init(115200); //串口初始化为115200/ f5 {6 W2 w9 z
- KEY_Init(); //KEY初始化/ P, f* N4 U2 X/ s
- LED_Init(); //LED端口初始化
! `" q. k; W) u5 J) ^+ N - usmart_dev.init(72); //初始化USMART " O( J; w, V& C2 C" Z
- LCD_Init(); //LCD初始化
0 Q( x; Q1 G* a' M - Adc_Init(); //ADC初始化3 R, R7 g1 L9 t8 D1 U9 _
- / ?, m& ~7 e5 q( ^% e# {# e) W
- TIM1_PWM_Init(255,0); //TIM1 PWM初始化,计数周期为256,Fpwm=72M/256=281.25Khz.
8 m n h( A, L( K5 } - TIM_SetCompare1(TIM1,100);//初始值为0
" m0 H; t1 o9 W5 U6 d# Y - ! S. g/ Z: Q3 T; O( |+ K& I+ G
- POINT_COLOR=RED;//设置字体为红色
5 K: m$ C5 o: ^4 b - LCD_ShowString(60,50,200,16,16,"WarShip STM32"); ! K T- L) L+ |0 c+ O& H) \) {
- LCD_ShowString(60,70,200,16,16,"PWM DAC TEST");
4 ?0 l( \0 S X2 ~4 ]" G- o/ d1 ? - LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
( |. v1 C6 T) n3 t+ X8 o - LCD_ShowString(60,110,200,16,16,"2015/1/15");
) D- G3 W: H, w3 q. i- _, j | - LCD_ShowString(60,130,200,16,16,"WK_UP:+ KEY1:-");
! z/ E( Z4 h. ? - //显示提示信息
/ B; ~: f; t* H: e: T) v# O - POINT_COLOR=BLUE;//设置字体为蓝色
0 e) t( [4 G0 v- v( E - LCD_ShowString(60,150,200,16,16,"PWM VAL:");
: X' z ?+ e: k' ~( }' u& }; n - LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V"); ; m1 b; q) o1 s4 [, X
- LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");
- G/ W$ ]0 S/ y; F Z& w5 ? - - N, L, i L8 c1 Q/ g: f
- TIM_SetCompare1(TIM1,pwmval);//初始值
6 _' ?7 S% U$ L9 p0 ~ - while(1)
+ e' S" o. d% x( C% g S9 [% A) Y4 H - {* e* j$ d9 `8 w1 o1 L4 p
- t++;
& h: x$ t& s3 P: ~" S- P9 l - key=KEY_Scan(0);
) N7 O! W/ X3 l: d- c7 o - if(key==WKUP_PRES)' k% X# x7 z/ a, s. M# e- E
- {
& g3 ?3 |1 d6 f3 l J+ o - if(pwmval<250)pwmval+=10;
|- z, C) a4 z" v9 P+ s3 m - TIM_SetCompare1(TIM1,pwmval); //输出" }7 R- n3 y' i; [( [: j
- }else if(key==KEY1_PRES) ! k a: |4 Q1 g" P: N1 Y' C
- {- _* |5 g- C$ K7 T/ P% @
- if(pwmval>10)pwmval-=10;# T* a( O8 z0 C% x5 U p1 G$ v
- else pwmval=0;) P# a0 `2 S- ]! O# D$ ^
- TIM_SetCompare1(TIM1,pwmval); //输出- u6 S6 _2 ]* s8 `# J1 P T+ O4 t
- }
. f# x& d8 \ `" F - " P' m; }& ~9 c+ R* m! z
- if(t==10||key==KEY1_PRES||key==WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了) c9 }; h: J+ k3 c4 k
- {
2 @1 q5 D+ C) X5 V2 L& V' i4 Y0 N - adcx=TIM_GetCapture1(TIM1);, l4 F8 h" q+ m( d' v6 }2 t
- LCD_ShowxNum(124,150,adcx,4,16,0); //显示DAC寄存器值
( [" i" t* p$ r# Z' q - temp=(float)adcx*(3.3/256); //得到DAC电压值
# ^5 b5 _7 g$ d9 ^- c - adcx=temp;4 m8 P3 M- J, v' Y _9 \! z
- LCD_ShowxNum(124,170,temp,1,16,0); //显示电压值整数部分9 g6 U0 l R+ ~9 B: F
- temp-=adcx;2 s( L+ [* v0 |% h* l3 d1 m+ |
- temp*=1000;
$ a& C5 P' {) Y0 ?9 l, \ - LCD_ShowxNum(140,170,temp,3,16,0x80); //显示电压值的小数部分 `) k F/ |! y/ B9 S% J7 ?- o
- , Q6 @0 v W- \" m. S
- adcx=Get_Adc_Average(ADC_Channel_1,20); //得到ADC转换值
+ N" a* L* Q4 C; u( s) v - temp=(float)adcx*(3.3/4096); //得到ADC电压值) l0 r" p1 h! [7 r% U' r
- adcx=temp;
- f0 k& C% N' x5 E3 p* F - LCD_ShowxNum(124,190,temp,1,16,0); //显示电压值整数部分
8 r$ g" @ V0 n+ r3 O* W* _ - temp-=adcx;9 H/ |5 x2 K: k# |+ _
- temp*=1000;
8 z! {- K8 G d1 b - LCD_ShowxNum(140,190,temp,3,16,0x80); //显示电压值的小数部分 N2 o; z! g* Z: e5 Q5 P
- t=0;# _) x) L# v4 _# V$ f$ w% g& e% d
- LED0=!LED0; 5 ^6 P; G: o7 d6 f
- }
( @. p# @8 n7 t% m - delay_ms(10); " F4 n" Y! B2 y- N5 G
- }$ \8 ?2 h: w% _ f5 |# F- i9 O
- }3 ]+ |) q9 e+ b
复制代码 2 R- l; ~7 G: N! Q
+ ~! v$ F! Q7 f- A
pwm_dac.c函数: k; W, A2 b1 d( k9 C1 w4 @- k
- //TIM1 CH1 PWM输出设置
9 S8 ^# x& G9 Q; J - //PWM输出初始化6 Y4 D. \% ^, y; n3 V3 S
- //arr:自动重装值
1 K8 @$ k0 o, y4 ]2 d+ @6 K' } - //psc:时钟预分频数
& x1 G' I& Q, b( }$ ^( l - void TIM1_PWM_Init(u16 arr,u16 psc)6 G% u3 t* I% A4 u# i5 V
- { ; y3 _0 r8 h0 |, G1 q
- GPIO_InitTypeDef GPIO_InitStructure;7 n K; T! F: F; l& G4 u" O- k
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
# P& U$ o, g( c, z+ f - TIM_OCInitTypeDef TIM_OCInitStructure;6 e3 f* J2 o! k6 k! a) a) Y; R
- 1 h* W, H1 @8 h( P9 h6 i5 ^
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIMx外设5 S# B9 {, H5 E; R- x
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设时钟使能# l, A; v X# K" K$ I) Q3 u9 L
- + b% j) l x3 n. w5 l; u- s. K
- //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
; D# @" e u k' x - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH1! W2 D0 M+ l* `3 p0 y, K, f8 U3 E( Y
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能输出/ H& ^4 l, T7 |
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;2 p. P) H2 i" L9 ]7 X
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO% w. _( m- _( T' a+ F+ T5 u
-
, w7 u% |; [$ x - TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载周期值" w ^& @5 A W& [ N
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 不分频
% W7 W0 C* v9 m( o. S# ` - TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim k2 E4 ~" K I
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
% ]7 O0 w0 `2 ^6 t* b1 J - TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx
- J6 c/ b q7 y& n - 9 B6 I- n, n m4 j& n8 \
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //CH1 PWM2模式
+ X5 R V. _" }3 B0 J9 a' Z - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能% w- o% ]; \# _ g( `/ a0 s
- TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值, Y3 _" g6 J% R3 z. r2 I' V' m
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //OC1 低电平有效
2 E, I* P2 ^$ M! i - TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据指定的参数初始化外设TIMx% o. P+ P9 S8 ~& T
6 c! n, Y& u& }' c: h, Y( ]- TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1 预装载使能
, B: p. K( e# _5 ~& h - c/ K6 s/ o2 i- u* S
- TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
- y" H: j7 Q# T6 J% J9 D% X# { -
/ \: {6 d+ M$ n1 q( m8 l - TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能,高级定时器必须开启这个
0 ]6 W$ q6 v A5 j1 f9 X - / g! _; n2 G7 M! w8 i) K( {
- TIM_Cmd(TIM1, ENABLE); //使能TIMx
$ \/ V, m0 {% f5 Z4 C" ?, ~* u - } & P( F, R& R* C+ `- z! a
复制代码 ' V+ u# {# @5 I- a6 N) |9 n. N
& }; H5 f8 Q; `" \6 f6 {————————————————/ E$ J7 O( p7 y2 f
版权声明:_Amen9 \8 [. H( P7 P, |; v- l
如有侵权请联系删除9 [/ K' ^ T; I7 Y) G8 M! j& V [# q
0 p( u, k& a+ b
" u$ Q5 t6 d% z- i |