PCA模块的使用方式2:扩展定时器模式
PCA模块可以作为16位定时器使用,即扩展一个16位定时器。
16位定时器模式的结构如下图所示
电路图的解读:
图中红色标示部分就是与扩展定时器有关的寄存器位。
首先使能ECOMn,开启16位比较器。
MATn位置1,当CH,CL中的计数值与CCAPnH,CCAPnL中的数值相等的时候,中断标志位将被置位。
ECCFn位置1,允许MCU响应中断。
EA=1总中断允许
CH,CL是一个十六位的计数器,当CR=1时,开启这个计数器,每隔一定的时间自动加1。当增加到与比较寄存器CCAPnH,CCAPnL中的值相等的时候,就会将中断标志位CCFn置位。此时如果EECFn=1允许响应中断,并且EA =1总中断允许,则程序将跳转到PCA中断服务子程序即interrupt 7处。
PCA计数器[CH,CL]每隔一定时间自动加1,时间间隔取决于所选择的时钟源。默认时钟源为SYSclk/12,即系统时钟的12分频。所以每隔12个时钟周期[CH,CL]加1,当[CH,CL]增加到等于捕获/比较寄存器[CCAPnH,CCAPnL]的值时,CCFn=1,产生中断请求。
相关寄存器:
AUXR1/P_SW1:
CMOD:PCA工作模式寄存器
例题:
要求:使用PCA模块扩展一个16位定时器,控制LED灯每隔0.5秒亮一次。RC振荡器12MHz。
问题解答:
主时钟频率 MAINclk=12MHz
如果将系统时钟频率设置为 SYSclk=MAINclk/128
如果将PCA模块计数频率设置为 PCAclk=SYSclk/12
根据要求,0.5秒产生一次中断,在中断函数中对LED灯端口进行取反,就是需要产生0.5秒的定时。
根据设置,PCA计数器【CH,CL】计数一次所需的时间是:1/(MAINclk/128/12)
那么,经过Value次计数后,时间应该是0.5秒,即
0.5=1/(MAINclk/128/12)*Value
经过计算得Value=3906,将这个值装入比较/捕获寄存器中【CCAPnH,CCAPnL】。
#include "STC15W4K.H"
sbit LED_PCA0=P0^0; //定义LED灯端口
unsigned int value=3906;
void main(void)
{
CLK_DIV=0x07; //SYSclk频率=主时钟频率/128
CMOD=0x00; //设置PCA时钟源SYSclk/12
P_SW1=0x00; //CCP_S0=0, CP_S1=0; PCA模块输出管脚设置
CCON=0; //停止PCA计数器,清除CF(PCA计数器溢出中断)和CCF0(PCA模块0中断)标志
CL=0; //清PCA计数器
CH=0;
CCAP0L=value; //将需要比对的计数值装入比较/捕获寄存器中【CCAP0H,CCAP0L】
CCAP0H=value>>8;
CCAPM0=0x49; //0100 1001
//ECOM0使能16位比较器
//MATn 允许计数器匹配时产生中断
//ECCFn 允许响应中断
EA=1; //总中断开
CR=1; //启动定时器[CH,CL]
while(1);
}
//中断服务程序
void PCA(void) interrupt 7
{
if(CCF0) //如果CCF0产生中断
{
CCF0=0; //PCA模块的中断标志位不会由硬件自动清除,需要软件清除
CL=0; //清计数器值
CH=0;
LED_PCA0=!LED_PCA0; //LED灯取反
}
}