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

【经验分享】STM32-PWM呼吸灯实验之软硬件设计

[复制链接]
STMCU小助手 发布时间:2022-6-30 19:00
硬件设计
    硬件电路非常简单,只使用到开发板上的 LED(D7),因为 D7 指示灯接在 PC6 管脚,而通过对 TIM3_CH1 复用功能完全重映射就可以映射到 PC6 脚。所以可以通过 TIM3 的 CH1输出PWM 信号,实现 D7 指示灯呼吸灯的控制。

3 `' P/ b1 c9 Y% ~5 ?! Z
软件设计
    所要实现的功能是:通过 TIM3 的 CH1 输出一个 PWM 信号,控制D7 指示灯由暗变亮,再由亮变暗,类似于人的呼吸。程序框架如下:
(1)初始化 PC6 管脚为PWM 输出功能
(2)PWM 输出控制程序
    在前面介绍通用定时器PWM配置步骤时,就已经讲解如何初始化 PWM。下面我们打开“\4--实验程序\库函数版\13. PWM 呼吸灯实验”工程,在 APP工程组中可以看到添加了 pwm.c 文件,在 StdPeriph_Driver 工程组中添加了stm32f10x_tim.c 库文件。定时器操作的库函数都放在 stm32f10x_tim.c 和stm32f10x_tim.h 文件中,所以使用到定时器功能就必须加入 stm32f10x_tim.c文件,同时还要包含对应的头文件路径。

; M& Z% s8 y; ^# k. x
TIM3 通道 1的 PWM初始化函数
    要使用定时器的 PWM 输出功能,我们必须先对它进行配置。TIM3 通道 1 的PWM 初始化代码如下:
  1. /**************************************************************2 m# Z3 _- r, R( d, y+ Y
  2. * 函 数 名 : TIM3_CH1_PWM_Init! O8 `& S- S! f9 E
  3. * 函数功能 : TIM3 通道 1 PWM 初始化函数
    ! {9 i# N3 h! f6 S) }
  4. * 输 入 : per:重装载值psc:分频系数$ [, p7 j* Y3 L$ R# |+ n6 U
  5. * 输 出 : 无
    8 C# t/ M- W, P7 ^) Q, j
  6. ****************************************************************/
    9 b' e$ k) x8 L0 G- _1 r: E
  7. void TIM3_CH1_PWM_Init(u16 per,u16 psc)" [5 ^) `' f/ E7 A/ H& L. ]8 p  z7 D
  8. {
    # z+ Y" s( H# R7 r7 `
  9. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;) \# v& f5 M' s; [
  10. TIM_OCInitTypeDef TIM_OCInitStructure;
    0 ?- T3 C% h7 m0 ?; Z
  11. GPIO_InitTypeDef GPIO_InitStructure;
    ! _" y' b7 o. k, @$ n3 I$ r
  12. /* 开启时钟 */) O- v0 Y; x, @- j  Q* G
  13. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
    & o5 m" O, f' v5 W9 _
  14. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    " P; l( z$ n0 P& |, t, Y
  15. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    7 u- v- a; Q" E( f6 b% X' v
  16. /* 配置 GPIO 的模式和IO 口 */
    7 o; ~+ K9 e1 K# l# y, _. p) _
  17. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;+ f9 k7 V4 P, H* H
  18. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;& K8 V% q# V5 j
  19. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
      u5 t# B$ r$ T( `
  20. GPIO_Init(GPIOC,&GPIO_InitStructure);) G/ O$ e( q. T2 c
  21. GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//改变指定管脚" O7 _' ?, o2 V; h6 N; v" o
  22. 的映射
    " w' h; v; K6 \  N5 J, _& ~7 B* G( H3 a
  23. TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值2 {) i% K, L& U; }/ n$ {
  24. TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数% h( z; z9 u: W2 ]. c, k2 j
  25. TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;+ k+ v6 E" n! C5 P& ?* k
  26. TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;* q8 `, Z' a- e& d/ }
  27. //设置向上计数模式' U9 S! c9 V- d  R/ L4 E9 T6 ]
  28. TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);1 U) Q7 i; v3 n  n2 V: E7 d
  29. TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;7 P& Y9 C# {  j: e1 {; O" K
  30. TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;! [0 t, t2 v' m9 ]1 Y- [# f
  31. TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;$ o% n( q3 Y9 g  W3 x6 t- {
  32. TIM_OC1Init(TIM3,&TIM_OCInitStructure); //输出比较通道1初始化
    $ a# c% p! E" Q; j7 U' C
  33. TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能 TIMx 在
    + S  G6 k/ y) r/ w- J9 P
  34. CCR1 上的预装载寄存器6 h+ p5 r- n  {
  35. TIM_ARRPreloadConfig(TIM3,ENABLE);//使能预装载寄存器
    & A0 T2 C$ }1 H4 [9 n& l
  36. TIM_Cmd(TIM3,ENABLE); //使能定时器
    - n1 s% `$ H6 @0 v) M& ]4 C, c
  37. }
复制代码

