PCA模块的使用方式4:PWM脉宽调制模式
实验1:产生指定占空比的PWM波 实验2:产生指定频率的PWM波 实验3:呼吸灯
PCA模块应用4:PWM脉宽调制
脉冲宽度调制简称PWM,可用于调整输出直流平均电压,对于矩形波而言,输出平均电压等于峰值电压×占空比,占空比是一个脉冲周期内高电平时间与周期的比值。
例如,峰值电压等于5V,占空比等于50%的方波信号平均电压等于2.5V,也就是万用表直流档测量得到的电压值,PWM结构如图所示,PWM输出不使用中断。
我们只使用PCA计数器的低8位【CL】,高8位【CH】固定为0。
【EPCnL,CCAPnL】是比较寄存器
【EPCnH,CCAPnH】是自动装载寄存器
系统时钟频率默认为不分频,即SYSclk=主时钟频率
PCA模块时钟频率默认为系统时钟频率的12分频,即PCAclk=SYSclk/12
PWM默认输出频率=PCA计数器频率/256=SYSclk/12/256
PWM的默认输出频率为什么是PCA计数器频率的1/256呢?
因为PCA计数器只有CL计数,CH为0,CL一共可以计数256个值,所以PCA计数周期*256=PWM波的周期。
那么,PCA计数器的频率=256*PWM波的频率,因此PWM波周期频率=PCA计数器频率/256
PWM波的周期=PCA计数器周期*256
这里,可以与模拟电路中的比较器进行类比。当同相端的电压>反相端的电压,输出为高电平,当同相端的电压<反相端的电压,输出为低电平。
要使用PWM功能,需要置位ECOMn和PWNn,它们两个是相与的关系,所以需要同时置1.
ECOMn是开启9位比较器
PWMn是启动PCA模块的PWM功能
【0,CL[7:0]】与【EPCnL, CCAPnL[7:0]】进行比较,
当【0,CL[7:0]】中的值<【EPCnL, CCAPnL[7:0]】时,输出为低,
当【0,CL[7:0]】中的值>=【EPCnL, CCAPnL[7:0]】时,输出为高,
当 EPCnL=0且 CCAPnL=00H时,PWM固定输出高,
当 EPCnL=1且 CCAPnL=FFH时,PWM固定输出低。
PWM默认输出频率=系统时钟/12/256 系统时钟典型值22.1184MHz
PWM输出占空比=(1- CCAPnH/256)×100%,进一步推导可得出:
CCAPnH=(1-占空比)×256,也就是说 CCAPnH中存储的是低电平的时间
比如要求输出占空比为87.5%的信号, CCAPnH=(1-0.875)×256=32,即0x20
当某个I/O口作为PM使用时,该口自动切换到强推挽输出模式。因此实验过程中注意I0口不能短路。
实验1:利用PCA模块输出占空比为87.5%的PWM信号
问题解答:利用PCA通道0实现在P1.1输出占空比为87.5%的PWM信号,设R/C时钟频率Fosc=22.1184MHz。
#include “STC15W4K.H”
void main()
{
CCAPM0=0x42; //设置PCA模块为PWM输出方式
//ECOMn=1, PWMn=1
CR=1; //PCA计数器开始运行
CCAP0H=0x20; //脉宽控制(低电平时间)
while(1); //程序空转
}
理论计算P1.1频率=22118400/12/256=7.2KHz,实验结果:测得频率为7.210KHz,占空比87.5%。可见理论计算与实际结果是一至的。
上面的程序中使用的是系统默认的频率,也可以自己设置所需要的频率,如图所示:
实验2:要求使用定时器0作为PCA的时钟源,通道1输出占空比87.5%频率200Hz的PWM波.
问题解答:
要求输出占空比为87.5%的信号, 则在CCAPnH中写入低电平所占时间,即
CCAPnH=(1-0.875)×256=32,即0x20
PWM频率=PCA计数频率/256
200Hz=(1/T0定时时长)/256
1/T0定时时长=200*256
T0定时时长=1/(200*256)=19.53us
设主时钟频率Fosc=22.1184MHz,不分频,则系统时钟频率SYSclk=22.1184MHz
则T0初值为:
TH0=0xFF; //定时时间19.53us
TL0=0xDC;
//产生指定频率的PWM波,使用定时器T0作为PCA计数时钟源
#include "STC15W4K.H"
void initPCA()
{
//初始化定时器T0为16位自动重装方式,
//其溢出脉冲作为PCA计数器的时钟源
TMOD=0x00;
TH0=0xFF; //定时时间19.53us
TL0=0xDC;
TR0=1; //启动定时器T0
//初始化PCA模块1为PWM输出方式
CMOD=0x84; //#1000 0100B , 选择T0作为PCA计数器的时钟源
CCAPM1=0x42; //设置PCA模块1为8为PWM输出方式。脉冲在P1.0引脚输出
CCAP1H=0x20; //设置占空比(实际上这里装在的是低电平时间)
EA=1; //开启总中断
CR=1; //开启PCA计数器(CH,CL)计数
}
void main(void)
{
initPCA();
while(1);
}
实验3:产生频率不变,但是脉冲宽度可变的PWM波,控制LED灯,产生渐暗效果,也就是呼吸灯。
当PCA计数器溢出时,也就是PWM波一个周期到时,产生中断,在中断函数中逐渐增大和减小占空比,使得输出平均电压平滑变化,控制LED灯产生呼吸灯的效果。
#include "STC15W4K.H"
#define uchar unsigned char
#define uint unsigned int
void PCA_int() interrupt 7
{
static uchar data a=1;
static uchar data b=0;
if(a==1)
{
b++;
if(b==255)
a=0;
}
if(a==0)
{
b--;
if(b==0)
{ a=1; b++; }
}
CCAP0H=b;
CCAP0L=b;
CF=0;
}
void main()
{
P_SW1=0x00; //CCP_S0=0 CCP_S1=0使用PCA0(P1.1)管脚输出
CCON=0; //停止PCA计数器,清除CF和CCF0标志
//CF计数溢出中断 CCF0 PCA0模块中断
CL=0; //清零PCA计数器的值
CH=0;
CMOD=0x03; //PCA时钟源为 系统时钟SYSclk/2 允许CF中断
PCA_PWM0=0x00; //PCA模块0,工作于8为的PWM模式
CCAP0L=0;
CCAP0H=0;
CCAPM0=0x42; //使能比较,脉宽调制模式
CR=1; //启动PCA计数器工作
EA=1; //总中断开
while(1);
}