一、什么是PWM?
PWM(脉冲宽度调制)是一种用于控制电子设备的技术。它通过调整信号的脉冲宽度来控制电压的平均值。PWM常用于调节电机速度、控制LED亮度、产生模拟信号等应用。
二、PWM的原理
PWM的基本原理是通过以一定频率产生的脉冲信号,通过调整脉冲的宽度(占空比)来模拟电压的不同电平。占空比是指脉冲高电平的时间占整个周期的比例。通过调整占空比,可以在输出端产生不同的电平,从而实现对电机、LED等设备的精确控制。
例如,对于一个50%占空比的PWM信号,脉冲的高电平时间占整个周期的一半,这将导致输出电平的平均值为一半的电压。通过调整占空比,你可以在0%到100%的范围内控制输出电平的变化。
三、PWM模式以及输出PWM原理
ARR: 自动重装载寄存器的值。
CCRx: 捕获/比较寄存器的值。
PWM波周期或频率由ARR决定,PWM波占空比由CCRx决定
(1)PWM模式1
在向上计数时,一旦CNT<CCRx 时输出为有效电平,否则为无效电平。
在向下计数时,一旦CNT>CCRx 时输出为无效电平,否则为有效电平。
如:
当CNT < CCRx,IO输出1。
当CNT >= CCRx,IO输出0。
当CNT <=CCRx,IO输出1。
当CNT > CCRx,IO输出0。
(2)PWM模式2
在向上计数时,一旦CNT>CCRx 时输出为有效电平,否则为无效电平。
在向下计数时,一旦CNT<CCRx 时输出为无效电平,否则为有效电平。
如:
当CNT < CCRx,IO输出0。
当CNT >= CCRx,IO输出1。
当CNT <= CCRx,IO输出0。
当CNT > CCRx,IO输出1。
四、PWM极性设置
当极性为高 (TIM_OCPolarity_High) 时,不进行反相。即按pwm模式正常的去进行比较与输出。
当极性为低 (TIM_OCPolarity_Low) 时,输出通道在比较匹配时为低电平,相当于对输出信号进行反相。
如:pwm模式1向上计数。
设置高极性:当CNT < CCRx,IO输出1。 当CNT >= CCRx,IO输出0。
设置低极性:当CNT < CCRx,IO输出0。 当CNT >= CCRx,IO输出1。
五、配置PWM输出实验步骤
实验内容:将PC6复用为TIM3通道1,用于输出pwm。注:stm32的pwm输出引脚是使用的IO口的复用功能。
(1)具体代码1–寄存器:
void PWM_Init_TIM3_CH1(u16 ccr)
{
//1.初始化PC6引脚
RCC->AHB1ENR |=(0x01 <<2); //开启GPIOC的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启AFIO时钟
AFIO->MAPR |=(0x03 <<10); //定时器3 完全重映射
GPIOC->CRL &= 0XF0FFFFFF;//PC6清0
GPIOA->CRL |= 0X0B000000;//复用功能输出(推挽50MHz输出)
//2.初始化基本定时器配置
RCC->APB1ENR |= 1 << 1; //使能TIM3时钟
TIM3->SMCR &=~(0x07 << 0); //选择内部时钟源
TIM3->CR1 &=~(0x03<<5); //边沿对齐
TIM3->CR1 &=~(0X01<<4); //设置为向上计数模式
TIM3->CR1 |=(0x01 <<7); //有影子,缓冲。
TIM3->ARR = 99;//设定计数器主动重装值(决定PWM的频率)
TIM3->PSC = 7199;//预分频器 0为不分频
//3.初始化输出通道
TIM3->CCR1 =ccr; //写入比较值
TIM3->CCMR1 &=~(0x03 << 0) ; //通道配置为输出功能
TIM3->CCMR1 |=(0x01 << 3); //有影子
TIM3->CCMR1 &=~(0x01 <<7); //OC1Ref不受ETRF输入影响。
TIM3->CCMR1 &= ~(0x07 <<4);
TIM3->CCMR1 |=(0x06 <<4); //PWM模式1
TIM3->CCER &=~(0x01 <<1); //实际波形=参考波形。 不反相
TIM3->CCER |= (0x01 << 0);//输入/捕获1输出使能
TIM3->EGR |=(0x01 <<0); //产生更新事件,将上面配置更新到影子寄存器
TIM3->CR1 |= (0X01 << 0);//使能定时器3
}
主函数:
int main()
{
//pwm范围为0-ARR。 高低电平随着pwm模式不同而不同。
//如比较值为90,pwm模式1向上计数,低于比较值90时,为高电平。
PWM_Init_TIM3_CH1(90);
while(1)
{
}
}
(2)具体代码2–库函数
void TIM3_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef qjl;//初始化定时器
TIM_OCInitTypeDef TIM_OCInitsture;//设置定时器的pwm模式
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);
qjl.TIM_Period = arr; //设置自动重装载寄存器周期的值 ARR
qjl.TIM_Prescaler =psc; //设置时钟频率除数的预分频值
qjl.TIM_ClockDivision =TIM_CKD_DIV1;
qjl.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM3,&qjl);
TIM_OCInitsture.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitsture.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitsture.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM3,&TIM_OCInitsture);
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_OC2Init(TIM3,&TIM_OCInitsture);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_Cmd(TIM3,ENABLE);
}
主函数:
u16 dir=1;
u16 ledpwm=100;
int main(void)
{
led_int();
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设 置 NVIC 中 断 分 组 2
TIM3_PWM_Init(899,0);
uart1_init(115200);
while(1)
{
delay_ms(2);
if(dir)
{
ledpwm++;
}
else
{
ledpwm--;
}
if(ledpwm>900)
dir=0;
if(ledpwm==0)
dir=1;
TIM_SetCompare1(TIM3,ledpwm);
}
}