PCA模块的使用方式3:高速脉冲输出模式
高速输出模式的结构如图所示,原理与16位定时器模式几乎完全相同,与通用时钟输出不同的是:通用时钟输出不占用中断,PCA时钟输出需要CPU反复中断。在中断服务程序中改变比较/捕获寄存器【CCAPnH,CCAPnL】的值,或是在中断函数中清零PCA计数器【CH,CL】的值,使其从0开始重新计数。每当匹配发生的时候,端口电平自动翻转。
PCA模块用作时钟输出时,需要将寄存器 CCAPMn(n=0、1、2)的 ECON、MATn、TOGn位置1。当PCA计数器【CH,CL】的值与比较/捕获寄存器 【CCAPnH,CCAPnL】的值相等时,PCA模块的输出引脚CCPn将发生翻转。
PCA计数器所使用的时钟频率是系统默认的频率,也就是系统时钟频率SYSclk的12分频,如图所示:
如果希望使用其它的时钟频率,也可以自己在CMOD寄存器中设置:
CMOD:PCA工作模式寄存器
例题:使用PCA0产生10KHz的时钟输出。
问题解答:
几乎与扩展16位定时器完全相同,只是需要打开PCA端口翻转开关TOGn。
比较捕获寄存器【CCAPnH,CCAPnL】值的计算公式:
比较捕获寄存器值=PCA计数脉冲频率/(2*输出频率)
如果主时钟频率设置为22.1184MHz
系统时钟频率SYSclk=主时钟频率=22.1184MHz
PCA计数器频率=SYSclk/12
要求的时钟输出频率=10KHz
则装入【CCAPnH,CCAPnL】的值
value=(SYSclk/12)/(2*10KHz)=(22.1184MHz/12)/(2*10KHz)=92
即将92(0x5C)装入【CCAPnH,CCAPnL】寄存器中,当PCA计数值与比较/捕获寄存器【CCAPnH,CCAPnL】中的值相等时,PCA0输出引脚(P1.1)电平翻转。
在中断程序中,有两种处理方法,第一种:
增加步长值:也就是每次比较/捕获寄存器【CCAPnH,CCAPnL】中的值增加相同的步长值,例如此处的92,而不清零PCA计数器【CH,CL】的值。
//首先读取【CCAPnH,CCAPnL】中的值,再加上步长值92(0x5C)
temp=(CCAP0H<<8)+CCAP0L+0x5C;
//将修改后的值重新装入【CCAPnH,CCAPnL】中
CCAP0L=temp;
CCAP0H=temp>>8;
CCF0=0; //PCA模块的中断标志位不会由硬件自动清除,需要软件清除
完整代码如下:
#include "STC15W4K.H"
unsigned int value=92;
void main(void)
{
//默认主时钟不分频
CMOD=0x00; //设置PCA时钟源SYSclk/12
P_SW1=0x00; //CCP_S0=0, CP_S1=0; 输出管脚为PCA0模块第一引脚,即P1.1
CCON=0; //停止PCA计数器,清除CF和CCF0标志
CL=0;
CH=0;
CCAP0L=value;
CCAP0H=value>>8;
CCAPM0=0x4d; //0100 1101
//ECOM0使能16位比较器
//MATn 允许计数器匹配时产生中断
//TOGn 实现PCA输出端口电平翻转Toggle
// 和扩展定时器模式相比,只是多出了这个位的设置
//ECCFn 允许响应中断
EA=1; //总中断开
CR=1; //启动定时器[CH,CL]
while(1);
}
//中断服务程序
void PCA(void) interrupt 7
{
unsigned int temp;
if(CCF0) //如果CCF0产生中断
{
temp=(CCAP0H<<8)+CCAP0L+0x5C;
CCAP0L=temp;
CCAP0H=temp>>8;
CCF0=0; //PCA模块的中断标志位不会由硬件自动清除,需要软件清除
}
}
实验结果:
实验表明,这种增加步长值的方法所得到的频率误差最小。
另一种方法是
在中断服务程序中不改变比较/捕获寄存器【CCAPnH,CCAPnL】的值,而是清零PCA计数器【CH,CL】的值。这种方法误差稍微大一点,实测频率为:9.926KHz
程序段如下:
//中断服务程序
void PCA(void) interrupt 7
{
if(CCF0) //如果CCF0产生中断
{
CL=0;
CH=0;
CCF0=0; //PCA模块的中断标志位不会由硬件自动清除,需要软件清除
}
}