普通型51单片机一般不集成PWM硬件发生器,要想完结PWM输出有必要选用软件模仿的方法。依据详细运用的不同,PWM波形频率也凹凸纷歧;就直流电机操控而言,PWM波的频率一般主张在10kHz~40kHz,20kHz为典型值,输出频率过低,则输出电流不行陡峭,电机运转不平稳。
软模PWM输出一般有两种方法:运用定时器0操控PWM频率输出,结合定时器1操控占空比,这是其一;第二种方法,仅运用一个定时器,作业于16bit手艺装载形式,一起操控输出频率和占空比,这种方法不占用太多资源,并且完结起来也不失其灵活性,俺自己就主张选用这样方法,主张除掉第一种方法。本文的研讨也是根据方法二打开的。
网络上常见MCS-51软模输出PWM波的文章,而至于对这种方法完结的可行性或者说局限性,却无一例外的被小觑了。本文就51单片机模仿PWM波输出的劣根性进行了讨论,不正之处,欢迎咱们提点。
1、发生PWM波的子模块例程(PWM.C):
#include “Includes.h” //文件包括
/*******************************************************************************
*** 函 数 名: extern void PWM_Init(void)
*** 功用描绘: PWM参数初始化;
*** 全局变量: NO !
*** 输 入: NO !
*** 输 出: NO !
*** 创 建 人:huangtiexiong 日期:2006-11-28
*** 修 改 人: 日期:2006-11-28
*** 函数阐明: 外部函数;
/******************************************************************************/
extern void PWM_Init(void)
{
TMOD &= 0x0f; TMOD |= 0x10; //定时器1方法1,16位手动装载形式;
TH1 = (65536 – PWM_HIGH) / 256 ;
TL1 = (65536 – PWM_HIGH) % 256 ;
PWM_PIN = 1; //初始化先输出高电平;
ET1 = 1; //开定时器1中止;
EA = 1; TR1 = 1; //发动定时器1;
}
/*******************************************************************************
*** 函 数 名: extern void Timer1_ISR(void) interrupt 3
*** 功用描绘: 定时器1中止服务例程;
*** 全局变量: NO !
*** 输 入: NO !
*** 输 出: NO !
*** 创 建 人:huangtiexiong 日期:2006-11-28
*** 修 改 人: 日期:2006-11-28
*** 函数阐明: 中止服务函数;
PWM_LOW: 低电平持续时刻us;
PWM_HIGH: 高电平持续时刻us;
PWM_PIN: PWM波输出引脚,接P1.7;
/******************************************************************************/
extern void Timer1_ISR(void) interrupt 3
{
if(PWM_PIN) {PWM_PIN = 0;
TH1 = (65536 – PWM_LOW) / 256 ;
TL1 = (65536 – PWM_LOW) % 256 ; }
else {PWM_PIN = 1;
TH1 = (65536 – PWM_HIGH) / 256 ;
TL1 = (65536 – PWM_HIGH) % 256 ; }
}
/*******************************************************************************
**** End Of File
*******************************************************************************/
其中止服务例程在Keil C中编译后的汇编代码如下(默许8级代码优化):
; FUNCTION Timer1_ISR (BEGIN)
; SOURCE LINE # 43
; SOURCE LINE # 45
0000 309709 JNB PWM_PIN,?C0002
; SOURCE LINE # 46
; SOURCE LINE # 47
0003 C297 CLR PWM_PIN
; SOURCE LINE # 48
0005 758DFF MOV TH1,#0FFH
; SOURCE LINE # 49
0008 758BB5 MOV TL1,#0B5H
; SOURCE LINE # 50
000B 32 RETI
000C ?C0002:
; SOURCE LINE # 52
; SOURCE LINE # 53
000C D297 SETB PWM_PIN
; SOURCE LINE # 54
000E 758DFF MOV TH1,#0FFH
; SOURCE LINE # 55
0011 758BE7 MOV TL1,#0E7H
; SOURCE LINE # 56
; SOURCE LINE # 57
0014 ?C0004:
0014 32 RETI
; FUNCTION Timer1_ISR (END)
2、主进口模块(BootLoader.c):在主模块main函数中,首要清零PWM_PIN引脚,接着调用PWM_Init()例程,然后便是一个简略的空循环,其经由Keil C编译后的汇编代码为:
; FUNCTION main (BEGIN)
0000 C297 CLR PWM_PIN
; SOURCE LINE # 31
0002 120000 E LCALL PWM_Init
0005 ?C0001:
; SOURCE LINE # 32
0005 80FE SJMP ?C0001
; FUNCTION main (END)
3、别的还有两个重要的参数宏,界说在在PWM模块的头文件PWM.H中:
#define PWM_CYCLE 100 //100us,则PWM波的频率为10kHz;
#define PWM_HIGH 25 //高电平持续时刻,占空比1/4;
#define PWM_LOW 75 //低电平持续时刻;
4、首要取PWM_CYCLE, PWM_HIGH, PWM_LOW分别为100、25、75,则设定的PWM波频率为10kHz,占空比0.25。编译衔接正确后在Proteus中仿真(单片机晶振频率设置为12.0mHz),抓出一个周期的波形图如下:
可计算:高电平持续时刻为810us-773us=37us,低电平持续时刻897us-810us=87us,实践输出PWM波的占空比为:37/(37+87)=0.298387,占空比差错率为(0.298387-0.25)/0.25=19.35%;一般工程实践要求的差错率不超越5%,明显这19.35%的差错率是不符合要求的。(注-Proteus的图形仿真精度:对模仿量的采样最小距离为1e-18s,典型值为1e-09,拜见Proteus运用手册。)
5、接着取PWM_CYCLE, PWM_HIGH, PWM_LOW分别为10、2、8,则设定的PWM波频率为100kHz,占空比0.2。编译衔接正确后在Proteus中仿真(12.0mHz晶振)后抓出的单个周期波形图如下:
由图可计算得:实践输出的PWM_HIGH, PWM_LOW分别为15、19,占空比0.4412,占空比差错率120.59%,也便是说,实践输出的PWM波占空比翻番了。
6、持续取PWM_CYCLE, PWM_HIGH, PWM_LOW分别为1000、250、750,则设定的PWM波频率为1kHz,占空比0.25。编译衔接正确后在Proteus中仿真(12.0mHz晶振)后抓出的单个周期波形图如下:
由图可计算:实践输出的PWM_HIGH, PWM_LOW分别为262、762,占空比0.2558,占空比差错率2.34%(<5%)。
7、综上,本文得出的定论为:在51单片机上选用软件模仿的方法输出PWM波,其频率越大,占空比差错越不可收拾;在PWM波形频率不是很高的状况下(比方小于1kHz),选用软模方法输出PWM是彻底可行的。
8、为什么会呈现这种状况呢 ?首要将每次仿真调试,程序中设定的PWM_HIGH, PWM_LOW值及实践输出值列表如下:
比较发现实践输出的PWM波形时刻参数总比咱们当然中预期的多约12个us,也便是本仿真单片机的12个机器周期。再次检查中止服务函数的汇编代码:
; FUNCTION Timer1_ISR (BEGIN)
; SOURCE LINE # 43
; SOURCE LINE # 45
0000 309709 JNB PWM_PIN,?C0002 ;;;2us
; SOURCE LINE # 46
; SOURCE LINE # 47
0003 C297 CLR PWM_PIN ;;;1us
; SOURCE LINE # 48
0005 758DFF MOV TH1,#0FFH;;;2us
; SOURCE LINE # 49
0008 758BB5 MOV TL1,#0B5H ;;;2us
; SOURCE LINE # 50
000B 32 RETI ;;;2us
000C ?C0002:
; SOURCE LINE # 52
; SOURCE LINE # 53
000C D297 SETB PWM_PIN;;1us
; SOURCE LINE # 54
000E 758DFF MOV TH1,#0FFH ;;2us
; SOURCE LINE # 55
0011 758BE7 MOV TL1,#0E7H;;2us
; SOURCE LINE # 56
; SOURCE LINE # 57
0014 ?C0004:
0014 32 RETI ;;2us
; FUNCTION Timer1_ISR (END)
这次把每条指令的履行时刻注释了在后,考虑指令流进入了定时器中止,履行CLR PWM_PIN指令完结,则经4us的PWM_HIGH计时参数装载,2us的中止回来操作,运转main流程中的SJMP ?C0001空转指令至定时器再次溢出中止(Xus,X为程序设定PWM_HIGH取值),CPU中止呼应再次转入中止服务例程(可计算中止呼应时刻为3~4us),履行JNB PWM_PIN,?C0002SETB PWM_PIN
9、到这儿,单片机软模PWM波在高频输出下占空比差错率变得不可收拾的原因总算毕露原形。实践输出占空比计算式为:(PWM_HIGH+12)/(PWM_HIGH+PWM_LOW+24)。