# R1 U- n% Z' x# F
    在 TIM3_CH1_PWM_Init()函数中,首先使能 GPIOC 端口时钟、TIM3 时钟和AFIO时钟,其次配置 TIM3_CH1 为完全复用重映射功能,并将 PC6 管脚模式配置为复用推挽输出。然后配置定时器结构体 TIM_TimeBaseInitStructure,初始化PWM 输出参数,由于我们的 LED 指示灯是低电平点亮,而我们希望当 CCR1 的值小的时候,LED 暗, CCR1 值大的时候,LED 亮,所以我们设置为 PWM1 模式,输出极性为低电平,使能 PWM 输出。最后就是开启 TIM3。这一过程在前面步骤介绍中已经提了。程序中我们看到最后调用了 TIM_OC1PreloadConfig()和TIM_ARRPreloadConfig,他们是用来使能 TIM3 在 CCR1 上的预装载寄存器和自动重装载寄存器,第一个库函数必须调用,第二个的话如果不调用也没有关系。
    TIM3_CH1_PWM_Init()函数有两个参数,用来设置定时器的自动装载值和分频系数,方便大家修改 PWM频率。
    其实如果你会使用通用定时器 TIM3 的 CH1 输出 PWM,那么其他通用定时器通道都一样。
9 D9 x- z7 i- d2 a4 [8 u
主函数
    编写好 PWM 初始化函数后,接下来就可以编写主函数了,代码如下:
  1. /***************************************************************
      v: `* n3 d6 J# g/ v
  2. * 函 数 名 : main
    7 g& H, z  q' d' _( }
  3. * 函数功能 : 主函数
    " w% i- u4 d7 o9 J
  4. * 输 入 : 无& b, e5 q  s( Q$ n
  5. * 输 出 : 无0 {* a( L7 |* Z  N- _
  6. ****************************************************************/
    : R+ M( J. o' ]# E
  7. int main()
    & B- O8 o" G7 q  F$ e
  8. {6 A, }- Y1 N! J- e) b- s
  9.   u16 i=0;
    " _7 Z9 ^( n( n& R2 r  V9 W
  10.   u8 fx=0;
    3 g, @4 R6 ?* T) b/ X) f
  11.   SysTick_Init(72);
    ' x7 z) l3 x- ]5 d* }* |! f: H
  12.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2 组8 h( L/ D8 x0 A/ D+ }6 X* K3 v9 N
  13.   LED_Init();
    8 P& A% e" f. Q* ^' G
  14.   TIM3_CH1_PWM_Init(500,72-1); //频率是 2Kh
    " m+ y5 m9 E3 s* Q6 G2 x
  15.   while(1)3 ]  L- B# F/ h, T9 B
  16.   {: P8 ~" j) ~) E! \/ J% d
  17.     if(fx==0)' d9 v- Q" ~- k7 z
  18.     {
    1 [5 _. H$ w; M
  19.         i++;0 w7 u) ^1 @8 h" d+ G) ]
  20.         if(i==300)
    ! z' A4 }0 J. ^# V, v, v0 m0 x
  21.         {
    9 G) O& r" |; {1 C* ?# A0 z
  22.           fx=1;* o* S- \) A, I; B  L  p& q
  23.         }
    " a$ [, I; u& s, c: s  I2 r; Q
  24.       }- U& X5 n8 S$ `+ T0 l, {1 d' w
  25.     else" {1 B" G: c1 ]# o
  26.     {/ h9 z9 n" I' V4 l, B
  27.       i--;' c- _' c, v5 {# j) ]
  28.       if(i==0)  C5 Q  T3 d' L2 z$ v! \
  29.       {
    # m1 O$ n) {7 g1 O4 j  s; o
  30.         fx=0;# I7 w8 H- l2 [, N
  31.       }
    2 H% ~, b' w$ ^$ S! @6 W, w
  32.     }
    0 }: u" e' G$ E; g+ m  o+ ?
  33.    TIM_SetCompare1(TIM3,i); //i 值最大可以取 499,因为 ARR最大值是 499.) H0 t" f9 E+ h8 |" P* \& X( {
  34.    delay_ms(10);9 ~7 \' m0 ?6 ^7 |& j
  35.   }
    # r9 N+ W8 `. E/ h$ q+ d
  36. }
复制代码

& a' {1 }  h3 A/ ]  o- r: g1 E
    主函数实现的功能很简单,首先初始化对应的硬件端口时钟和 IO 口,然后调用我们前面编写的 TIM3_CH1_PWM_Init 函数, 这里我们设定定时器自动重装载值为 500,预分频系数为72-1,定时周期即为 500us,频率即为 2KHz,这里为什么减 1在定时器中断已经介绍。
    初始化后,定时器开始工作,PC6 开始输出 PWM 波形,波形频率为 2K,你也可以修改这个频率值,但是要注意,不能将频率设置过大,否则会看到 D7 指示灯有明显的闪烁。通过变量 fx 控制 i 的方向,如果 fx=0,i 值累加,否则递减,然后将这个变化的 i 值传递给TIM_SetCompare1 函数, 这个函数功能是改变占空比的,因此可以实现 D1 指示灯亮度的调节,呈现呼吸灯的效果。程序中将 i 值控制在 300 内,主要是因为 PWM 输出波形占空比达到这个值时,D1 指示灯亮度变化就不明显了,而且我们在初始化定时器时,将自动重装载值设置为499,所以这个i 值也不能超过。
    将工程程序编译后下载到开发板内,可以看到 D7 指示灯由暗变亮,再由亮变暗,呈现呼吸灯的效果。
# j1 g2 \# M0 I" h. Q
赞 收藏 评论0 发布时间:2022-6-30 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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