STM32F1自带的DAC模块的使用。但有时候,可能两个DAC不够用,我们可以通过PWM+RC滤波来实现一个PWM DAC。本章将向大家介绍如何利用STM32的PWM来设计一个DAC。利用按键(USMART)控制STM32的PWM输出,从而控制PWM DAC的输出电压,通过ADC1的通道1采集PWM DAC的输出电压,并在LCD模块上面显示ADC获取到的电压值以及PWM DAC的设定输出电压值等信息。
; j) Q& A; e5 s; B6 `8 x8 H
- c2 U T* G; }! U$ l" X* } u; q' Z; M$ P# u* E6 {) k
9 G" k) m( k$ H- s8 Z1 ?
9 f! X+ R# b1 K
% g# V' ?1 C" B( V" K! X i v
0 E3 u7 g/ B2 H7 H |+ l2 Z+ G. Q, q+ s, @# ?7 v% t. c& I( P" K! S p
* z& s8 t. e) D1 c* U
9 v, ?# j( k' k0 P' T4 c7 W- F8 z5 Z
1 g4 p7 n: b. g( q" u; D
8 b6 ], q* _; A; _) {- z9 C# ~) B( C# `# A5 f' s
3 A5 R9 [/ e* q! R
( L) `3 q+ R# W) E! y8 W8 w# @3 M8 _. k' Y% q4 M+ Z& t& d6 h
main函数
$ ^# ?# @0 b* m9 X1 ]- \7 H( D- #include "led.h"0 {$ t5 ?2 h8 {' k+ d. q- k* ]
- #include "delay.h"
4 h8 i& Q5 ]0 E/ y: \ - #include "key.h"
) a4 k4 G' c0 r% n# f2 X4 t - #include "sys.h"
- Q& e8 j( `) @% n0 X4 U - #include "lcd.h" m" Y8 E2 G3 \
- #include "usart.h"
d; E8 ? {5 G& f - #include "rtc.h" 7 M2 E8 {5 I; U7 |- E7 E7 U
- #include "wkup.h"% P5 J6 V) J# ?$ l, t2 A( ~
- #include "adc.h" / n% C: H& {+ X9 o8 h! }
- #include "dac.h"/ b2 c* I2 B2 z
- #include "timer.h"/ Y& q: F4 l+ _* M8 F3 J# k
- #include "usmart.h"2 }% }6 p* A1 V! ]; c1 E/ J( G
3 O+ z1 G m$ d6 C3 T! O6 D- //设置输出电压& D$ e- S+ W' [/ Q# t8 d
- //vol:0~330,代表0~3.3V
8 B: w) a( X) @8 L2 F" D. l% Q - void PWM_DAC_Set(u16 vol)8 C7 P3 |9 W5 k, Q3 `
- {& J1 F$ Q4 }3 Y0 [% j. g& e9 d
- float temp=vol;+ ~% g. j8 H/ J: d. T3 l7 w
- temp/=100;
$ |4 I% B6 Y t+ H U2 F0 v - temp=temp*256/3.3;2 n/ L) t% V9 O% t
- TIM_SetCompare1(TIM1,temp);
+ M# A1 j5 S+ ?+ U' ~9 U - }+ ^& Q9 r' ~! E4 w& n1 N7 S
- 4 n: G0 f! {# K1 }
- int main(void)
1 I- s/ u7 Z, A - { # u: }# h3 T3 x
- u16 adcx;
$ L' T/ \0 ~; M" ~ - float temp;
6 _1 k8 `: P4 a# k7 M - u8 t=0; . B' `. X& x; N& ]+ b4 `. G
- u16 pwmval=0;
4 z1 N2 ?3 H0 L - u8 key;( y) W9 O, l" g8 \
-
3 k$ P5 T# l# g8 u7 B; ^ - delay_init(); //延时函数初始化 # e! \9 }+ u# @& n( ^. P
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
5 O. f' z: I% c i/ [6 P/ A) L" ?% z - uart_init(115200); //串口初始化为115200
6 K3 P; b! N' S9 |( K - KEY_Init(); //KEY初始化
( o; `& W( w( q z& w - LED_Init(); //LED端口初始化
+ ~/ ^( O3 E( I, F( J2 h. q - usmart_dev.init(72); //初始化USMART 6 c4 ]' v! a0 G3 l4 G
- LCD_Init(); //LCD初始化4 n; v$ X) V- g# `$ Z
- Adc_Init(); //ADC初始化
9 W8 e% U* H3 M2 k* o# H# H -
( x) b6 q6 z+ ] - TIM1_PWM_Init(255,0); //TIM1 PWM初始化,计数周期为256,Fpwm=72M/256=281.25Khz." R* m$ i7 p6 w- p. j4 Y1 [
- TIM_SetCompare1(TIM1,100);//初始值为0
& Z( g7 V: T4 U0 ] -
/ H2 R3 k1 e* C - POINT_COLOR=RED;//设置字体为红色
: B' X' n! a8 n" g - LCD_ShowString(60,50,200,16,16,"WarShip STM32");
! Z( [# t* F& P, l2 X/ Q( K - LCD_ShowString(60,70,200,16,16,"PWM DAC TEST");
9 a q% K( \* G8 W/ ]6 h% E7 j+ { - LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
% m; S9 m, ~! w" V$ U6 W2 ` - LCD_ShowString(60,110,200,16,16,"2015/1/15"); % X6 X6 {( }% e. M% \1 D
- LCD_ShowString(60,130,200,16,16,"WK_UP:+ KEY1:-");
3 p1 K0 I, P7 y2 a - //显示提示信息
- O% O6 T, d9 y1 i4 \; V - POINT_COLOR=BLUE;//设置字体为蓝色, ^8 }7 A. G$ W9 s" K- L2 }5 s
- LCD_ShowString(60,150,200,16,16,"PWM VAL:");
$ ]1 ~+ u9 x$ ^5 ^, S- Q; D - LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V"); ) o: ~0 r, d( `# I6 W: _3 I
- LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");
/ k7 s$ o: p, n -
8 |' R g" a. e9 j( p- `( e - TIM_SetCompare1(TIM1,pwmval);//初始值
8 A( v6 `7 e5 p' O - while(1)
% }1 a3 M9 m1 W. f* ~0 P' c/ G - {
1 m3 e8 V0 N9 `2 @ - t++;' _- U, U5 ~" b0 s: e' K2 e- C& ]
- key=KEY_Scan(0);
! V" L/ j2 U8 H0 ?' s - if(key==WKUP_PRES). I* k: d5 Y7 h; F: W4 t
- {
- C- ~; [2 e; l3 Z2 ~ - if(pwmval<250)pwmval+=10;
0 A$ U7 K7 h! M* V/ c+ T$ W - TIM_SetCompare1(TIM1,pwmval); //输出. H5 \* m9 a1 A# {
- }else if(key==KEY1_PRES)
0 ^, K% A0 N) O# Q. ~4 i: l" y - {
3 y3 I3 z/ \# d! e7 m - if(pwmval>10)pwmval-=10;
8 n3 j6 Y4 n! u* G# G7 p9 e. [ - else pwmval=0;4 c/ g4 ]& V1 @$ D
- TIM_SetCompare1(TIM1,pwmval); //输出
- l0 s5 @9 T5 X7 A4 w& p - } * k R- W: E/ G Q
- 7 t# @6 K& w1 L+ i
- if(t==10||key==KEY1_PRES||key==WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了# ]4 g5 g& ^: A5 ^$ a
- { ( f5 T$ S$ G8 l. c$ t6 v
- adcx=TIM_GetCapture1(TIM1);
3 y8 [* _1 u0 J9 X5 p) m - LCD_ShowxNum(124,150,adcx,4,16,0); //显示DAC寄存器值
4 G( S, F( P( y' x; y/ U - temp=(float)adcx*(3.3/256); //得到DAC电压值
3 t) a* d1 r# U3 M% s' L1 | - adcx=temp;2 V4 p1 K1 y# S; t( l
- LCD_ShowxNum(124,170,temp,1,16,0); //显示电压值整数部分
4 v6 E# u0 D7 H4 ]; B4 P - temp-=adcx;' J% @$ B; |* A R @) v( a
- temp*=1000;
3 |2 ?" T% t0 F - LCD_ShowxNum(140,170,temp,3,16,0x80); //显示电压值的小数部分
9 p4 q3 W) O7 |( C -
" r. e1 {& d0 H - adcx=Get_Adc_Average(ADC_Channel_1,20); //得到ADC转换值
* t2 H- j" p/ W$ T o - temp=(float)adcx*(3.3/4096); //得到ADC电压值
* r3 l" ]2 f# `$ T' s5 a; q - adcx=temp;! k! w9 j5 ^" ^: @ g6 p: l$ i
- LCD_ShowxNum(124,190,temp,1,16,0); //显示电压值整数部分; }. H2 ]: e9 B% E" y
- temp-=adcx;9 s5 A. U( d' [7 K$ c) k
- temp*=1000;% n* H, v5 ]/ @' }
- LCD_ShowxNum(140,190,temp,3,16,0x80); //显示电压值的小数部分
/ e% b5 k. T' P6 a0 E' R - t=0;& o. C( i, |7 ]. x3 N5 a
- LED0=!LED0;
' l" i# `- ` ~7 r% d - }
* g9 ?- e+ G2 I; ` - delay_ms(10); + e% l D5 b" ~
- }& g" ~+ ~5 L3 S# R- n% d. G. Q: _
- }! r# ]% N# y5 s8 `
复制代码 _" B0 [% y" T4 N' q% M
; g( J( E( |4 G; k% jpwm_dac.c函数
4 M" t7 m6 _0 |8 ^4 w- //TIM1 CH1 PWM输出设置 6 b& t# y" T" f8 r- v
- //PWM输出初始化
/ O3 F. g+ c0 Q6 w( Q* t - //arr:自动重装值4 ?0 t O. z# Z5 p# e
- //psc:时钟预分频数
! q1 m0 e4 P1 O+ Z8 B2 Z7 d# M( z - void TIM1_PWM_Init(u16 arr,u16 psc)' f0 D4 ~0 C+ r1 z0 [
- {
% G) D( R0 b$ F: W - GPIO_InitTypeDef GPIO_InitStructure;6 |6 ^; T, U7 Y
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;7 |/ U6 V" O# w2 t) I( z
- TIM_OCInitTypeDef TIM_OCInitStructure;) c1 r! w* O7 E3 _5 S; r
- 8 q! T' j+ n- }1 I+ D7 r
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIMx外设
" G; q* v. h, o; O* r - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设时钟使能2 N$ e* w+ w! c' {
- 7 C9 Z, I- ]+ Q, A1 P
- //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形! ~3 V( i7 v r8 w4 ^- Y
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH16 J2 ~8 T" i1 z! ^# M8 U3 b: r
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能输出! A7 r8 k9 ?7 E* Q
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ ?& R' d z: o" ^& F+ N4 B/ o$ S - GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO" ]3 s) x5 q, _! [4 T1 T
-
0 p0 \" v: x8 P- k - TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载周期值
# C# B$ b, |& b# ` - TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 不分频$ o1 s' t3 t( `) M
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
9 T# @+ s$ a- Q8 G. A/ i; M - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式% [; Q/ W5 C: R6 {1 i8 M
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx: S$ r. j2 F% o; s6 ^, N. i* j
-
" I% m& S+ |( c! t - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //CH1 PWM2模式
w- E4 |6 |$ a - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
9 v# K" k+ H% U - TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
. E! k5 f0 {" u4 U# B7 ] - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //OC1 低电平有效
3 P2 A2 g {8 v+ O# D4 \ - TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据指定的参数初始化外设TIMx
! Y8 H2 l+ C4 l2 e% x3 P' G$ n - + D7 d" m) d- @, v: r0 d
- TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1 预装载使能
1 U1 y v3 U& H8 b0 m - 9 A; S! ]- W. t9 ^% M4 N1 v
- TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
* K' J1 X! l6 x* S; ? - 9 z* _8 K0 j# ~: A: U7 }
- TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能,高级定时器必须开启这个 % U: A* ~+ s. Y7 c
- . X+ | P) g$ s) t+ g
- TIM_Cmd(TIM1, ENABLE); //使能TIMx 6 T" \. x2 V; ]5 D: K, p% w- L
- } $ K3 d' Z$ |1 x( L" s2 t6 X
复制代码 6 y% K/ p4 k3 \
: o; H7 K F$ N6 u
————————————————
( Z, F/ y e0 q6 K Q+ n版权声明:_Amen! J. a7 Y9 N1 S+ ~. ^
如有侵权请联系删除
1 X0 b' U0 g) ^& T9 {0 i3 a% }) c4 q
2 j) W4 u( {' _" b6 Q/ U+ k; b' F
|