APP下载

基于STC单片机实现多位软件PWM

2013-04-29蔡锦韩

职业·下旬 2013年8期

蔡锦韩

摘 要:本文针对当前带有硬件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模块中断优先级设为最高级,以实现更佳控制效果;同时建议在正常运行时,尽量不要关闭。

(作者单位:广东省粤东高级技工学校)