1)设置自动重装载数值
2)设置捕获比较数值
3)设置pwm输出模式及对齐方式
4)配置信号输出极性并使能输出
5)使能计数器打开总开关
1)占空比
2)配置模式
1、pwm实现调速的原理与介绍
2、pwm信号配置流程
3、pwm调速代码
4、为什么pwm可以调速
PWM(Pulse Width Modulation)脉冲宽度调制。
pwm占空比就是一个脉冲周期内有效电平在整个周期所占的比例。
通过调节PWM的占空比就能调节IO口上电压的持续性变化,因此也能够控制外设的功率进行持续性变化,也就能控制直流电机的转速快慢。
那么重点就在于如何调节PWM波形的输出。如下图所示
PWM模式、有效电平
前面我们假设ARR大于CCRx时输出为高电平,ARR小于CCRx时输出为低电平,但在实际运用中可能并非如此,有可能是相反的情况——ARR大于CCRx时输出为低电平,ARR小于CCRx时输出为高电平,至于到底是哪种情况,还要看PWM是哪种模式、有效电平又设置的是何种极性了。
模式1:ARR小于CCRx时输出为“有效”电平,ARR大于CCRx时输出为“无效”电平。
模式2:ARR小于CCRx时输出为“无效”电平,ARR大于CCRx时输出为“有效”电平。
注意,我这里用的是“有效”和“无效”,而不是“高”和“低”,也就是说有效电平可高可低,并非一定就是高电平。PWM模式、效电平极性,需要程序员自己配置相关的寄存器来实现。
● 向上计数配置
当TIM1_CR1寄存器中的DIR位为低的时候执行向上计数。
下面是一个PWM模式1的例子。当TIM1_CNT<TIM1_CCRi时,PWM参考信号OCiREF为高,否则为低。如果TIM1_CCRi中的比较值大于自动重装载值(TIM1_ARR),则OCiREF保持为’1’。如果比较值为0,则OCiREF保持为’0’。下图为TIM1_ARR=8时边沿对齐的PWM波形实例。
需要stm8寄存器参考手册的可以去csdn下载或者评论一下
(此处以stm8配置TIM1为例)
既TIM1_ARR寄存器ARR[15:0]
既TIM1_CCRx寄存器CCRi[15:0]
既TIM1_CCMRx寄存器OCiM[1:0]和TIM1_CR1寄存器CMS[1:0]位
既TIM1_CCERx寄存器CCiP和CCiE
既TIM1_CR1寄存器CEN位和TIM1_BKR寄存器MOE位(TIM3没有MOE位)
(此处以stm8配置TIM3位例子)
/****************************************************************///TIM3输出比较功能初始化函数TIM3_init(),有形参F_PWM_SET,无返回值//Duty_CH1为通道一PD2的占空比//Duty_CH2为通道二PD0的占空比//F_PWM_SET为自动重装载寄存器数值/****************************************************************/void Motor_SpeedSet(unsigned long F_PWM_SET,float Duty_CH1,float Duty_CH2){ //配置自动重装载寄存器 TIM3_ARRH=F_PWM_SET/256;//配置自动重装载寄存器高位“ARRH” TIM3_ARRL=F_PWM_SET%256;//配置自动重装载寄存器低位“ARRL” TIM3_CH1_PWM_SET(F_PWM_SET,Duty_CH1); TIM3_CH2_PWM_SET(F_PWM_SET,Duty_CH2); TIM3_CR1|=0x01;//使能TIM1计数器功能“CEN=1”}//Duty_CH1为占空比//F_SET_CH1为输出比较的数值//TIM3_CH1为PD2void TIM3_CH1_PWM_SET(unsigned long F_PWM_SET,float Duty_CH1){ // F_SET_CH1 = 16000; //TIM1输出比较功能初始化配置 // printf('start\n'); float CompareNum; //变量为比较值,用于配置比较寄存器 CompareNum=Duty_CH1*F_PWM_SET; //利用占空比和预装载数值来反求比较寄存器所需要设定的值 /* //配置自动重装载寄存器 TIM3_ARRH=F_PWM_SET/256; TIM3_ARRL=F_PWM_SET%256; */ //配置比较计数器 TIM3_CCR1H=((u16)(CompareNum))/256;//配置捕获/比较寄存器1高位“CCR1H” TIM3_CCR1L=((u16)(CompareNum))%256;//配置捕获/比较寄存器1低位“CCR1L” //printf('计数器配置完成...\n'); //配置向上计数模式边沿对齐,不用设置,默认向上计数 //TIM1_CR1&=0x8F; //配置为PWM模式1,OC1M[2:0]=110,需要注意这里只是设置了有效电平,但是并没有说有效电平是高电平还是低电平 //PWM模 - 在 计数 式1 向上无效电平;在向下计数时,一旦TIMx_CNT>则为有效电平(OC1REF=1)。 //CC1通道被配置为输出,CC1S[1:0]=00 TIM3_CCMR1=0x60; //配置CC1P=0,OC1信号有效电平为高电平 //也就是比TIM3_CCR小时输出高电平,比TIM3_CCR大时输出低电平 TIM3_CCER1&=0xFD; //配置CC1E=1,OC1信号输出到对应的输出引脚 TIM3_CCER1|=0x01; //空闲状态时OC1为高电平,不需要设置 //TIM1_OISR|=0x01; //TIM3_CR1|=0x01;//使能TIM1计数器功能“CEN=1”}//Duty_CH1为占空比//F_SET_CH1为输出比较的数值//TIM3_CH1为PD0void TIM3_CH2_PWM_SET(unsigned long F_PWM_SET,float Duty_CH2){ // F_SET_CH1 = 16000; //TIM1输出比较功能初始化配置 // printf('start\n'); float CompareNum; //变量为比较值,用于配置比较寄存器 CompareNum=Duty_CH2*F_PWM_SET; //利用占空比和预装载数值来反求比较寄存器所需要设定的值 /* //配置自动重装载寄存器 TIM3_ARRH=F_PWM_SET/256; TIM3_ARRL=F_PWM_SET%256; */ //配置比较计数器 TIM3_CCR2H=((u16)(CompareNum))/256;//配置捕获/比较寄存器1高位“CCR1H” TIM3_CCR2L=((u16)(CompareNum))%256;//配置捕获/比较寄存器1低位“CCR1L” //配置为PWM模式1,OC1M[2:0]=110,需要注意这里只是设置了有效电平,但是并没有说有效电平是高电平还是低电平 //PWM模 - 在 计数 式1 向上无效电平;在向下计数时,一旦TIMx_CNT>则为有效电平(OC1REF=1)。 //CC1通道被配置为输出,CC1S[1:0]=00 TIM3_CCMR2=0x60; //配置CC2P=0,OC2信号有效电平为高电平 //也就是比TIM3_CCR小时输出高电平,比TIM3_CCR大时输出低电平 TIM3_CCER1&=0xDF; //配置CC2E=1,OC2信号输出到对应的输出引脚 TIM3_CCER1|=0x10; //TIM3_CR1|=0x01;//使能TIM1计数器功能“CEN=1”}//将pwm信号接到l298n的使能端就可以了 printf('现在开始测试PWM信号产生...\n'); case '1': Motor_SpeedSet(20000,0.2,0.2); //一档速 break; case '2': Motor_SpeedSet(20000,0.4,0.4); //二档速 break; Motor_SpeedSet(60000,0.8,0.8); //可以配置不同当的速度,只要你想,100档速的小车都可以 printf('信号已产生...\n');
这里参考一篇文章—“STM32 PWM输出原理和直流电机PWM驱动原理详解及例程”,在最下面的参考链接可以查看,这位博主写得非常好,这里我提取一些关键原理。
那么这个时候思考一下,有两个灯,供电电压相同,在一段固定的时间内,A灯在不停地闪烁,频率及其之快以至于人眼无法分别,其中有50%的时间亮着,50%熄灭,B灯一直亮着。那么这样观察上去就会明显地感觉到A灯比B灯暗很多。那么这就是一种控制小灯亮度的办法了。
当然你也可以理解为在相同的功率下,AB两个灯都是在做把电能转化为光能的工作,在一天里A灯断断续续地工作了12小时,B灯连续不停工作了24小时。那么谁转化的光能更多就显而易见了,谁更亮也就不言而喻了
在上图中AB两个灯的供电端电压可以看成下图这样
大概截取就带这里,如果想看全部的介绍,可以点击一下文章底部的参考链接。
联系客服