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

基于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的设定输出电压值等信息。
; j) Q& A; e5 s; B6 `8 x8 H
- c2 U  T* G; }! U$ l" X* }
  u; q' Z; M$ P# u* E6 {) k
20200514191553939.png
9 G" k) m( k$ H- s8 Z1 ?
9 f! X+ R# b1 K

% g# V' ?1 C" B( V" K! X  i  v 2020051419162562.png
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 20200514191652697.png
9 v, ?# j( k' k0 P' T4 c7 W- F8 z5 Z
1 g4 p7 n: b. g( q" u; D
20200514191718963.png
8 b6 ], q* _; A; _) {- z9 C# ~) B( C# `# A5 f' s

3 A5 R9 [/ e* q! R 20200514191746367.png
( 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
  1. #include "led.h"0 {$ t5 ?2 h8 {' k+ d. q- k* ]
  2. #include "delay.h"
    4 h8 i& Q5 ]0 E/ y: \
  3. #include "key.h"
    ) a4 k4 G' c0 r% n# f2 X4 t
  4. #include "sys.h"
    - Q& e8 j( `) @% n0 X4 U
  5. #include "lcd.h"  m" Y8 E2 G3 \
  6. #include "usart.h"         
      d; E8 ?  {5 G& f
  7. #include "rtc.h" 7 M2 E8 {5 I; U7 |- E7 E7 U
  8. #include "wkup.h"% P5 J6 V) J# ?$ l, t2 A( ~
  9. #include "adc.h"         / n% C: H& {+ X9 o8 h! }
  10. #include "dac.h"/ b2 c* I2 B2 z
  11. #include "timer.h"/ Y& q: F4 l+ _* M8 F3 J# k
  12. #include "usmart.h"2 }% }6 p* A1 V! ]; c1 E/ J( G

  13. 3 O+ z1 G  m$ d6 C3 T! O6 D
  14. //设置输出电压& D$ e- S+ W' [/ Q# t8 d
  15. //vol:0~330,代表0~3.3V
    8 B: w) a( X) @8 L2 F" D. l% Q
  16. void PWM_DAC_Set(u16 vol)8 C7 P3 |9 W5 k, Q3 `
  17. {& J1 F$ Q4 }3 Y0 [% j. g& e9 d
  18.         float temp=vol;+ ~% g. j8 H/ J: d. T3 l7 w
  19.         temp/=100;
    $ |4 I% B6 Y  t+ H  U2 F0 v
  20.         temp=temp*256/3.3;2 n/ L) t% V9 O% t
  21.         TIM_SetCompare1(TIM1,temp);
    + M# A1 j5 S+ ?+ U' ~9 U
  22. }+ ^& Q9 r' ~! E4 w& n1 N7 S
  23. 4 n: G0 f! {# K1 }
  24. int main(void)
    1 I- s/ u7 Z, A
  25. {         # u: }# h3 T3 x
  26.         u16 adcx;
    $ L' T/ \0 ~; M" ~
  27.         float temp;
    6 _1 k8 `: P4 a# k7 M
  28.         u8 t=0;         . B' `. X& x; N& ]+ b4 `. G
  29.         u16 pwmval=0;
    4 z1 N2 ?3 H0 L
  30.         u8 key;( y) W9 O, l" g8 \
  31.        
    3 k$ P5 T# l# g8 u7 B; ^
  32.         delay_init();                     //延时函数初始化          # e! \9 }+ u# @& n( ^. P
  33.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);          //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    5 O. f' z: I% c  i/ [6 P/ A) L" ?% z
  34.         uart_init(115200);                 //串口初始化为115200
    6 K3 P; b! N' S9 |( K
  35.         KEY_Init();                                  //KEY初始化
    ( o; `& W( w( q  z& w
  36.         LED_Init();                             //LED端口初始化
    + ~/ ^( O3 E( I, F( J2 h. q
  37.         usmart_dev.init(72);        //初始化USMART        6 c4 ]' v! a0 G3 l4 G
  38.         LCD_Init();                                  //LCD初始化4 n; v$ X) V- g# `$ Z
  39.         Adc_Init();                                  //ADC初始化
    9 W8 e% U* H3 M2 k* o# H# H
  40.        
    ( x) b6 q6 z+ ]
  41.         TIM1_PWM_Init(255,0);        //TIM1 PWM初始化,计数周期为256,Fpwm=72M/256=281.25Khz." R* m$ i7 p6 w- p. j4 Y1 [
  42.         TIM_SetCompare1(TIM1,100);//初始值为0       
    & Z( g7 V: T4 U0 ]
  43.              
    / H2 R3 k1 e* C
  44.         POINT_COLOR=RED;//设置字体为红色
    : B' X' n! a8 n" g
  45.         LCD_ShowString(60,50,200,16,16,"WarShip STM32");       
    ! Z( [# t* F& P, l2 X/ Q( K
  46.         LCD_ShowString(60,70,200,16,16,"PWM DAC TEST");       
    9 a  q% K( \* G8 W/ ]6 h% E7 j+ {
  47.         LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
    % m; S9 m, ~! w" V$ U6 W2 `
  48.         LCD_ShowString(60,110,200,16,16,"2015/1/15");        % X6 X6 {( }% e. M% \1 D
  49.         LCD_ShowString(60,130,200,16,16,"WK_UP:+  KEY1:-");       
    3 p1 K0 I, P7 y2 a
  50.         //显示提示信息                                                                                             
    - O% O6 T, d9 y1 i4 \; V
  51.         POINT_COLOR=BLUE;//设置字体为蓝色, ^8 }7 A. G$ W9 s" K- L2 }5 s
  52.         LCD_ShowString(60,150,200,16,16,"PWM VAL:");             
    $ ]1 ~+ u9 x$ ^5 ^, S- Q; D
  53.         LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V");              ) o: ~0 r, d( `# I6 W: _3 I
  54.         LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");
    / k7 s$ o: p, n
  55.        
    8 |' R  g" a. e9 j( p- `( e
  56.         TIM_SetCompare1(TIM1,pwmval);//初始值                         
    8 A( v6 `7 e5 p' O
  57.         while(1)
    % }1 a3 M9 m1 W. f* ~0 P' c/ G
  58.         {
    1 m3 e8 V0 N9 `2 @
  59.                 t++;' _- U, U5 ~" b0 s: e' K2 e- C& ]
  60.                 key=KEY_Scan(0);                          
    ! V" L/ j2 U8 H0 ?' s
  61.                 if(key==WKUP_PRES). I* k: d5 Y7 h; F: W4 t
  62.                 {                 
    - C- ~; [2 e; l3 Z2 ~
  63.                         if(pwmval<250)pwmval+=10;
    0 A$ U7 K7 h! M* V/ c+ T$ W
  64.                         TIM_SetCompare1(TIM1,pwmval);                 //输出. H5 \* m9 a1 A# {
  65.                 }else if(key==KEY1_PRES)       
    0 ^, K% A0 N) O# Q. ~4 i: l" y
  66.                 {
    3 y3 I3 z/ \# d! e7 m
  67.                         if(pwmval>10)pwmval-=10;
    8 n3 j6 Y4 n! u* G# G7 p9 e. [
  68.                         else pwmval=0;4 c/ g4 ]& V1 @$ D
  69.                         TIM_SetCompare1(TIM1,pwmval);                 //输出
    - l0 s5 @9 T5 X7 A4 w& p
  70.                 }         * k  R- W: E/ G  Q
  71.                 7 t# @6 K& w1 L+ i
  72.                 if(t==10||key==KEY1_PRES||key==WKUP_PRES)                 //WKUP/KEY1按下了,或者定时时间到了# ]4 g5 g& ^: A5 ^$ a
  73.                 {          ( f5 T$ S$ G8 l. c$ t6 v
  74.                         adcx=TIM_GetCapture1(TIM1);
    3 y8 [* _1 u0 J9 X5 p) m
  75.                         LCD_ShowxNum(124,150,adcx,4,16,0);             //显示DAC寄存器值
    4 G( S, F( P( y' x; y/ U
  76.                         temp=(float)adcx*(3.3/256);                                //得到DAC电压值
    3 t) a* d1 r# U3 M% s' L1 |
  77.                         adcx=temp;2 V4 p1 K1 y# S; t( l
  78.                         LCD_ShowxNum(124,170,temp,1,16,0);             //显示电压值整数部分
    4 v6 E# u0 D7 H4 ]; B4 P
  79.                         temp-=adcx;' J% @$ B; |* A  R  @) v( a
  80.                         temp*=1000;
    3 |2 ?" T% t0 F
  81.                         LCD_ShowxNum(140,170,temp,3,16,0x80);         //显示电压值的小数部分
    9 p4 q3 W) O7 |( C
  82.                        
    " r. e1 {& d0 H
  83.                         adcx=Get_Adc_Average(ADC_Channel_1,20); //得到ADC转换值          
    * t2 H- j" p/ W$ T  o
  84.                         temp=(float)adcx*(3.3/4096);                        //得到ADC电压值
    * r3 l" ]2 f# `$ T' s5 a; q
  85.                         adcx=temp;! k! w9 j5 ^" ^: @  g6 p: l$ i
  86.                         LCD_ShowxNum(124,190,temp,1,16,0);             //显示电压值整数部分; }. H2 ]: e9 B% E" y
  87.                         temp-=adcx;9 s5 A. U( d' [7 K$ c) k
  88.                         temp*=1000;% n* H, v5 ]/ @' }
  89.                         LCD_ShowxNum(140,190,temp,3,16,0x80);         //显示电压值的小数部分
    / e% b5 k. T' P6 a0 E' R
  90.                         t=0;& o. C( i, |7 ]. x3 N5 a
  91.                         LED0=!LED0;          
    ' l" i# `- `  ~7 r% d
  92.                 }            
    * g9 ?- e+ G2 I; `
  93.                 delay_ms(10);        + e% l  D5 b" ~
  94.         }& g" ~+ ~5 L3 S# R- n% d. G. Q: _
  95. }! 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
  1. //TIM1 CH1 PWM输出设置 6 b& t# y" T" f8 r- v
  2. //PWM输出初始化
    / O3 F. g+ c0 Q6 w( Q* t
  3. //arr:自动重装值4 ?0 t  O. z# Z5 p# e
  4. //psc:时钟预分频数
    ! q1 m0 e4 P1 O+ Z8 B2 Z7 d# M( z
  5. void TIM1_PWM_Init(u16 arr,u16 psc)' f0 D4 ~0 C+ r1 z0 [
  6. {                                                                 
    % G) D( R0 b$ F: W
  7.         GPIO_InitTypeDef GPIO_InitStructure;6 |6 ^; T, U7 Y
  8.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;7 |/ U6 V" O# w2 t) I( z
  9.         TIM_OCInitTypeDef  TIM_OCInitStructure;) c1 r! w* O7 E3 _5 S; r
  10.         8 q! T' j+ n- }1 I+ D7 r
  11.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能TIMx外设
    " G; q* v. h, o; O* r
  12.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA外设时钟使能2 N$ e* w+ w! c' {
  13.          7 C9 Z, I- ]+ Q, A1 P
  14.   //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形! ~3 V( i7 v  r8 w4 ^- Y
  15.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH16 J2 ~8 T" i1 z! ^# M8 U3 b: r
  16.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用功能输出! A7 r8 k9 ?7 E* Q
  17.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    + ?& R' d  z: o" ^& F+ N4 B/ o$ S
  18.         GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO" ]3 s) x5 q, _! [4 T1 T

  19. 0 p0 \" v: x8 P- k
  20.         TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载周期值
    # C# B$ b, |& b# `
  21.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 不分频$ o1 s' t3 t( `) M
  22.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    9 T# @+ s$ a- Q8 G. A/ i; M
  23.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式% [; Q/ W5 C: R6 {1 i8 M
  24.         TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx: S$ r. j2 F% o; s6 ^, N. i* j
  25.                  
    " I% m& S+ |( c! t
  26.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //CH1 PWM2模式       
      w- E4 |6 |$ a
  27.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    9 v# K" k+ H% U
  28.         TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
    . E! k5 f0 {" u4 U# B7 ]
  29.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //OC1 低电平有效
    3 P2 A2 g  {8 v+ O# D4 \
  30.         TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据指定的参数初始化外设TIMx
    ! Y8 H2 l+ C4 l2 e% x3 P' G$ n
  31. + D7 d" m) d- @, v: r0 d
  32.         TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //CH1 预装载使能
    1 U1 y  v3 U& H8 b0 m
  33.         9 A; S! ]- W. t9 ^% M4 N1 v
  34.         TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
    * K' J1 X! l6 x* S; ?
  35.         9 z* _8 K0 j# ~: A: U7 }
  36.         TIM_CtrlPWMOutputs(TIM1,ENABLE);        //MOE 主输出使能,高级定时器必须开启这个 % U: A* ~+ s. Y7 c
  37.         . X+ |  P) g$ s) t+ g
  38.         TIM_Cmd(TIM1, ENABLE);  //使能TIMx                                                                                             6 T" \. x2 V; ]5 D: K, p% w- L
  39. } $ 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
赞 收藏 评论0 发布时间:2023-5-14 17:40

举报

0个回答

所属标签

相似技术帖

官网相关资源

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