1、PWM原理(Pulse Width Modulation)
TIM1&TIM8高级定时器可以输出7路PWM
ARR:自动重装载值;CCRX:比较寄存器的设定值
原理:通过定时器不断技计数,是CNT增加,当CNT<CCRX时,通道输出低电平;当CNT>CCRX时,输出高电平;当CNT=ARR时,计数器清零循环计数。
ARR决定了PWM 的周期,CCRX决定了PWM的占空比。其中X为PWM的通道。
2、PWM模式的区别(寄存器CCMR决定PWM模式)
PWM1:不管是向上计数还是向下计数,只要CNT<CCRX,则输出有效电平;当CNT>CCRX输出无效电平
PWM2:与PWM1正好相反
3、PWM极性(CCER:0,高电平有效;1,低电平有效)
以LED灯为例:
设置PWM1模式,CCR1=300,低电平有效,当CNT<CCR1时,输出有效电平低电平,LED低电平时点亮;
设置PWM2模式,CCR1=300,高电平有效,当CNT>CCR1时,输出有效电平高电平,LED高电平时熄灭;
二者的效果相同。
注:低电平时间越长LED 越亮,否则越暗。
附呼吸灯代码
/************************************************
* PWM实验
* 功能:呼吸灯
* TIM1;CH1;
*************************************************/
TIM_HandleTypeDef TIM1_Handler; //定时器1句柄
TIM_OC_InitTypeDef TIM1_CHnHandler; //定时器1 PWM句柄
/*TIM1初始化函数*/
void PWM_Init(u16 arr, u16 psc)
{
TIM1_Handler.Instance = TIM1;
TIM1_Handler.Init.Prescaler = psc;
TIM1_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
TIM1_Handler.Init.Period = arr;
TIM1_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
// TIM1_Handler.Init.RepetitionCounter = 0;
HAL_TIM_PWM_Init(&TIM1_Handler);
TIM1_CHnHandler.OCMode = TIM_OCMODE_PWM2;
TIM1_CHnHandler.Pulse = arr / 2;
/*PWM输出极性*/
TIM1_CHnHandler.OCPolarity = TIM_OCPOLARITY_HIGH;
/*通道1*/
HAL_TIM_PWM_ConfigChannel(&TIM1_Handler, &TIM1_CHnHandler, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&TIM1_Handler, TIM_CHANNEL_1);
/*通道2*/
// HAL_TIM_PWM_ConfigChannel(&TIM1_Handler, &TIM1_CHnHandler, TIM_CHANNEL_2);
// HAL_TIM_PWM_Start(&TIM1_Handler, TIM_CHANNEL_2);
}
/***************************************
* 定时器底层驱动,此函数会被HAL_TIM_PWM_Init()调用
* 时钟使能,引脚配置
****************************************/
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_TIM1_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
GPIO_Initure.Pin = GPIO_PIN_9;
GPIO_Initure.Mode = GPIO_MODE_AF_PP;
GPIO_Initure.Pull = GPIO_PULLUP;
GPIO_Initure.Speed = GPIO_SPEED_HIGH;
GPIO_Initure.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOE, &GPIO_Initure);
}
/*设置占空比*/
void TIM_SetTIM1Compare1(u32 compare)
{
TIM1->CCR1 = compare;
}
主函数
int main(void)
{
u8 dir = 1;
u16 pwmval = 0;//PWM默认值
HAL_Init();
SystemClock_Config(); //初始化系统时钟为80M
delay_init(80); //初始化延时函数 80M系统时钟
uart_init(115200);
PWM_Init(1000 - 1, 80 - 1);
while(1)
{
delay_ms(10);
if(dir) pwmval++;
else pwmval--;
if(pwmval > 300) dir = 0;
if(pwmval==0) dir = 1;
TIM_SetTIM1Compare1(pwmval);
}
}