STM32F1自带的DAC模块的使用。但有时候,可能两个DAC不够用,我们可以通过PWM+RC滤波来实现一个PWM DAC。本章将向大家介绍如何利用STM32的PWM来设计一个DAC。利用按键(USMART)控制STM32的PWM输出,从而控制PWM DAC的输出电压,通过ADC1的通道1采集PWM DAC的输出电压,并在LCD模块上面显示ADC获取到的电压值以及PWM DAC的设定输出电压值等信息。' d R0 B) e" m8 W# E7 P5 x% W" \% u
/ p( q/ I6 V" L9 a4 |: s' p
# F) D4 q4 ]1 Z5 [1 r- M
5 E1 K# h: E5 f B1 y% M# @/ O9 q9 c6 G
$ h( C$ M0 [0 L- g7 R8 g
$ z: G& [! _8 Q+ Y9 k0 f) {/ O
% f& i% I( d6 L8 D
* `' J2 b. I1 Z( W3 A5 T o
* d4 `% o% X" ]! E. `$ s0 ]2 i1 |( p1 u. G X5 I& g* w! C4 x4 R7 u
: p1 d" f2 {7 e! S: T* q
) x" D4 N# N g0 ?8 Z
) @ \% L U# ]7 c
8 S+ N/ d! U3 J$ c2 v) M8 @, m
9 ~/ o# y: m0 ~9 P6 ]
" ~1 ^7 f2 g+ r. P N) Q3 |3 ^6 a5 k$ m
main函数5 u! q1 T; N( N, K2 U' k
- #include "led.h"
0 X& p* `2 N6 G1 G7 h- U3 V - #include "delay.h"' t4 \& O9 }0 Y
- #include "key.h"
' c0 O4 k- F. h+ L! P4 H* ? Q% ^ g - #include "sys.h"
9 Y7 Z1 g+ X) d% \ - #include "lcd.h"
) C" k: l1 W. O) q/ [+ I+ u9 s - #include "usart.h"
+ H% y4 A2 a ^8 z. e3 u - #include "rtc.h" ; v( {) X+ y* M' k, p0 B
- #include "wkup.h"3 [" {. l* h/ K B( u
- #include "adc.h"
9 H) G) x- P2 o7 k" v" X% C5 b$ @ - #include "dac.h"; L$ w0 b" t/ R5 I4 z6 I% M
- #include "timer.h"
- O! `% V$ h3 A5 ~6 E. B# n - #include "usmart.h"
4 Y3 |" X9 ^0 v/ @0 E- q - . Z$ c+ l3 W% C3 [/ j* j
- //设置输出电压
2 g8 }- M$ r$ U1 m( _$ { - //vol:0~330,代表0~3.3V
* x, o( H# q5 @' W0 D4 x7 Y - void PWM_DAC_Set(u16 vol)' ^$ ^$ g$ z5 \& F! W
- {
T. V0 {, ?* A+ Q/ P0 ~9 D v% r - float temp=vol;+ l, D0 W& v5 | ~8 K# A0 D
- temp/=100;
. X+ l% r$ T8 g4 w" R - temp=temp*256/3.3;1 k- N& V5 {/ k1 V& @7 u; W
- TIM_SetCompare1(TIM1,temp);
5 u, y$ ]1 b0 f9 p- ?! E9 O; E - }
# }8 |) q' _: Z6 W. k1 U: O - , M4 Z2 \& b _4 a
- int main(void)
$ r& g! J4 e5 ^2 E6 T3 F) z - {
& ^3 r! @" T8 K, `6 U* O - u16 adcx;% U: i' k: _. h; v
- float temp;% R) z r# ]% H6 m
- u8 t=0;
1 _7 O. Z1 }' s2 b* b - u16 pwmval=0;) `; c; x5 [5 ]0 a5 n, x! J$ T
- u8 key;
+ Y- H: K/ \/ i3 d: v0 V -
3 \+ P7 {8 W9 M, W - delay_init(); //延时函数初始化 # w, q$ W( D2 L* e% j
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
3 F" B. `# Y% `0 F) O, w/ H - uart_init(115200); //串口初始化为115200% S$ ~" G" o& a/ [1 b
- KEY_Init(); //KEY初始化
5 ], H- `. G9 M6 W - LED_Init(); //LED端口初始化
. P" v) N6 C9 v7 G' {, x - usmart_dev.init(72); //初始化USMART
3 W( K) A y2 c- {: t - LCD_Init(); //LCD初始化4 O8 T6 Q( |& ^0 L3 y
- Adc_Init(); //ADC初始化5 A' y) h% @# U0 D9 C( Q; I: W
-
& L& O. J& x* m1 t4 \& g - TIM1_PWM_Init(255,0); //TIM1 PWM初始化,计数周期为256,Fpwm=72M/256=281.25Khz.
2 L1 a0 U4 E H! ` ]- S: a, L7 e - TIM_SetCompare1(TIM1,100);//初始值为0 8 d. q. [! z5 x, ], w5 t; q
-
4 ^8 [# g" E3 _! q9 |3 {. s - POINT_COLOR=RED;//设置字体为红色
; i/ H* b9 E7 G4 _ - LCD_ShowString(60,50,200,16,16,"WarShip STM32"); , M# p* T0 q& T1 k7 [
- LCD_ShowString(60,70,200,16,16,"PWM DAC TEST");
7 Z9 v# m/ }. W1 M! D) F# \$ I - LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
+ }1 I% w, ~+ |. W' [ - LCD_ShowString(60,110,200,16,16,"2015/1/15");
5 N& T5 N2 a! K) D2 l, P/ |# F - LCD_ShowString(60,130,200,16,16,"WK_UP:+ KEY1:-");
" `+ p4 d3 _+ F" J - //显示提示信息
. N2 s# ~7 `% U v p, D- R7 D# A - POINT_COLOR=BLUE;//设置字体为蓝色' }# N; g" [* f/ G) e+ f5 r$ M# X
- LCD_ShowString(60,150,200,16,16,"PWM VAL:");
) A' G/ D0 r H4 @( o - LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V"); ! C6 P1 W' Q+ \" P) R0 z/ F; S
- LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");6 s/ ?" a3 F& ]# ~
- # n5 B+ U% e# [4 a. \- L
- TIM_SetCompare1(TIM1,pwmval);//初始值 3 }! q; v8 E! q) e/ X0 T# J, Q
- while(1)# [* J+ X9 P4 v8 j) M
- {
# A- U+ Q- d' d2 U - t++;
9 y6 y4 |7 G. y6 A$ c - key=KEY_Scan(0); ; A* t3 g" p, B2 o' ^
- if(key==WKUP_PRES)/ }( O0 u! R0 j" K/ C) O1 Y
- { $ D* }% p: m% [4 P/ M1 G
- if(pwmval<250)pwmval+=10;2 m! l+ [' H1 A
- TIM_SetCompare1(TIM1,pwmval); //输出
4 I2 C4 C9 L, b9 T- ^" H/ T% b - }else if(key==KEY1_PRES) c R# [! y {
- {
. F6 z0 |. z) M/ d0 d6 k - if(pwmval>10)pwmval-=10; T$ U4 @3 ^. r
- else pwmval=0;
( ~9 W: f0 Y5 f! S7 w# ~ - TIM_SetCompare1(TIM1,pwmval); //输出
8 T: f$ j7 {( g. r1 T - } 1 o% ?2 A/ H# Y: w
-
$ [3 m- @: Z: `" F - if(t==10||key==KEY1_PRES||key==WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了
' i9 Y$ e ?" |+ B: V - {
& z) A3 ~7 |% ~- B3 i- v1 E K - adcx=TIM_GetCapture1(TIM1);$ ^: G2 G) ~' A# d- `
- LCD_ShowxNum(124,150,adcx,4,16,0); //显示DAC寄存器值0 H" J/ V' k4 |, Q9 s* W' p8 R4 f
- temp=(float)adcx*(3.3/256); //得到DAC电压值
9 e- S; z* u" s4 x" A. S - adcx=temp;6 _* o* a- w% ^% H% Z. c' f+ R" s
- LCD_ShowxNum(124,170,temp,1,16,0); //显示电压值整数部分
. h2 R' h2 |) _% d - temp-=adcx;+ N* E; R7 C3 N
- temp*=1000;2 E: H; U7 P. O s! x# {6 a
- LCD_ShowxNum(140,170,temp,3,16,0x80); //显示电压值的小数部分
! t8 Q: p) d0 a7 O -
; J$ p2 Y1 G! H4 ?/ N& G3 N! t - adcx=Get_Adc_Average(ADC_Channel_1,20); //得到ADC转换值
6 P1 f1 I- e+ q5 y3 v - temp=(float)adcx*(3.3/4096); //得到ADC电压值
- m4 A, C: M8 {" m0 F - adcx=temp;& C L2 \" C) |7 P
- LCD_ShowxNum(124,190,temp,1,16,0); //显示电压值整数部分1 x5 A% j& E% V) J
- temp-=adcx;
, J `& @+ H& ?& K# I" c4 N - temp*=1000;
, _9 U7 Q1 ~% E/ F a - LCD_ShowxNum(140,190,temp,3,16,0x80); //显示电压值的小数部分. G* r) [ Q9 H- ~
- t=0;( q& A+ h* ?8 \$ r7 u2 {
- LED0=!LED0; 4 a9 | H: w# }" y. G" b
- }
" O- S6 t2 u4 J( |% M, [& R - delay_ms(10); # |% ]* `. E5 o: p+ o7 |
- }. Y& `1 T' w5 ] r* B) I
- }" _/ e+ [8 u; n8 M8 y( t
复制代码
3 s. I, Y1 o/ a% _ t" e4 m5 h+ ?( l: T( g
pwm_dac.c函数- T$ T4 z) k' {; n
- //TIM1 CH1 PWM输出设置
% L/ r1 B% C7 b" _1 U7 t* `* U$ K - //PWM输出初始化* w( ^7 i h% m9 |
- //arr:自动重装值+ Z+ v; n/ X% |3 O
- //psc:时钟预分频数
( i2 Z$ h+ o+ [# A; |6 L, j8 ^" m+ ] - void TIM1_PWM_Init(u16 arr,u16 psc)) b" J# |5 h( U) H
- { - V4 B- f2 r5 F* m
- GPIO_InitTypeDef GPIO_InitStructure;
6 x+ q; p/ D( r1 R _* P - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
& i+ r* j+ A, s* D O) F - TIM_OCInitTypeDef TIM_OCInitStructure;
$ m' _* u. a% t7 h& b7 B2 A -
& J! K$ [8 e4 n - RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIMx外设, e# U2 u) S, \3 Q- E F2 o& [
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设时钟使能9 l( {1 O; k/ W( B! d" X
- 7 y0 _" H. c) v8 c$ g. Y
- //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
6 D. q7 Y8 u: U0 z6 f2 N; Y - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH1& X( ]3 d; S( M# k
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能输出2 Q9 T( Q: t' O, I, W
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;8 N/ z2 V% ~* H3 t' i
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO/ x2 V, Z& a$ p& a6 O
- + W9 I$ c$ k q, t) D
- TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载周期值: B/ \2 T0 M% G0 ?
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 不分频) j" k/ J- s9 S' h) ?) K# P
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim( y& Q2 \, e% u5 a+ ]& M
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式% j. t! t, R8 O; {' t; z! j4 g7 D# D! H# F
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx
- m' x0 X G& r - : \ t! `. b( x+ g6 Q5 G
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //CH1 PWM2模式 - s0 K/ P' b- o# k& n. A, \& x
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
2 p8 ]( i* G D& r - TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值9 M1 |1 t# h+ Q* y
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //OC1 低电平有效 ! O6 l# n2 t) T7 E/ Z- F
- TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据指定的参数初始化外设TIMx% d ~6 `) y( j: d$ }
$ ]" e! ?! n7 q5 l! ], o4 o Q. L. s- TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1 预装载使能( z5 q( F4 |. W' j# V
-
* G% \" P1 l: w! l - TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器8 T7 ]( x% I7 x6 @2 S D* @$ ^2 R
- " f6 v" g1 _- V; T8 ~5 R p/ w
- TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能,高级定时器必须开启这个 4 A# \! ^- a7 N9 E. _! A; g
-
" `! L( x8 n8 B+ O& R - TIM_Cmd(TIM1, ENABLE); //使能TIMx * |7 S3 B2 ~5 E) H/ n! }
- } 0 B3 M* {6 @4 g
复制代码 7 ^$ F/ {' Q- p' ~
L1 h+ \$ c* F3 [$ r————————————————
& c& I) b% n: R9 i5 _9 r( k版权声明:_Amen- Z4 g& P! ~ w. X; {
如有侵权请联系删除
# p6 ]: m) r( b
& M1 U u: D4 h
4 q/ h+ ]" X1 X! g* N# e( ~& E. X |