任务:
利用STC12C5410AD自带的4路PCA,扩展4路外部中断;利用4路外部中断来对输入的脉冲序列进行计数。
备注:
本文工程文件里还涉及到STC12C5410AD的UART、Time0等接口函数,请读者自行理解
一、PCA16位定时器计数器结构
从图中得知,要产生PCA溢出中断需要进行一下设置:
1、 选择PCA16计数器的时钟源。时钟源的选择由PCA的CMOD寄存器的CPS1和CPS0决定。
2、 IDLE跟CIDL必须有一位为0(常规的置CIDL为0)
3、 CR必须置1,允许计数器开始计数
4、 CMOD的ECF必须置1,以允许CCOD中的CF位在产生中断时:CF=1
5、 需要给PCA的16位计数器CH和CL赋初值
二、PCA捕获模式
PCA工作于捕获模式需要进行一下设置:(主要是配合CCON寄存器和CCAPMn寄存器)
1、 设置PCA捕获模块的对外部脉冲的捕获方式:主要是允许上升沿捕获或者下降沿捕获。由CCAPMn的CAPPn跟CAPNn决定:当CAPPn=1,允许上升沿捕获;当CAPNn=1,允许下降沿捕获
2、 使能CCFn中断。设置相应的ECCFn=1
具体的工作流程如下,以PCA0为例并设置为上升沿捕获:PCA0模块对P3^7(PCA0的输入管脚)进行跳变捕获,当采样到有效的上升沿时,PCA在硬件上会把PCA的计数器寄存器(CH/CL)的值转载到PCA0的捕获寄存器(CCAP0L和CCAPOH)中,置位中断标志位:CF =1,CCF0=1。使用者则只需要,在中断函数里进行相关的操作即可,记得要清零中断标志位。
三、IO口初始化函数、PCA初始化函数、PCA中断处理函数
/*******************************************************************************
* Function Name : IO_Init
* Description : IO初始化
* Input : None
* Output : None
* Return : None
* Others : 系统时钟20Mhz
*******************************************************************************/
void IO_Init(void)
{
P3M0 |= 0xA0;//初始化P3^7(PCA0),P3^5(PCA1)的IO状态为:仅为输入,
P3M1 |= 0x00;
P2M0 |= 0x10;//初始化P2^4(PCA3)的IO状态为:仅为输入
P2M1 |= 0x00;
}
/*******************************************************************************
* Function Name : PCA_Init
* Description : PCA初始化
* Input : None
* Output : None
* Return : None
* Others : 系统时钟20Mhz
*******************************************************************************/
void PCA_Init(void)
{
CMOD |= 0x01;//CMOD=00000011
//CIDL=0,空闲模式下允许PCA继续工作
//CPS1:CPS0=01,PCA的时钟系统为:sysclk/2
//ECF=1,允许寄存器CCON中CF位的中断
CCON |= 0x00;//CCON=01000000
//CF=0,PCA计数器阵列溢出标志位清零
//CR=0,关闭PCA计数器阵列
//CCF0-3=0,PCA模块0123中断标志位清零
CCAPM0 |= 0x21;//CCAPM0=00100001
//ECOM0=0,不允许比较器功能
//CAPP0=1,允许上升沿捕获
//MAT0=0,PCA计数值与模块的捕获值相匹配时,置位中断CCP0
//ECCF0=1,使能CCF0中断
CCAPM1 |= 0x21;//CCAPM1=00100001
//ECOM1=0,不允许比较器功能
//CAPP1=1,允许上升沿捕获
//MAT1=0,PCA计数值与模块的捕获值相匹配时,置位中断CCP1
//ECCF1=1,使能CCF1中断
CCAPM2 |= 0x21;//CCAPM2=00100001
//ECOM2=0,不允许比较器功能
//CAPP2=1,允许上升沿捕获
//MAT2=0,PCA计数值与模块的捕获值相匹配时,置位中断CCP2
//ECCF2=1,使能CCF2中断
CCAPM3 |= 0x21;//CCAPM3=00100001
//ECOM3=0,不允许比较器功能
//CAPP3=1,允许上升沿捕获
//MAT3=0,PCA计数值与模块的捕获值相匹配时,置位中断CCP3
//ECCF3=1,使能CCF3中断
CH = 0;//PCA装载值的高8位
CL = 0;//PCA装载值的低8位
CCAP0L = 0;//PCA0捕获计数值的高8位
CCAP0H = 0;//PCA0捕获计数值的低8位
CCAP1L = 0;//PCA1捕获计数值的高8位
CCAP1H = 0;//PCA1捕获计数值的低8位
CCAP2L = 0;//PCA2捕获计数值的高8位
CCAP2H = 0;//PCA2捕获计数值的低8位
CCAP3L = 0;//PCA3捕获计数值的高8位
CCAP3H = 0;//PCA3捕获计数值的低8位
CR = 1; //CR=1,启用PCA计数器阵列
IE |= 0x40;//EPCA_LVD=1,允许PCA模块和低压监测中断
EA = 1; //EA=1,打开总中断
}
/*******************************************************************************
* Function Name : PCA_ISR
* Description : PCA扩展中断处理函数
* Input : None
* Output : None
* Return : None
* Others : None
*******************************************************************************/
void PCA_ISR(void) interrupt 7 using 1
{
EPCA_LVD = 0;//关闭PCA中断
if(1 == CF)//有信号就进入捕获中断
{
CF = 0; //清零PCA总的捕获中断标志位
}
if(1 == CCF0)
{
CCF0 = 0; //清零PCA0的捕获中断标志位
CCF0_Flag++; //CCF0_Flag标志位递增
}
if(1 == CCF1)
{
CCF1 = 0; //清零PCA1的捕获中断标志位
CCF1_Flag++; //CCF1_Flag标志位递增
}
if(1 == CCF2)
{
CCF2 = 0; //清零PCA2的捕获中断标志位
CCF2_Flag++; //CCF2_Flag标志位递增
}
if(1 == CCF3)
{
CCF3 = 0; //清零PCA3的捕获中断标志位
CCF3_Flag++; //CCF3_Flag标志位递增
}
EPCA_LVD = 1;//打开PCA中断
}
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』