idata WORD cnt; //存储PCA计时溢出次数
idata WORD count0_tmp; //记录上一次的捕获值
idata WORD count1_tmp;
idata long int count0;
idata long int count1;
idata WORD result;
BYTE flag_updown;
#define CCP_S0 0x10 //P_SW1.4
#define CCP_S1 0x20 //P_SW1.5
sbit EPCA = IE^6; //PCA中断允许位
void InitPCA()
{
ACC = P_SW1;
ACC &= ~(CCP_S0 | CCP_S1); //CCP_S0=0 CCP_S1=0
P_SW1 = ACC; //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2)
CCON = 0; //初始化PCA控制寄存器
//PCA定时器停止
//清除CF标志
//清除模块中断标志
CL = 0; //复位PCA寄存器
CH = 0;
CCAP0L = 0;
CCAP0H = 0;
//CMOD = 0x09; //设置PCA时钟源为系统时钟,且使能PCA计时溢出中断
CMOD = 0x01; //12
}
void EnablePCA()//启动捕获
{
flag_updown = 1;
CCAPM0 = 0x21; //PCA模块0为16位捕获模式(上升沿捕获,可测从高电平开始的整个周期),且产生捕获中断
CR = 0; //
EPCA = 1; //使能PCA中断
}
/***********************************************************
功能:PCA中断服务程序,用于测定脉冲占空比:
变量:
flag_updown : 捕获脉冲标志 置0时程序不捕获脉冲,置1时开始捕获,计算完占空比后由本函数清零
count0:低电平时间
count1:高电平时间
说明:STC15单片机的PCA中断开启后关闭则无法再次开启
关于STC15单片机的PCA中断,如果作为定时器,中断号为7 如果作为脉冲捕获,中断号为6(并非手册说明7)
以上结论仅为本人经验
琛琛 2013/11/3
***********************************************************/
void PCA_isr() interrupt 6 //using 1
{
if (CF)
{
CF = 0;
cnt++; //PCA计时溢出次数+1
}
if (CCF0)
{
CCF0 = 0;
if(flag_updown == 1)//捕获到上升沿,开定时器,准备捕获下降沿
{
CR = 1; //PCA定时器开始工作
CCAPM0 = 0x11; //PCA模块0为16位捕获模式(下降沿捕获,可测从低电平开始的整个周期),且产生捕获中断
flag_updown = 2;
}
else if(flag_updown == 2)//捕获到下降沿,读取定时器,准备捕获上升沿
{
count0 = CCAP0H;
count0 = count0 << 8;
count0 = count0 + CCAP0L;
CCAPM0 = 0x21; //PCA模块0为16位捕获模式(上升沿捕获,可测从高电平开始的整个周期),且产生捕获中断
CCAP0L = 0;
CCAP0H = 0;
flag_updown = 3;
}
else if(flag_updown == 3)//捕获到上升沿,读取定时器,完成一次检测
{
EA = 0;
CR = 0; //关闭PCA定时器
//EPCA = 0; //关闭PCA中断 关闭之后打不开了
flag_updown = 0;
//LED = 0;
count1 = CCAP0H;
count1 = count1 << 8;
count1 = count1 + CCAP0L;
// count1_tmp = count1;
// count0_tmp = count0;
result = (10*count0+500)/count1;
//result = ((float)count0/(float)count1)*10;
count0 = 0;
count1 = 0;
CL = 0; //复位PCA寄存器
CH = 0;
CCAP0L = 0;
CCAP0H = 0;
cnt = 0;
//SendData('A'); //测试能否完成一次测试标志 如果可以完成一次测试,则串口输出'A'
EA = 1;
}
}
}