微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 51单片机软模PWM误差率之研究

51单片机软模PWM误差率之研究

时间:11-18 来源:互联网 点击:
普通型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),抓出一个周期的波形图如下:

可计算:高电平持续

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top