中斷加定時器---C語言版 優點:極少的占用系統軟件資源(CPU),隨時都可以解碼,而不管系統此時運行到何處。 缺點:占用系統兩個硬件資源,一個外部中斷和一個定時器。
/******************************************************
********六哥紅外解碼程序********************************
********************************************************/
#include"STC15Fxxxx.H"
///**************************************************
/////用戶配置區:
#define xi_tong_pl 12000000 ///晶振頻率設定 如你的系統晶振頻率是12MHz,則寫12000000
#define jan_zhi P1 ///解碼輸出二進制端口,解碼成功則從該端口輸出鍵值的二進制
sbit zhi_s = P5^5; ///解碼成功標志,解碼成功一次該端口取反一次
////外部中斷
#define zd_rkdz interrupt 0 ///中斷入口設置
#define zd_cffs IT0 ///中斷觸發方式設置
#define zd_dk EX0 ///中斷打開設置
////
#define stc_dsqsz AUXR &= 0x7F;//定時器時鐘12T模式,不需要可在AUXR....前加//
///**************************************************
/******************************************************************
*****本程序使用外部中斷加定時器來實現紅外解碼,占用系統軟件資********
*****源極少,硬件方面占用了一個外部中斷,定時器中斷還可以進行********
*****一些簡單的運用,軟件部分可以做很多的動作,就看你發揮了!********
******************************************************************/
#define shi_jian_ (xi_tong_pl/12000000)///定時器設置,請勿更改
unsigned char hwyhmh,hwyhml,hwjz,hwsj,hwjmws;///全局變量
bit hwjmok,yxjm;///全局變量,紅外解碼OK,允許解碼
void main(void)
{
EA=1; //總中斷打開
zd_cffs=1; //外部中斷_邊沿觸發方式
zd_dk=1; //外部中斷_打開
ET0=1; //定時器中斷打開
stc_dsqsz
TMOD &= 0xF0; //設置定時器模式
TMOD |= 0x01; //設置定時器
while(1)
{if(hwjmok)
{hwjmok=0;
jan_zhi=hwjz;
zhi_s=~zhi_s;
}
}
}
/*------------------------------------------------
定時器0中斷子程序
------------------------------------------------*/
void T0ZDCX(void) interrupt 1 using 3
{
yxjm=0; //未收到重復碼清除解碼允許標志
hwjz=0;
TR0=0; //關閉定時器
}
/*********************************************************
中斷方式紅外接收程序
***********************************************************/
void ZDhwjsCX(void) zd_rkdz using 3
{
unsigned int a=TH0*256+TL0;
TL0=0;
TH0=0;
TR0=1; ///開啟T0
if(a>shi_jian_*13000&&a<shi_jian_*14000)///if1分支2.判引導碼13-14ms
{
hwsj=0;
hwjmws=32;
yxjm=1;
}
else if(yxjm) ///if1分支1.已收到引導碼,允許解碼
{
if(a>shi_jian_*11000&&a<shi_jian_*12000&&hwjmws==0)///if2分支1。判重復碼11-12ms
{
hwjmok=1;
}
else ///if2分支3。否則解碼,取位
{
hwjmws--;
////////////////////////////////////////////////////////
if (a>shi_jian_*2000&&a<shi_jian_*2400)/// 判1 2-2.4ms
{
hwsj>>=1;
hwsj|=0x80;
}
else if (a>shi_jian_*1000&&a<shi_jian_*1300)/// 判0 1-1.3ms
{
hwsj>>=1;
}
else
{
hwjmws=32;
yxjm=0; //清除允許解碼標志
TR0=0; //關閉T0
}
//////////////////////////////////////////////////////////
}
switch(hwjmws)
{case 24:{
hwyhmh=hwsj;
hwsj=0;
}
break;
case 16:{hwyhml=hwsj;
hwsj=0;}
break;
case 8:{hwjz=hwsj;
hwsj=0;}
break;
case 0:{if(hwjz==~hwsj)
{hwjmok=1;
TL0=shi_jian_*12000%256;
TH0=shi_jian_*12000/256;
}
}
break;
default:;}
}
else;
}
中斷加定時器---匯編版;******************************************************
;********六哥紅外解碼程序********************************
;********************************************************/
;******************************************************************
;*****本程序使用外部中斷加定時器來實現紅外解碼,占用系統軟件資********
;*****源極少,硬件方面占用了一個外部中斷,定時器中斷還可以進行********
;*****一些簡單的運用,軟件部分可以做很多的動作,就看你發揮了!********
;******************************************************************/
hwyhmh data 7fh
hwyhml data 7eh
hwjz data 7dh
hwsj data 7ch
DSQ_ZDCS data 7bh
ZDCS DATA 7AH
hwjmok bit 20h.0
yxjm bit 20h.1
hwjmwei bit 20h.2
hwjmkg BIT 20H.3
HWJST BIT P3.3
ORG 0000H
AJMP MAIN
ORG 0013H
LJMP WBZD1
ORG 000BH
LJMP DSQ_0
ORG 0050H
MAIN:
SETB EA
SETB IT1
SETB EX1
SETB ET0
MOV TMOD,#01H
CLR hwjmkg
CLR yxjm
CLR hwjmok
HHHH:
JB hwjmok,jm_cg ;JBC:為1跳轉并把該位清零,為0則順序執行
;此部分可寫其他程序,不會影響接收
LJMP HHHH
jm_cg: ;這里寫解碼成功后的動作
CLR hwjmok
MOV P1,hwjz
LJMP HHHH
;==============================================
WBZD1:
INC ZDCS
MOV A,ZDCS
JNB yxjm,ZD0_5 ;
CLR TR0
MOV TH0,#0FAH ;設置定時1400us
MOV TL0,#70H ;
SETB TR0 ;開定時器
XCH A,hwsj
MOV C,hwjmwei
CLR hwjmwei
RRC A
XCH A,hwsj
CJNE A,#10,ZD0_0 ;取出用戶碼高位
MOV hwyhmh,hwsj
AJMP ZD0_4
ZD0_0:
CJNE A,#18,ZD0_1 ;取出用戶碼低位
MOV hwyhml,hwsj
AJMP ZD0_4
ZD0_1:
CJNE A,#26,ZD0_2 ;取出鍵值
MOV hwjz,hwsj
AJMP ZD0_4
ZD0_2:
CJNE A,#34,ZD0_4 ;取出鍵值反碼
MOV A,hwsj
CPL A
CJNE A,hwjz,ZD0_3 ;鍵值判斷
SETB hwjmok ;解碼正確,置位標志位
ZD0_3: ;解碼不成功
CLR TR0 ;關閉定時器
CLR hwjmkg ;關閉解碼開關
CLR yxjm ;清除允許解碼標志
MOV ZDCS,#0 ;中斷次數清零
MOV DSQ_ZDCS,#0 ;定時器中斷次數清零
ZD0_4:
RETI ;中斷返回
ZD0_5: ;開始接收引導碼
CJNE A,#1,ZD0_3 ;
MOV TH0,#0F2H ;設置定時3.5ms
MOV TL0,#54H ;
SETB TR0 ;開定時器
SETB hwjmkg ;開紅外解碼開關
AJMP ZD0_4
DSQ_0:
JNB hwjmkg,T0FH ;
JNB yxjm,DSQ_0_0 ;
SETB hwjmwei
CLR TR0
T0FH:
RETI
;==========引導碼判斷程序===============
DSQ_0_0:
MOV TH0,#0F2H ;設置定時3.5ms
MOV TL0,#54H ;
INC DSQ_ZDCS ;對T0中斷計數
MOV A,DSQ_ZDCS
CJNE A,#1,DSQ_0_1
JB HWJST,JMCW ;判低電平,9ms引導碼
AJMP T0FH
DSQ_0_1:
CJNE A,#2,DSQ_0_2
JB HWJST,JMCW ;判低電平,9ms引導碼
AJMP T0FH
DSQ_0_2:
JNB HWJST,JMCW ;判高電平,4.5ms引導碼
SETB yxjm ;引導碼接收成功,允許解碼
CLR hwjmwei ;
CLR TR0
AJMP T0FH
JMCW: ;引導碼接收錯誤,
CLR TR0 ;關閉定時器
CLR hwjmkg ;關閉解碼開關
CLR yxjm ;清除允許解碼標志
MOV ZDCS,#0 ;中斷次數清零
MOV DSQ_ZDCS,#0 ;定時器中斷次數清零
AJMP T0FH
END
純軟件解碼 --- 匯編版利用程序判電平和時間進行解碼,缺點是浪費系統軟件資源;優點是對系統硬件要求稍低 ORG 0000H T0ZD BIT 20H.2 XH BIT P3.3 ;紅外接收頭數據接口 RS BIT P2.3 RW BIT P2.4 E BIT P2.5 BB BIT P3.6 ORG 0000H ; AJMP MAIN ORG 000BH ;T0中斷入口 LJMP T0ZDCX ORG 0100H ;主程序首地址 MAIN: LCALL CSH MOV DPTR,#TAB ;總查表 SETB EA ;T0中斷設定 SETB ET0 MOV TMOD,#01H DDXH: ;信號接收前準備 SETB P2.0 ;關信號指示燈 MOV P0,#0FFH CLR TR0 ;關T0中斷 CLR T0ZD ;接收信號時間判斷 MOV R5,#4 ;延時計數 MOV TH0,#00H MOV TL0,#00H ;================解碼主要過程===========關鍵============================================================ JB XH,$ ;等待電平變低,解碼從這開始 CLR P2.0 ;開信號指示燈,表示正在接收信號 MOV P0,#8EH SETB TR0 ;開T0中斷 LCALL YS3MS JB XH,DDXH ;干擾檢測 LCALL YS3MS JB XH,DDXH ;干擾檢測 DD1: JB T0ZD,DDXH ;是否超出接收允許時間 JNB XH,DD1 ;等待電平變高 LCALL YS3MS JNB XH,DDXH ;干擾檢測 DD2: JB T0ZD,DDXH ;是否超出接收允許時間 JB XH,DD2 ;等待電平變低 JSSJ: ;信號確認,開始接收數據 MOV R0,#30H ZJ: ;接收一個字節數據 MOV R2,#8 WEI: ;位數據,分辯0和1 JB T0ZD,DDXH ;是否超出接收允許時間 JNB XH,WEI ;等待電平變高 LCALL YS845 MOV C,XH ;取位數據 RRC A DD3: JB T0ZD,DDXH ;是否超出接收允許時間 JB XH,DD3 ;等待電平變低,為1的高電平提供過度 DJNZ R2,WEI ;8位數據是否接收完 MOV @R0,A INC R0 CJNE R0,#34H,ZJ ;四字節數據是否接收完 MOV A,33H CPL A CJNE A,32H,DDXH ;鍵值確認,解碼 MOV R4,A ;==========這里已經取出鍵值,存在R4中================================================== MOV R7,#100; TSY:MOV R6,#255 DJNZ R6,$ CPL BB DJNZ R7,TSY MOV A,#0CDH ;鍵值高位輸出 LCALL YJP_XZL MOV A,R4 MOV B,#10H DIV AB MOVC A,@A+DPTR LCALL YJP_XSJ MOV A,#0CEH ;鍵值低位輸出 LCALL YJP_XZL MOV A,B MOVC A,@A+DPTR LCALL YJP_XSJ ; LCALL DYBF ;調用燈控制子程序 LJMP DDXH ;返還等待下一次信號 YS845: ;延時845微秒 MOV R7,#255 DJNZ R7,$ MOV R7,#165 DJNZ R7,$ RET YS3MS: ;延時3ms MOV R7,#8 DDD: MOV R6,#255 DJNZ R6,$ DJNZ R7,DDD RET T0ZDCX: ;T0中斷程序 MOV TL0,#00H MOV TH0,#00H DJNZ R5,T0FH SETB T0ZD T0FH: RETI ;===============以下是多余部分=========================================================================== DYBF: MOV A,#0C0H ;用號碼前高位輸出 LCALL YJP_XZL MOV A,30H MOV B,#10H DIV AB MOVC A,@A+DPTR LCALL YJP_XSJ MOV A,#0C1H ;用戶碼前低位輸出 LCALL YJP_XZL MOV A,B MOVC A,@A+DPTR LCALL YJP_XSJ MOV A,#0C4H ;用戶碼后高位輸出 LCALL YJP_XZL MOV A,31H MOV B,#10H DIV AB MOVC A,@A+DPTR LCALL YJP_XSJ MOV A,#0C5H ;用戶碼后低位輸出 LCALL YJP_XZL MOV A,B MOVC A,@A+DPTR LCALL YJP_XSJ ;============此處專門針對我的開發板和遙控,不是解碼的關鍵,只是一種應用舉例 MOV A,R4 CJNE A,#0CH,BA1 ;是否1號鍵按下 CPL P1.0 ;點亮1號燈 BA1: CJNE A,#18H,BA2 ;是否2號鍵按下 CPL P1.1 ;點亮1號燈 BA2: CJNE A,#5EH,BA3 ;是否3號鍵按下 CPL P1.2 ;點亮1號燈 BA3: CJNE A,#08H,BA4 ;是否4號鍵按下 CPL P1.3 ;點亮1號燈 BA4: CJNE A,#1CH,BA5 ;是否5號鍵按下 CPL P1.4 ;點亮1號燈 BA5: CJNE A,#5AH,BA6 ;是否6號鍵按下 CPL P1.5 ;點亮1號燈 BA6: CJNE A,#42H,BA7 ;是否7號鍵按下 CPL P1.6 ;點亮1號燈 BA7: CJNE A,#52H,BAB ;是否8號鍵按下 CPL P1.7 ;點亮1號燈 BAB:RET CSH: ;=============液晶初始化=============== MOV A, #00111000B ;8位數據,雙行顯示,5-7字型 LCALL YJP_XZL ;調用寫液晶指令 MOV A, #00001100B ;顯示屏開啟,光標出現在地址計數器位置,光標不閃爍 LCALL YJP_XZL ;調用寫液晶指令 MOV A, #00000110B ;光標右移一格,AC值加一,字符全部不動 LCALL YJP_XZL ;調用寫液晶指令 MOV A,#81H ; LCALL YJP_XZL MOV A, #4CH ;L的ASCII碼 LCALL YJP_XSJ MOV A,#83H ; LCALL YJP_XZL MOV A, #47H ;G的ASCII碼 LCALL YJP_XSJ MOV A,#85H ; LCALL YJP_XZL MOV A, #58H ;X的ASCII碼 LCALL YJP_XSJ MOV A,#88H ; LCALL YJP_XZL MOV A, #5AH ;Z的ASCII碼 LCALL YJP_XSJ MOV A,#89H ; LCALL YJP_XZL MOV A, #68H ;h的ASCII碼 LCALL YJP_XSJ MOV A,#8AH ; LCALL YJP_XZL MOV A, #69H ;i的ASCII碼 LCALL YJP_XSJ MOV A,#8CH ; LCALL YJP_XZL MOV A, #5AH ;Z的ASCII碼 LCALL YJP_XSJ MOV A,#8DH ; LCALL YJP_XZL MOV A, #61H ;a的ASCII碼 LCALL YJP_XSJ MOV A,#8EH ; LCALL YJP_XZL MOV A, #6FH ;o的ASCII碼 LCALL YJP_XSJ MOV A,#0C2H ; LCALL YJP_XZL MOV A, #48H ;H的ASCII碼 LCALL YJP_XSJ MOV A,#0C6H ; LCALL YJP_XZL MOV A, #48H ;H的ASCII碼 LCALL YJP_XSJ MOV A,#0CAH ; LCALL YJP_XZL MOV A, #4AH ;J的ASCII碼 LCALL YJP_XSJ MOV A,#0CBH ; LCALL YJP_XZL MOV A, #5AH ;Z的ASCII碼 LCALL YJP_XSJ MOV A,#0CCH ; LCALL YJP_XZL MOV A, #3AH ;:的ASCII碼 LCALL YJP_XSJ MOV A,#0CFH ; LCALL YJP_XZL MOV A, #48H ;H的ASCII碼 LCALL YJP_XSJ RET ;=========寫指令到液晶============= YJP_XZL: LCALL CHECK_BUSY;查詢忙碌狀態 CLR E CLR RS CLR RW SETB E MOV P0,A;寫指令 CLR E RET ;==========寫數據到液晶============== YJP_XSJ: LCALL CHECK_BUSY;查詢忙碌狀態 CLR E SETB RS CLR RW SETB E MOV P0,A;寫數據 CLR E RET ;=========查詢忙碌標志============ CHECK_BUSY: PUSH ACC BUSY_LOOP: CLR E SETB RW CLR RS SETB E MOV A,P0;讀取狀態 JB p0.7,BUSY_LOOP POP ACC LCALL DEL RET DEL: MOV R6,#5 L1: MOV R7,#248 DJNZ R7,$ DJNZ R6,L1 RET TAB:DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H DB 41H,42H,43H,44H,45H,46H END
定時器捕獲中斷法---c語言版
|