基于STC单片机实现多位软件PWM
2013-04-29蔡锦韩
蔡锦韩
摘 要:本文针对当前带有硬件PWM的8位单片机普遍存在分辨率低,难以适应实际使用需要的问题,利用STC12 C5A60S2系列单片机的PCA模块实现多位(9~16位)软件PWM的基本方法,并给出实用控制程序。实验表明,该方法具有很强的实用性。
关键词:STC单片机 PCA模块 软件PWM
PWM全称为Pulse Width Modulation,即脉冲宽度调制,简称为脉宽调制。常见的PWM调制方式是定频调宽,在固定的调制周期内,通过改变有效电平的宽度,即改变占空比(0≤ρ≤1),实现对输出电压的控制。随着单片机技术的飞速发展,当前主流的单片机普遍在片上集成了硬件PWM等功能,使用起来非常方便。但对8位机而言,片内集成的硬件PWM大多为8位分辨率,虽然可以由硬件实现占空比的无缝刷新,但存在分辨率较低的现实问题。笔者利用深圳宏晶科技有限公司出品的51内核STC12C5A60S2系列单片机设计一种软件PWM,可实现从9~16位之间任意分辨率,从而满足控制精度等要求。
一、STC12C5A60S2系列单片机PCA模块介绍
STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机。内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换、双串口。它在工业电动机控制中,有不俗的表现。STC12C5A60S2系列单片机集成了两路可编程计数器阵列(PCA)模块,可用于软件定时器、外部脉冲捕捉、高速输出以及PWM输出四种工作模式。
1.PCA模块的结构
PCA含有一个特殊的16位定时器,有2个16位的捕获/比较模块与之相连,如图1所示。
图1 PCA模块结构
每个模块可编程工作在4种工作模式:上升/下降沿捕获、软件定时器、高速输出或PWM输出。16位PCA定时器/计数器是2个模块的公共时间基准,其结构如图2所示。
图2 PCA定时/计数器结构
寄存器CH和CL的内容是正在自由递增计数的16位PCA定时器的值,可通过对CMOD(CMOD寄存器的说明参考下面描述)特殊功能寄存器中CPS2、CPS1和CPS0三个位的编程实现对时钟源的选择,具体配置关系如表1所示。
表1
2.PCA模块相关寄存器
PCA模块相关寄存器及其功能受篇幅限制,在此仅介绍几个关键寄存器,其他部分从略。
(1)CCON-PCA控制寄存器。
CF:PCA计数器阵列溢出标志位。为1表示溢出;为0表示未溢出。可软硬件置位,只能软件复位。
CR:PCA计数器阵列运行控制位。置1,启动;置0,停止。
CCF1:PCA模块1中断标志。当出现匹配或捕获时硬件置位;必须软件清零。
CCF0:PCA模块0中断标志。当出现匹配或捕获时硬件置位;必须软件清零。
(2)CMOD—PCA模式寄存器。
CIDL:空闲模式下是否停止PCA计数的控制位。为1时,停止计数;为0时,继续工作。
CPS2、CPS1、CPS0:PCA计数脉冲源选择控制位。具体配置见上文。
ECF:PCA计数溢出中断使能位。为1时允许CF中断;为0时禁止CF中断。
(3)CCAPMn(n=0,1)——PCA模块工作模式寄存器,配置如表2所示。
表2 PCA模块工作模式设定(CCAPMn,n=0,1)
- ECOMn CAPPn CAPNn MATn TOGn PWMn ECCFn 模块功能
0 0 0 0 0 0 0 无此操作
0 0 0 0 0 1 0 8位PWM,无中断
1 1 0 0 0 1 1 8位PWM输出,由低变高可产生中断
1 0 1 0 0 1 1 8位PWM输出,由高变低可产生中断
1 1 1 0 0 1 1 8位PWM输出,由低变高或者由高变低增可产生中断
X 1 0 0 0 0 X 16位捕获模式,由CEXn/PCAn的上升沿触发
X 0 1 0 0 0 X 16位捕获模式,由CEXn/PCAn的下降沿触发
X 1 1 0 0 0 X 16位捕获模式,由CEXn/PCAn的跳变触发
1 0 0 1 0 0 X 16位软件定时器
1 0 0 1 1 0 X 16位高速输出
可见,通过配置,PCA能工作在多种工作模式,具有较强的灵活性。
二、软件实现PWM基本原理
本设计应用PCA模块的高速输出模式实现多位PWM功能。当PCA计数器的计数值与模块捕获寄存器的值相匹配时,PCA模块的CCPn引脚输出将发生翻转。PCA模块高速输出模式框图,如图4所示。
图4 PCA高速输出模式
由图4可见,当激活高速输出模式时,CCAPMn寄存器的TOGn,MATn和ECOMn位都必须置位。一旦出现匹配,在比较匹配中断里判断高速输出的电平,如果是高电平,则向捕获寄存器装入高电平的PCA时钟数;如果是低电平,则装入低电平的PCA时钟数。
设要求的PWM分辨率为n(0≤n≤1),则每个PWM周期为DUTY=2n个PCA时钟。设PWM_high为PWM高电平持续时间,PWM_low为PWM低电平持续时间,则有DUTY=PWM_high+PWM_low,占空比。明显的,分辨率n的值越大,则分辨率越高。
为实现设计功能,需要用到的资源有:PCA可编程计数器阵列、捕获寄存器、匹配中断向量。由于中断处理需要一点时间,输出的占空比不能到0%或100%,所以对占空比有最小和最大值限制,中断处理绝对时间大约为100个系统时钟。
三、参考程序
/* --- STC单片机实现软件PWM功能,本程序以10位PWM为例-----------------*/
#include"STC12C5A60S2.h"/*包含STC12C5A60S2单片机头文件*/
#define PWM_DUTY 1024 ∥定义PWM的周期,数值为PCA所选择的时钟脉冲个数。
#define PWM_HIGH_MAX PWM_DUTY-32 ∥限制PWM输出的最大占空比。
#define PWM_HIGH_MIN 32 ∥限制PWM输出的最小占空比。
sbit CCP0 = P1^3; ∥CCAP0引脚声明
/* -------------- 全局变量定义---------------*/
unsigned int PWM_high; ∥ 定义PWM占空比寄存器,即PWM输出高电平的PCA时钟脉冲个数。
unsigned int PWM_low; ∥ 定义PWM输出低电平的PCA时钟脉冲个数。
unsigned int CCAP0_tmp;//定义CCAP0重装载影射寄存器。
∥=============================================
∥ 函数: void PWM_SetHigh(unsigned int high)
∥ 描述: 写入占空比数据。
∥ 参数: high: 占空比数据,即PWM输出高电平的PCA时钟脉冲个数。
∥=================================================
void PWMn_SetHigh(unsigned int high)
{
if(high > PWM_MAX)
high = PWM_MAX; ∥如果写入大于最大占空比数据,强制为最大占空比。
if(high < PWM_MIN)
high = PWM_MIN; ∥如果写入小于最小占空比数据,强制为最小占空比。
CR = 0; ∥停止PCA。
PWM_high = high; ∥数据在正确范围,则装入占空比寄存器。
PWM_low = PWM_DUTY - high; ∥计算并保存PWM输出低电平的PCA时钟脉冲个数。
CR = 1; ∥启动PCA。
}
∥============================================
∥ 主函数: void main(void)
∥=============================================
void main(void)
{
P1M1 &= ~0x08,
P1M0 |= 0x08; /*设置CCAP0(P1.3)使用PUSH-PULL推挽输出模式。*/
CCON = 0; /*清除CF、CR、CCF0、CCF1*/
IPH |= 0x80; /*PCA中断使用最高优先级*/
IP |= 0x80;
CMOD = 0; /*空闲模式下PCA计数器继续工作,计数器时钟源为系统时钟的12分频,禁止PCA计数溢出(CF)中断*/
CCAPM0 = 0x4d; /*高速输出模式,允许比较匹配中断(ECCF0=1)。*/
CL = 0; /*清空PCA基本计数器。*/
CH = 0;
CCAP0_tmp = 0; /*清空CCAP0重装载影射寄存器。*/
PWMn_SetHigh(512);/*设定占空比数据。*/
CR = 1; /*启动PCA。*/
EA = 1; /*允许总中断*/
while(1);
}
∥=================================================
∥ 函数: void PCA_interrupt (void) interrupt 7
∥ 描述: PCA中断服务程序。
∥ 参数: 无。
∥ 返回: 无。
∥=================================================
void PCA_ISR (void) interrupt 7
{
if(CCF0) /*PCA模块0中断(只开放CCF0中断)*/
{
CCF0 = 0; /*清PCA模块0中断标志*/
if(CCP0)
CCAP0_tmp += PWM_high; /*输出为高电平,则给影射寄存器装载高电平时间长度*/
else
CCAP0_tmp += PWM_low; /*输出为低电平,则给影射寄存器装载低电平时间长度*/
CCAP0L = (unsigned char)CCAP0_tmp;/*将影射寄存器写入捕获寄存器,先写CCAP0L*/
CCAP0H = (unsigned char)(CCAP0_tmp >> 8);/*注意:后写CCAP0H*/
}
}
四、实验验证
某设计项目使用10位软件PWM功能,实验结果如图5、图6、图7所示。
图5 15%占空比
图6 50%占空比
图7 80%占空比
五、结语
本设计在多个实际项目使用,均能很好地实现控制要求,同时大大降低硬件成本。在实际应用中,考虑到中断的消耗,特别是其他中断服务开销很长时间时,有可能会影响本程序的正常运行,因此强烈建议将PCA模块中断优先级设为最高级,以实现更佳控制效果;同时建议在正常运行时,尽量不要关闭。
(作者单位:广东省粤东高级技工学校)