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

基于Cubemx与HAL库之PWM呼吸灯经验分享

[复制链接]
攻城狮Melo 发布时间:2023-4-2 18:31
摘要

本章还是点灯,但是小飞哥带大家换一种点灯方式,利用PWM功能实现“呼吸灯”,什么是呼吸灯?顾名思义,像人呼吸一样的灯...简而言之就是,吸气...呼气...实现灯光渐亮渐灭的效果。


PWM原理介绍

脉冲宽度调制(PWM),是英文“Pulse Width Modulation” 的缩写,简称脉宽调制,是利用 微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽 度的控制,如下图(摘自正点原子手册)



微信图片_20230402183103.png

PWM 原理示意图


上图就是一个简单的PWM 原理示意图。图中,我们假定定时器工作在向上计数PWM模式,且当 CNT<CCRx时,输出0,当CNT>=CCRx时输出1。那么就可以得到如上的PWM示意图:当CNT值小于CCRx的时候,IO输出低电平(0),当CNT值大于等于CCRx的时候,IO输出高电平(1),当CNT达到ARR值的时候,重新归零,然后重新向上计数,依次循环。改变CCRx的值,就可以改变PWM输出的占空比,改变 ARR的值,就可以改变PWM输出的频率,这就是PWM输出的原理。


STM32的定时器几乎都能够产生PWM波,高级定时器 TIM1和TIM8可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM输出,如下图定时器4,可以产生4路PWM波。本文,咱们只使用一路PWM,学懂原理之后,随便怎么搞~


微信图片_20230402183100.png


cubemx配置PWM

本次使用的是TIM4的通道4来产生PWM波,也即是PB9。硬件连接比较简单,LED正极连接PB9,负极连接GND即可。

关于时钟等配置,就不多做介绍了

选择TIM4->勾选inter clock->通道4->PWM output CH4->PB9


微信图片_20230402183056.png


定时器参数配置,主要分为两部分,一部分是定时器的基本配置,分频系数、周期,这个配置不是固定的,把握频率的计算方式即可:

