应广单片机
最近因为缺货,很多工程师被迫忙于将原来一个既选型号,扩展为多个型号同时采用。其中PMS152,这颗1.25K程序空间的型号,有用户想采用PMS153来代替,但是PMS153是一颗简单功能的纯IO,除了程序空间只有1K以外,还不具备PWM功能。但是对于一些要求比较低的PWM,是可以用软件来模拟的。
首先我们看硬件PWM的工作原理示意图:
从示意图中我们可以看出,无论是8位还是6位的PWM,都有一个周期值,8位是255,也就是0xFF,;6位是63,也就是十六进制的0x3F。然后还有一个上限寄存器值,这个上限寄存器值控制着PWM输出口的输出。要么在上限寄存器值以下时输出高,要么在上限寄存器以下时输出低(反向输出)。
因此,我们在用软件模拟PWM时,也最好遵循硬件PWM的原理来做。首先我们需要定义一个普通IO输出口RLED_OUT,在定义两个寄存器。PWM周期寄存器pwm_cnt,和PWM上限寄存器pwmr_cnt。
BIT RLED_OUT :PA.7 //out
byte pwmr_cnt;
byte pwm_cnt;
然后,我们可以利用中断来对PWM周期寄存器做计数累计,中断的频率快满决定着PWM的最小分辨率,周期寄存器所计数值大小决定PWM的频率。比如,我们是用40us作为中断周期,PWM的周期寄存器的上限值是250的话,PWM的周期就成了40us*250=10ms, 频率则为100赫兹。用软件模拟PMW,你想得到更快的频率只能降低分辨率。为了让PWM输出比较稳定,也最好在中断中控制PWM的输出。
参考实例:
#include “extern.h”
BIT RLED_OUT : PA.7
.ramadr 0
word t16_cnt;
byte pwm_cnt;
byte pwmr_cnt;
byte systatus;
byte int_cnt;
bit f_10ms :systatus.0
word i_gword;
void FPPA0 (void)
{
.ADJUST_IC SYSCLK=IHRC/4 // SYSCLK=IHRC/4
// Insert Initial Code
pac = 0xff;
$ T16M IHRC,/16,BIT15;
i_gword = 32768-40;
inten.T16 = 1;
engint;
while (1)
{
if(f_10ms == 1)
{
pwmr_cnt++;
f_10ms = 0;
}
// …
// wdreset;
}
}
void Interrupt (void)
{
pushaf;
if (Intrq.T16)
{ // T16 Trig
// User can add code
Intrq.T16 = 0;
stt16 i_gword;
if(int_cnt<250)
{
int_cnt++;
}
else
{
int_cnt = 0;
f_10ms =1;
}
//======pwm周期计数======
if(pwm_cnt<255)
{
pwm_cnt++;
}
else{
pwm_cnt = 0;
}
//===pwm输出=============
if(pwmr_cnt<pwm_cnt)
{
RLED_OUT = 1;
}
else
{
RLED_OUT = 0;
}
//…
}
popaf;
}