基于stm32的pwm调节占空比实验HAL库方式实现
本文目标:基于stm32的pwm调节占空比实验HAL库方式实现
按照本文的描述,应该可以跑通实验并举一反三。
先决条件:装有编译和集成的开发环境,比如:Keil uVision5、STM32CubeMX
使用外设:TIM、GPIO
前言
这篇文章是自己捣鼓一个rgb灯时需要实现亮度调节,于是根据自己所拥有的硬件平台进行验证一下,顺便给一些初学者一些启发。
实验目的
基于stm32的pwm调节占空比实验HAL库方式实现,使用两个按键实现灯的亮度实验。在本实验过程中,我们将涉及 STM32 的 GPIO 端口配置、TIM等。
学习了前面几篇博客的基础上,我们可以实现完成这个实验。
基于stm32的time定时器HAL库编程_独处东汉的博客-CSDN博客
基于HAL库的stm32呼吸灯实验_基于stm32的呼吸灯设计_独处东汉的博客-CSDN博客
基于stm32的gpio实验HAL库方式实现_独处东汉的博客-CSDN博客
关于实验原理图
根据我这里的硬件原理图,想要驱动LED_R亮,那么mcu的PB0低电平可以亮,给高电平灯灭。我们想实现变亮度需要是利用定时器的TIM外设,可以看到我这里的原理图设计在TIM3_CH3上,于是我们这里可以利用TIM3来实现灯的亮度调节,按键这里的原理图解析则是常态下都是高电平,按下按键则可以读取到低电平。基于这个原理图,准备好一个工程模板。
搭建工程
使用STM32CubeMX配置stm32的基本配置。基本的配置如下:开启swd调试,开启外部时钟。
- 配置TIM3
这个CH有效电平按照我的理解,就我的这个场景中,期望的有效电平是低电平,所以笔者这里设置成了低电平。
- 配置按键gpio
- 时钟界面选项卡:
- 工程选项卡:
点击右上角的的生成代码:
使用keil打开工程,编译工程,一切都是ok
编写代码实现需求
我们使用场景是使用两个按键实现加减灯的亮度,按下KEY1按键亮度增加,按下KEY2的按键亮度减少。接下来创建两个文件,led_pwm.c和led_pwm.h简单粗暴的写一些代码,实现我们亮度调节的逻辑,其中led_pwm.c的代码如下:
#include "led_pwm.h"
#include "stm32f1xx_ll_tim.h"
#include "key.h"
LED led_pwm = {0};
float aDutyCycle[TIM_DUTYCYCLE_NB] = {
0.0, /* 0% */
0.1, /* 10% */
0.2, /* 20% */
0.3, /* 30% */
0.4, /* 40% */
0.5, /* 50% */
0.6, /* 60% */
0.7, /* 70% */
0.8, /* 80% */
0.9, /* 90% */
1.0, /* 100% */
};
/*********************************************************************************
* 函数名 :led_pwm_test
* 描述 :pwm灯测试一下
**********************************************************************************/
void led_pwm_test(void)
{
static uint8_t iDutyCycle = 0;
iDutyCycle = (iDutyCycle + 1) % TIM_DUTYCYCLE_NB;
/* Set duty cycle */
LL_TIM_OC_SetCompareCH3(TIM3, (LL_TIM_GetAutoReload(TIM3) * aDutyCycle[iDutyCycle]));
}
/*********************************************************************************
* 函数名 :led_pwm_init
* 描述 :灯初始化
**********************************************************************************/
void led_pwm_init(void)
{
led_pwm.dutycycle = 5;
// 直接设置50%的占空比
LL_TIM_OC_SetCompareCH3(TIM3, (LL_TIM_GetAutoReload(TIM3) * aDutyCycle[led_pwm.dutycycle]));
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
}
/*********************************************************************************
* 函数名 :led_pwm_add
* 描述 :灯亮度加
**********************************************************************************/
void led_pwm_add(void)
{
if(key_even_flag == 1)
{
led_pwm.dutycycle++;
if(led_pwm.dutycycle >= TIM_DUTYCYCLE_NB-1) led_pwm.dutycycle = TIM_DUTYCYCLE_NB-1;
LL_TIM_OC_SetCompareCH3(TIM3, (LL_TIM_GetAutoReload(TIM3) * aDutyCycle[led_pwm.dutycycle]));
key_even_flag = 0;
}
}
/*********************************************************************************
* 函数名 :led_pwm_sub
* 描述 :灯亮度减
**********************************************************************************/
void led_pwm_sub(void)
{
if(key_even_flag == 2)
{
led_pwm.dutycycle--;
if(led_pwm.dutycycle <= 0) led_pwm.dutycycle = 0;
LL_TIM_OC_SetCompareCH3(TIM3, (LL_TIM_GetAutoReload(TIM3) * aDutyCycle[led_pwm.dutycycle]));
key_even_flag = 0;
}
}
/*********************************************************************************
* 函数名 :led_pwm_poll
* 描述 :灯轮询
**********************************************************************************/
void led_pwm_poll(void)
{
key_poll(); // 按键轮询
led_pwm_add();
led_pwm_sub();
}
其中这个LL_TIM_OC_SetCompareCH3(TIM3, (LL_TIM_GetAutoReload(TIM3) * aDutyCycle[led_pwm.dutycycle]));这个函数是在#include "stm32f1xx_ll_tim.h"中找到了,需要把对应的头文件包含进来。
是哪个定时器就修改对应的定时器,这个函数其实是设置定时器的CCR比较值的。比如你的板子对应的硬件定时器是TIM1的通道4,就要设置成LL_TIM_OC_SetCompareCH4(TIM1, (LL_TIM_GetAutoReload(TIM1) * aDutyCycle[iDutyCycle])); 使用时需要根据对应的硬件进行适配。
led_pwm.h的内容如下:
#ifndef __LED_PWM_H__
#define __LED_PWM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "key.h"
#define TIM_DUTYCYCLE_NB 11
typedef struct LED{
int8_t dutycycle; // 占空比档位
}LED;
extern LED led_pwm;
void led_pwm_init(void);
void led_pwm_add(void);
void led_pwm_sub(void);
void led_pwm_poll(void);
#ifdef __cplusplus
}
#endif
#endif /* __SIGHTING_H__ */
在main函数中简单进行测试一下
/* USER CODE BEGIN 2 */
led_pwm_init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
led_pwm_poll();
}
main.c中的编写的代码片段
接下来简单的对工程配置一下
实验现象
可以观察到,当我按下板子的KEY1时,灯的亮度在增加,每次增加10%的亮度,当我按下板子的KEY2时,灯的亮度在减小,每次减少10%,表明此次实验成功,使用简单直观的代码可以实现我们的小需求。
本文中使用的测试工程
https://download.csdn.net/download/weixin_44317448/88222802