目录
我们打开原理图找到LED,LED0的引脚为PB5,在数据手册查找找到PB5可以看到是重映射为TIM3_CH2,所以我们可以把PB5端口重映射为TIM3_CH2,通过配置TIM3通用定时器实现PWM模式进而实现呼吸灯。
一、配置TIM和PWM
打开board.h可以找到有关配置TIM和PWM驱动的说明
第一步,打开RT-Thread Settings使能HWTIMER和PWM设备驱动程序
第二步,在board.h找到TIM的宏定义,取消注释,并添加TIM3的宏定义,找到TIM3的宏定义,取消注释。并添加PWM3的宏定义
第三步,在cubemx进行引脚配置,在生成的文件中的stm32f1xx_hal_msp.c,找到这两个函数HAL_TIM_PWM_MspInit.,HAL_TIM_MspPostInit,复制粘贴在board.c,在main.c中找到 MX_TIM3_Init(void)复制粘贴在board.c,并定义一个全局变量TIM_HandleTypeDef htim3;这里是没有开启复用时钟的,我们手动添加一下,将__HAL_RCC_AFIO_CLK_ENABLE()添加在HAL_TIM_MspPostInit函数中__HAL_AFIO_REMAP_TIM3_PARTIAL()的下面
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
{
if(htim_pwm->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspPostInit 0 */
/* USER CODE END TIM3_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM3 GPIO Configuration
PB5 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_AFIO_REMAP_TIM3_PARTIAL();
__HAL_RCC_AFIO_CLK_ENABLE();
/* USER CODE BEGIN TIM3_MspPostInit 1 */
/* USER CODE END TIM3_MspPostInit 1 */
}
}
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 2000-1;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 7200-1;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
第四步,在rt-thread studio工程中找到stm32f1xx_hal_conf.h,取HAL_TIM_MODULE_ENABLED的注释
二、实现呼吸灯
以上配置完成后,就可以实现呼吸灯了,我们把官方例程修改一下,编译烧录,可以看到先慢慢亮后慢慢灭
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#define PWM_DEV_NAME "pwm3" /* PWM设备名称 */
#define PWM_DEV_CHANNEL 2 /* PWM通道 */
struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */
int main(void)
{
rt_uint32_t period, pulse, dir;
period = 500000; /* 周期为0.5ms,单位为纳秒ns */
dir = 1; /* PWM脉冲宽度值的增减方向 */
pulse = 0; /* PWM脉冲宽度值,单位为纳秒ns */
MX_TIM3_Init();
/* 查找设备 */
pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
if (pwm_dev == RT_NULL)
{
rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME);
return RT_ERROR;
}
/* 设置PWM周期和脉冲宽度默认值 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
/* 使能设备 */
rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);
while (1)
{
rt_thread_mdelay(50);
if (dir)
{
pulse += 5000; /* 从0值开始每次增加5000ns */
}
else
{
pulse -= 5000; /* 从最大值开始每次减少5000ns */
}
if (pulse >= period)
{
dir = 0;
}
if (0 == pulse)
{
dir = 1;
}
/* 设置PWM周期和脉冲宽度 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
}
}