你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32F1开发PWM DAC实验经验分享

[复制链接]
攻城狮Melo 发布时间:2023-5-14 17:40
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
20200514191553939.png 8 E4 {* @8 i( B8 B+ M

0 F, h7 j& W9 O* l. [5 Y# e
6 x1 U( R9 G+ _% @9 ~+ T  g6 ^
2020051419162562.png
' W3 m0 b* k7 t% n
( L' ^' @  f, d: F
( U: N( Z8 @4 I8 u. |
20200514191652697.png
3 Y" T/ X8 |% X3 e9 ^% Z2 x" Q6 B& o5 x" d& N* c& n
' @8 B( R/ r6 z5 }0 ~, L
20200514191718963.png
$ 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 20200514191746367.png
+ h: C1 K! _/ U+ Z  {7 {# a" y6 {; ^& M: F7 f# o- ]
main函数
/ I  p+ @0 B5 c. |) X
  1. #include "led.h"4 V: G# {8 B/ B# b" g
  2. #include "delay.h"
    9 O! l2 n1 Y# x
  3. #include "key.h"/ ~) z% [3 j' c8 ]
  4. #include "sys.h"
    3 D; z& T+ \* O! p) y  @
  5. #include "lcd.h"! u/ G' J+ F0 x5 X
  6. #include "usart.h"         
    ) e  B0 o8 w+ Q0 B: p0 c
  7. #include "rtc.h" " N, U6 X7 r9 M& q
  8. #include "wkup.h"
    ! z9 y( z) p% v2 O  i* A, N0 d  j: K
  9. #include "adc.h"         / L( [7 C! }  Y, `* [
  10. #include "dac.h"
    9 k% F! n% U9 a8 V
  11. #include "timer.h"
    5 [+ Z. r' O6 E  q) N8 t) R
  12. #include "usmart.h"
    6 K) C' I" l8 l- ]

  13. 4 [( s1 D% r! s) M7 q
  14. //设置输出电压
    5 g- t: q6 q! k2 [
  15. //vol:0~330,代表0~3.3V/ ?3 A) |, O7 {9 I
  16. void PWM_DAC_Set(u16 vol)# ^! m' _8 ]# @6 e6 b+ y  _2 }
  17. {9 c; C. u1 Z, R* p/ E' ?
  18.         float temp=vol;
    + `+ `! g$ d! q( h
  19.         temp/=100;& B" j. `5 y! w. o+ |# Q5 i; P
  20.         temp=temp*256/3.3;4 Q, ?# J( ]- F2 y( o
  21.         TIM_SetCompare1(TIM1,temp);- z6 a$ ^, B" N' ?
  22. }
    ) j  [0 e+ {) b  G

  23. 4 F0 d: W6 u4 ~9 c/ {
  24. int main(void)# h1 y1 ~' C0 R  v
  25. {         
    , m0 O! r% P! b1 N& E3 l
  26.         u16 adcx;3 K0 \9 K+ S/ B# p/ s
  27.         float temp;
    , o+ `7 _9 ~. a9 j+ c$ S
  28.         u8 t=0;         
    ) f0 q8 x, ~1 w& A0 d1 d$ g! ^* T" g
  29.         u16 pwmval=0;) y: `6 ]# s# J  ^8 j% K: D+ b4 x
  30.         u8 key;
    $ W6 n0 O# O, L. p8 p5 r
  31.         , r- Q9 m, W0 }5 \& K  k
  32.         delay_init();                     //延时函数初始化          
    ! R8 m" u7 w6 g! y1 E! H5 G
  33.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);          //设置NVIC中断分组2:2位抢占优先级,2位响应优先级+ L1 O9 v5 i/ i5 p) E5 ^1 J, f  X
  34.         uart_init(115200);                 //串口初始化为115200
    % }5 x5 q! ]2 h$ S7 y( H% E/ b
  35.         KEY_Init();                                  //KEY初始化
      b  a2 R* i4 e) b
  36.         LED_Init();                             //LED端口初始化: g! ^; f5 k0 U7 t( v( J& \& ?
  37.         usmart_dev.init(72);        //初始化USMART       
    / ~% _9 ^6 V- p. D* a
  38.         LCD_Init();                                  //LCD初始化
    7 q8 @7 T9 R) f( _& v1 d3 W
  39.         Adc_Init();                                  //ADC初始化9 z6 t0 e" {* T
  40.        
    ! v' v, u" Q) i# B7 _
  41.         TIM1_PWM_Init(255,0);        //TIM1 PWM初始化,计数周期为256,Fpwm=72M/256=281.25Khz.. B' x: p# Z9 f
  42.         TIM_SetCompare1(TIM1,100);//初始值为0        . L# c7 `1 n5 o& x
  43.              
    : M5 l. F* s* l# ~/ W7 q
  44.         POINT_COLOR=RED;//设置字体为红色 * l& y9 R2 g6 Z# a
  45.         LCD_ShowString(60,50,200,16,16,"WarShip STM32");       
    * r) h: t/ L* m
  46.         LCD_ShowString(60,70,200,16,16,"PWM DAC TEST");       
    . f, j: Q8 U. E6 x& B. S7 `
  47.         LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
    " m- `, g9 [+ O% [
  48.         LCD_ShowString(60,110,200,16,16,"2015/1/15");        5 R  |4 y1 y7 E% V: y& U
  49.         LCD_ShowString(60,130,200,16,16,"WK_UP:+  KEY1:-");        * w2 ?2 B! c5 T, {  E5 [' ^
  50.         //显示提示信息                                                                                              3 D7 F* l. m/ D5 V7 C
  51.         POINT_COLOR=BLUE;//设置字体为蓝色
    # Z4 o( \" B- K, Y7 |
  52.         LCD_ShowString(60,150,200,16,16,"PWM VAL:");              : H& i  Z! ^& d) g6 F9 r
  53.         LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V");              - N8 O( N) L3 H$ X2 t# I. K
  54.         LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");7 f2 r7 W/ R4 ?/ S) P, s! C& f
  55.         ' \: u9 h3 \3 W" b& ^$ y: m+ L8 ^
  56.         TIM_SetCompare1(TIM1,pwmval);//初始值                         
    + E" d  {) r5 @( _4 j  ^
  57.         while(1)* ^7 @1 k* ^% [: x
  58.         {" @5 H7 }+ h& j7 W4 Z* w# r
  59.                 t++;: h0 ?# Z# i1 C  p% l' ^( U
  60.                 key=KEY_Scan(0);                          ! r3 A' Y* k: e" A
  61.                 if(key==WKUP_PRES)
    . T+ C. a0 n. X' k6 \8 u5 E# l
  62.                 {                 9 }4 M. O8 K3 f( q1 E
  63.                         if(pwmval<250)pwmval+=10;6 ~% r: ^- S. n7 z* c; z+ X- R. B3 t5 t
  64.                         TIM_SetCompare1(TIM1,pwmval);                 //输出+ `1 r( N( ^! E% o, Y% y
  65.                 }else if(key==KEY1_PRES)       
    & b; `; [# X5 X7 a
  66.                 {
    2 G  r% m5 H  L( _& M
  67.                         if(pwmval>10)pwmval-=10;
    % u4 o* G/ W0 y/ d& P4 s/ ~
  68.                         else pwmval=0;
    ; I, ?. ]: t4 Q7 l+ D9 Z: T' G
  69.                         TIM_SetCompare1(TIM1,pwmval);                 //输出1 |$ T' S# _% F+ o) v# p' [
  70.                 }         
      k6 E; L) W" J
  71.                 5 D( a2 B! L' `/ L) N
  72.                 if(t==10||key==KEY1_PRES||key==WKUP_PRES)                 //WKUP/KEY1按下了,或者定时时间到了; Z, r3 i- ]( @4 w6 V( f! g  Q
  73.                 {          , Q* G( L9 w& {  U5 f
  74.                         adcx=TIM_GetCapture1(TIM1);& ~7 f: J0 [- F0 M
  75.                         LCD_ShowxNum(124,150,adcx,4,16,0);             //显示DAC寄存器值4 A9 z) [/ k- A
  76.                         temp=(float)adcx*(3.3/256);                                //得到DAC电压值( C) z) n$ a4 `' M+ h
  77.                         adcx=temp;
    1 I$ V% c, N2 ]3 b
  78.                         LCD_ShowxNum(124,170,temp,1,16,0);             //显示电压值整数部分7 ^+ k2 y7 b2 M" v" C; C
  79.                         temp-=adcx;
    8 [' T( k  h" A2 ]7 s. I
  80.                         temp*=1000;# m$ u9 }9 f) f! U
  81.                         LCD_ShowxNum(140,170,temp,3,16,0x80);         //显示电压值的小数部分6 W/ f$ r, x2 ~+ L
  82.                        
    7 P( H: F8 a; d! o; q8 C- Z% p
  83.                         adcx=Get_Adc_Average(ADC_Channel_1,20); //得到ADC转换值          $ [; v- ^- W8 P( O: ]8 m1 B: w
  84.                         temp=(float)adcx*(3.3/4096);                        //得到ADC电压值3 c" \/ n# u5 G9 }/ r
  85.                         adcx=temp;  [5 g/ n9 F0 v+ ~4 b
  86.                         LCD_ShowxNum(124,190,temp,1,16,0);             //显示电压值整数部分0 N$ J" @$ g, D: x$ Y% n4 B
  87.                         temp-=adcx;
    ) E% e) i# L' j& S4 v: t, g
  88.                         temp*=1000;
    + f' L/ S& l8 e3 |/ L: I" M1 @+ E
  89.                         LCD_ShowxNum(140,190,temp,3,16,0x80);         //显示电压值的小数部分( v2 @) ~+ \8 w) z/ t$ w
  90.                         t=0;
    4 G5 y! E- i* o( [' s! |/ t; x8 d
  91.                         LED0=!LED0;           & }% L9 \" m$ b* T
  92.                 }            . y8 n, X- |$ c. S
  93.                 delay_ms(10);        8 M' \1 R+ v- I: M3 h! u2 h
  94.         }
    3 L  f1 Y1 z2 H7 z" B! w3 ~4 |7 @
  95. }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
  1. //TIM1 CH1 PWM输出设置 7 j  Y; {) t7 \& ^
  2. //PWM输出初始化
    8 E2 }. B- q% w6 k$ ?
  3. //arr:自动重装值
    , D9 f5 \% }6 H, D1 }) u
  4. //psc:时钟预分频数
    9 o. V  a3 Q0 M4 {# K/ A
  5. void TIM1_PWM_Init(u16 arr,u16 psc)
    1 o" i) N/ e. C  S& l# Q) Y8 D
  6. {                                                                  ( p8 _7 f+ Y% }- i1 U4 ]5 q2 h
  7.         GPIO_InitTypeDef GPIO_InitStructure;
    1 E. N+ v  d# t+ G/ J9 F  n
  8.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    * Y3 h- {/ {) X* k* U
  9.         TIM_OCInitTypeDef  TIM_OCInitStructure;; s2 ?$ R0 ?' ~7 b9 \
  10.         6 U. |& n% m7 W3 Z2 V
  11.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIMx外设
    0 I, A9 a) |$ k; b
  12.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA外设时钟使能
    : H. c+ P, y/ J$ \7 L: w) F
  13.          8 `$ K) h0 e2 H4 `( |
  14.   //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
    & |& F- B4 ], q$ P( S# M
  15.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH1
    , u: ^. L) H& B  g, |7 r8 c
  16.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用功能输出9 `8 E0 h( L. E& i7 |5 l
  17.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    3 Y( Z7 X- U' {& I
  18.         GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO
    5 f- m( _+ Y* j$ @. K$ e
  19. ; f* Y1 W/ [2 }1 F+ L
  20.         TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载周期值& _* s. k- k0 K5 Y7 J
  21.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 不分频. r! P! O1 Q1 |2 J( z4 C0 X/ f; l
  22.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    " U  F3 [7 T/ {; R/ ^6 C
  23.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    & X# {4 m) ~8 u! j9 q7 R
  24.         TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx
    4 n" [' m# z9 j& q: B4 M
  25.                  
    7 C* v( u% z1 T( n3 Y
  26.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //CH1 PWM2模式       
    % Q8 Y- q0 ]# V0 J
  27.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能1 x6 ^" q* _' g* [- `
  28.         TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值/ y# j- g7 t9 V+ d9 J  b
  29.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //OC1 低电平有效 5 x' s8 a( t- y( k6 n
  30.         TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据指定的参数初始化外设TIMx
    ! c! J8 [8 r" A0 Z2 O/ ^, q3 _

  31. / F& S0 B& h6 u# d# A5 J
  32.         TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //CH1 预装载使能: X  ?9 n4 v! K$ f# T! Y% V
  33.         - v! d9 V( F1 ^8 H8 P2 m
  34.         TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
    ' ^  h$ g# ~% s
  35.        
    % K) ?3 X! p" S  O; Q
  36.         TIM_CtrlPWMOutputs(TIM1,ENABLE);        //MOE 主输出使能,高级定时器必须开启这个
    0 ]& [3 t7 I' Q
  37.        
    ( k0 \' P, w9 S
  38.         TIM_Cmd(TIM1, ENABLE);  //使能TIMx                                                                                             
    # Q& ~$ c, G- ]! a  o' |
  39. }
    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
赞 收藏 评论0 发布时间:2023-5-14 17:40

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版