PWM模式:
PWM模式1:
递增:CNT < CCRx,输出有效电平
CNT >= CCRx,输出无效电平
递减:CNT > CCRx,输出无效电平
CNT <= CCRx,输出有效电平
PWM模式2:
递增:CNT < CCRx,输出无效电平
CNT >= CCRx,输出有效电平
递减:CNT > CCRx,输出有效电平
CNT <= CCRx,输出无效电平
有/无效状态由TIMx_CCER决定
CCxP=0:OCx高电平有效
CCxP=1:Ocx低电平有效
实验要求:
通过定时器输出的PWM控制LED0,实现类似手机呼吸灯的效果。
1,确定PWM波的周期/频率 Tout =((ARR+1)∗(PSC+1))/Ft
2KHZ为例,psc=71,ARR=499。
2,配置输出比较模式为:PWM模式1,通道输出极性为:低电平有效
通用定时器PWM输出实验配置步骤:
1,配置定时器基础工作参数 HAL_TIM_PWM_Init()
2,定时器PWM输出MSP初始化 HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
3,配置PWM模式/比较值等 HAL_TIM_PWM_ConfigChannel()
4,使能输出并启动计数器 HAL_TIM_PWM_Start()
5,修改比较值控制占空比(可选) __HAL_TIM_SET_COMPARE()
6,使能通道预装载(可选) __HAL_TIM_ENABLE_OCxPRELOAD()
函数结构体介绍:
HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
TIM_OC_InitTypeDef *sConfig,
uint32_t Channel) 参数二结构体介绍
typedef struct
{
uint32_t OCMode; /* 输出比较模式选择 */
uint32_t Pulse; /* 设置比较值 */
uint32_t OCPolarity; /* 设置输出比较极性 */
uint32_t OCNPolarity; /* 设置互补输出比较极性 */
uint32_t OCFastMode; /* 使能或失能输出比较快速模式 */
uint32_t OCIdleState; /* 空闲状态下OC1输出 */
uint32_t OCNIdleState; /* 空闲状态下OC1N输出 */
} TIM_OC_InitTypeDef;
在本次实验中只用到前三个结构体。
源码
gtim.c
#include "./BSP/TIMER/gtim.h"
#include "./BSP/LED/led.h"
TIM_HandleTypeDef g_timx_pwm_chy_handle;
//通用定时器pwm输出初始化函数
void gtim_timx_pwm_chy_init(uint16_t psc,uint16_t arr)
{
TIM_OC_InitTypeDef timx_oc_pwm_chy;
g_timx_pwm_chy_handle.Instance = TIM3;
g_timx_pwm_chy_handle.Init.Prescaler = psc;
g_timx_pwm_chy_handle.Init.Period = arr;
g_timx_pwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_PWM_Init(&g_timx_pwm_chy_handle);
timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1;
timx_oc_pwm_chy.Pulse = arr / 2; //这样设计得到占空比为50%
timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_LOW;
HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_chy_handle, &timx_oc_pwm_chy, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&g_timx_pwm_chy_handle, TIM_CHANNEL_2);
}
//定时器输出pwm msp初始化函数
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_TIM3_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_5;
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽式复用 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIOB, &gpio_init_struct); /* 初始化引脚 */
__HAL_RCC_AFIO_CLK_ENABLE(); //使用重映射功能要打开AFIO时钟
__HAL_AFIO_REMAP_TIM3_PARTIAL(); //使用重映射功能要打开对应的重映射宏
}
}
gtim.h
#ifndef __TIMER_H
#define __TIMER_H
#include "./SYSTEM/sys/sys.h"
void gtim_timx_pwm_chy_init(uint16_t psc,uint16_t arr);
#endif
main.c
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/gtim.h"
extern TIM_HandleTypeDef g_timx_pwm_chy_handle; //定时器x句柄
//因为修改比较值控制占空比用到g_timx_pwm_chy_handle所以要声明一下
int main(void)
{
uint16_t ledrpwmval = 0;
uint8_t dir = 1;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟,72M */
delay_init(72); /* 初始化延时函数 */
led_init(); /* 初始化LED */
gtim_timx_pwm_chy_init(500 - 1, 72 - 1);
while(1)
{
delay_ms(10);
if (dir)ledrpwmval++; /* dir==1 ledrpwmval递增 */
else ledrpwmval--; /* dir==0 ledrpwmval递减 */
if (ledrpwmval > 300)dir = 0; /* ledrpwmval到达300后,方向为递减 */
if (ledrpwmval == 0)dir = 1; /* ledrpwmval递减到0后,方向改为递增 */
/* 修改比较值控制占空比 */
__HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, TIM_CHANNEL_2, ledrpwmval);
}
}