文本中的工程文件下載地址:http://download.csdn.net/detail/cgb165937385/5310549
任務:
利用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中斷
}