fclk= (Fcore/(Prescaler+1)/(Period+1)


按照我的配置,计算有得到:

fclk = 72000000/500/72=2KHZ

这个频率是直接影响到LED灯光的闪烁频率的,如果设置的太低了,会有明显的闪烁感。


微信图片_20230402183052.png


PB9是被复用的


微信图片_20230402183049.png


配置是比较简单的,直接生成代码即可


PWM代码解析

上面知道,PB9是被复用为PWM通道功能的,代码如下,自从有了cubemx,代码初始化似乎变得简单了呢...

  1. void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
  2. {

  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
  4.   if(timHandle->Instance==TIM4)
  5.   {
  6.   /* USER CODE BEGIN TIM4_MspPostInit 0 */

  7.   /* USER CODE END TIM4_MspPostInit 0 */

  8.     __HAL_RCC_GPIOB_CLK_ENABLE();
  9.     /**TIM4 GPIO Configuration
  10.     PB9     ------> TIM4_CH4
  11.     */
  12.     GPIO_InitStruct.Pin = GPIO_PIN_9;
  13.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  14.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  15.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  16.   /* USER CODE BEGIN TIM4_MspPostInit 1 */

  17.   /* USER CODE END TIM4_MspPostInit 1 */
  18.   }

  19. }
复制代码

上面我们对定时器及PWM参数的配置代码如下,其中有一个参数.pulse,这个参数是决定PWM的占空比的,计算如下:

Pulse = .pulse/period


计算得出的就是我们波形,高电平(由于是配置的模式1)所占整个周期的比例,占得比例越高,相应的电压会越高,对应的LED灯会越亮


关于定时器的参数是被封装在一个结构体里面的:

  1. /**
  2.   * @brief  TIM Time base Configuration Structure definition
  3.   */
  4. typedef struct
  5. {
  6.   uint32_t Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
  7.                                    This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */

  8.   uint32_t CounterMode;       /*!< Specifies the counter mode.
  9.                                    This parameter can be a value of @ref TIM_Counter_Mode */

  10.   uint32_t Period;            /*!< Specifies the period value to be loaded into the active
  11.                                    Auto-Reload Register at the next update event.
  12.                                    This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF.  */

  13.   uint32_t ClockDivision;     /*!< Specifies the clock division.
  14.                                    This parameter can be a value of @ref TIM_ClockDivision */

  15.   uint32_t RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
  16.                                     reaches zero, an update event is generated and counting restarts
  17.                                     from the RCR value (N).
  18.                                     This means in PWM mode that (N+1) corresponds to:
  19.                                         - the number of PWM periods in edge-aligned mode
  20.                                         - the number of half PWM period in center-aligned mode
  21.                                      GP timers: this parameter must be a number between Min_Data = 0x00 and
  22.                                      Max_Data = 0xFF.
  23.                                      Advanced timers: this parameter must be a number between Min_Data = 0x0000 and
  24.                                      Max_Data = 0xFFFF. */

  25.   uint32_t AutoReloadPreload;  /*!< Specifies the auto-reload preload.
  26.                                    This parameter can be a value of @ref TIM_AutoReloadPreload */
  27. } TIM_Base_InitTypeDef;
复制代码
  1. /**
  2.   * @brief  TIM One Pulse Mode Configuration Structure definition
  3.   */
  4. typedef struct
  5. {
  6.   uint32_t OCMode;        /*!< Specifies the TIM mode.
  7.                                This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */

  8.   uint32_t Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
  9.                                This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */

  10.   uint32_t OCPolarity;    /*!< Specifies the output polarity.
  11.                                This parameter can be a value of @ref TIM_Output_Compare_Polarity */

  12.   uint32_t OCNPolarity;   /*!< Specifies the complementary output polarity.
  13.                                This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
  14.                                @note This parameter is valid only for timer instances supporting break feature. */

  15.   uint32_t OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.
  16.                                This parameter can be a value of @ref TIM_Output_Compare_Idle_State
  17.                                @note This parameter is valid only for timer instances supporting break feature. */

  18.   uint32_t OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.
  19.                                This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
  20.                                @note This parameter is valid only for timer instances supporting break feature. */

  21.   uint32_t ICPolarity;    /*!< Specifies the active edge of the input signal.
  22.                                This parameter can be a value of @ref TIM_Input_Capture_Polarity */

  23.   uint32_t ICSelection;   /*!< Specifies the input.
  24.                               This parameter can be a value of @ref TIM_Input_Capture_Selection */

  25.   uint32_t ICFilter;      /*!< Specifies the input capture filter.
  26.                               This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
  27. } TIM_OnePulse_InitTypeDef;
复制代码

同样的,PWM的配置也是被封装在一个结构体里面,所以说,用了cubemx是方便了,其实对初学者学习是不太好的,知道了怎么用功能,但是背后的代码结构可能了解的会很少...


微信图片_20230402183046.png


关于PWM的函数还是非常多的,此次功能比较简单,仅仅用到了红框中的几个函数,主要看看start函数,其他的初始化过程中自动调用了,不用关心。


微信图片_20230402183042.png


start函数需要传两个参数,一个是定时器,另一个是对应的PWM通道号,本次

利用到的是TIM4,通道4


微信图片_20230402183039.png


启动定时器之后,我们需要更改的参数是PWM的占空间比,HAL库以宏定义的方式给了我们定义,看了这个代码之后,你有没有一种感觉,每天满世界找优秀的代码,找优美的宏定义写法,这不就挺好的...所以,库函数本身就是一个宝藏学习资料,大家不要忽略了


微信图片_20230402183036.png


代码编写

看了上面的函数介绍之后,其实写起来就很简单了,结构体能够让代码变得整洁一些,先来定义一个呼吸灯相关的结构体:

  1. typedef struct{
  2. uint16_t LedpwmVal;//占空比调整参数
  3. uint8_t LedpwmVal_Dir:1;//调整方向,1-递增,0递减
  4. }peripheral;
复制代码


初始化结构体成员为0,1,启动PWM波,接下来编写呼吸灯效果代码,代码也是非常的简单,延时是不能省略的,否则效果是眼睛分辨不出来的...代码也是非常的简单



微信图片_20230402183033.png


  1. while (1)
  2.   {
  3.     /* USER CODE END WHILE */

  4.     /* USER CODE BEGIN 3 */
  5.   HAL_Delay(10);//加延时,否则变化不明显,看不到效果
  6.   
  7.   if(PWM.LedpwmVal_Dir)
  8.    PWM.LedpwmVal++;
  9.   else
  10.    PWM.LedpwmVal--;
  11.   
  12.   if(PWM.LedpwmVal>breath_UP)
  13.    PWM.LedpwmVal_Dir=Breath_DOWN;//切换为PWM值递减状态
  14.   
  15.   if(PWM.LedpwmVal==Breath_DOWN)
  16.    PWM.LedpwmVal_Dir=1;//切换为PWM值递增状态
  17.   
  18. // TIM4->CCR4 = PWM.LedpwmVal;
  19.   __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,PWM.LedpwmVal);//设置占空比参数
  20.   }
复制代码


呼吸灯波形实际是怎么样的呢,接下来通过逻辑分析仪来看看波形


为了效果明显,我们选择10ms增加10的比例来看看波形:

递增效果:


微信图片_20230402183030.png


递减效果:


微信图片_20230402183026.png
转载自:Embedded小飞哥
如有侵权请联系删除


收藏 评论0 发布时间:2023-4-2 18:31

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版