PWM(Pulse Width Modulation)脉冲宽度调制。
pwm占空比就是一个脉冲周期内有效电平在整个周期所占的比例。
通过调节PWM的占空比就能调节IO口上电压的持续性变化,因此也能够控制外设的功率进行持续性变化,也就能控制直流电机的转速快慢。
那么重点就在于如何调节PWM波形的输出。如下图所示
图中的ARR是我们给定时器的一个预装载值,CCRx的上下变化是产生PWM波的关键。我们假设ARR大于CCRx的部分输出为高电平(即t1-t2、t3-t4、t5-t6),ARR小于CCRx的部分输出为低电平(即0-t1、t2-t3、t4-t5),则改变CCRx的值就能改变输出PWM的占空比。
只要弄明白了上面那幅图,那就不难理解想要控制PWM的输出波形,重要的就是如何设置ARR与CCRx这两个寄存器的值了。(此处如何设置寄存器的值我代码里会注释得非常清楚,可以先看看原理)
前面我们假设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_CR1寄存器的DIR位为高时执行向下计数。
在PWM模式1时,当TIM1_CNT>TIM1_CCRi时参考信号OCiREF为低,否则为高。如果TIM1_CCRi中的比较值大于TIM1_ARR中的自动重装载值,则OCiREF保持为’1’。该模式下不能产生0%的PWM波形。
需要stm8寄存器参考手册的可以去csdn下载或者评论一下
(此处以stm8配置TIM1为例)
既TIM1_CCMRx寄存器OCiM[1:0]和TIM1_CR1寄存器CMS[1:0]位
既TIM1_CR1寄存器CEN位和TIM1_BKR寄存器MOE位(TIM3没有MOE位)
需要stm8寄存器参考手册的可以去csdn下载或者评论一下
(此处以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为PD2
void 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为PD0
void 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两个灯的供电端电压可以看成下图这样
并不是!电机的线圈呢,你懂的哈,像电感类似的结构,它具有电流的不可突变性,这个性质呢也就是像高中老师说的,电感线圈,通直流阻交流,它内部产生的磁场不允许电流的突变,他会将电流产生的磁场用来抑制电流的变化。
所以说用PWM控制电机的话,不讲驱动电路板原理的话,可以简化理解为这样:用芯片生成的PWM去使电机两端的电源图像变得像PWM信号一样。至于他是怎么变得我们下回分解。
意思就是说如果用PWM控制电机,那么电机两端的电压是010101这么突变的,但是电机电流却不是,即使电压为0,因线圈自感电动势的存在,电机中依旧有电流流过,电机依旧继续转动,那么我们使用PWM 为什么可以控制转速呢?
你也许会想到高中物理老师说的一个词语:等效电压。
我们通过PWM去控制等效电压。这样你就能理解了。
你也可以根据能量守恒来想啊,电机转起来过后,线圈电阻恒定不变,功率恒定不变,两端电压峰值也恒定不变,那么这样情况下,电源电压图形上占空比的不同将导电机在这段时间内致消耗能量的不同,以此达到转化的机械能的不同,转速是不是也不同了。这样是不是很好理解了。
大概截取就带这里,如果想看全部的介绍,可以点击一下文章底部的参考链接。
参考链接:
STM32 PWM输出原理和直流电机PWM驱动原理详解及例程