㈠ 單片機紅外解碼
紅外解碼程序!
/*-----------------------------------------------
名稱:遙控器紅外解碼液晶顯示
------------------------------------------------*/
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include<stdio.h>
#include<intrins.h>
#define TURE 1
#define FALSE 0
sbit IR=P3^2; //紅外介面標志
sbit RS = P2^4;//Pin4
sbit RW = P2^5;//Pin5
sbit E = P2^6;//Pin6
#define Data P0//數據埠
unsigned int hour,minute,second,count;
char code Tab[16]="0123456789ABCDEF";
char data TimeNum[]=" ";
char data Test1[]=" ";
/******************************************************************/
/* 變數聲明 */
/******************************************************************/
unsigned char irtime;//紅外用全局變數
bit irpro_ok,irok;
unsigned char IRcord[4]; //處理後的紅外碼,分別是 客戶碼,客戶碼,數據碼,數據碼反碼
unsigned char irdata[33]; //33個高低電平的時間數據
/******************************************************************/
/* 函數聲明 */
/******************************************************************/
void Ir_work(void);
void Ircordpro(void);
void ShowString (unsigned char line,char *ptr);
/******************************************************************/
/* 定時器0中斷服務函數 */
/******************************************************************/
void tim0_isr (void) interrupt 1 using 1//定時器0中斷服務函數
{
irtime++; //用於計數2個下降沿之間的時間
}
/******************************************************************/
/* 外部中斷0函數 */
/******************************************************************/
void ex0_isr (void) interrupt 0 using 0//外部中斷0服務函數
{
static unsigned char i; //接收紅外信號處理
static bit startflag; //是否開始處理標志位
if(startflag)
{
if(irtime<63&&irtime>=33)//引導碼 TC9012的頭碼,9ms+4.5ms
i=0;
irdata[i]=irtime;//存儲每個電平的持續時間,用於以後判斷是0還是1
irtime=0;
i++;
if(i==33)
{
irok=1;
i=0;
}
}
else
{irtime=0;startflag=1;}
}
/******************************************************************/
/* 定時器0初始化 */
/******************************************************************/
void TIM0init(void)//定時器0初始化
{
TMOD=0x02;//定時器0工作方式2,TH0是重裝值,TL0是初值
TH0=0x00; //重載值
TL0=0x00; //初始化值
ET0=1; //開中斷
TR0=1;
}
/******************************************************************/
/* 外部中斷初始化 */
/******************************************************************/
void EX0init(void)
{
IT0 = 1; //指定外部中斷0下降沿觸發,INT0 (P3.2)
EX0 = 1; //使能外部中斷
EA = 1; //開總中斷
}
/******************************************************************/
/* 紅外鍵值處理 */
/******************************************************************/
void Ir_work(void) //紅外鍵值散轉程序
{
TimeNum[5] = Tab[IRcord[0]/16]; //處理客戶碼並顯示
TimeNum[6] = Tab[IRcord[0]%16];
TimeNum[8] = Tab[IRcord[1]/16]; //處理客戶碼並顯示
TimeNum[9] = Tab[IRcord[1]%16];
TimeNum[11] = Tab[IRcord[2]/16]; //處理數據碼並顯示
TimeNum[12] = Tab[IRcord[2]%16];
TimeNum[14] = Tab[IRcord[3]/16]; //處理數據反碼並顯示
TimeNum[15] = Tab[IRcord[3]%16];
ShowString(1,TimeNum);//顯示處理過後的碼值
irpro_ok=0; //處理完成後清楚標志位
}
/******************************************************************/
/* 紅外解碼函數處理 */
/******************************************************************/
void Ircordpro(void)//紅外碼值處理函數
{
unsigned char i, j, k;
unsigned char cord,value;
k=1;
for(i=0;i<4;i++) //處理4個位元組
{
for(j=1;j<=8;j++) //處理1個位元組8位
{
cord=irdata[k];
if(cord>7)//大於某值為1,這個和晶振有絕對關系,這里使用12M計算,此值可以有一定誤差
{
value=value|0x80;
}
else
{
value=value;
}
if(j<8)
{
value=value>>1;
}
k++;
}
IRcord[i]=value;
value=0;
} irpro_ok=1;//處理完畢標志位置1
}
/******************************************************************/
/* 微秒延時函數 */
/******************************************************************/
void DelayUs(unsigned char us)//delay us
{
unsigned char uscnt;
uscnt=us>>1;/* Crystal frequency in 12MHz*/
while(--uscnt);
}
/******************************************************************/
/* 毫秒函數聲明 */
/******************************************************************/
void DelayMs(unsigned char ms)//delay Ms
{
while(--ms)
{
DelayUs(250);
DelayUs(250);
DelayUs(250);
DelayUs(250);
}
}
/******************************************************************/
/* 寫入命令函數 */
/******************************************************************/
void WriteCommand(unsigned char c)
{
DelayMs(5);//操作前短暫延時,保證信號穩定
E=0;
RS=0;
RW=0;
_nop_();
E=1;
Data=c;
E=0;
}
/******************************************************************/
/* 寫入數據函數 */
/******************************************************************/
void WriteData(unsigned char c)
{
DelayMs(5); //操作前短暫延時,保證信號穩定
E=0;
RS=1;
RW=0;
_nop_();
E=1;
Data=c;
E=0;
RS=0;
}
/******************************************************************/
/* 寫入位元組函數 */
/******************************************************************/
void ShowChar(unsigned char pos,unsigned char c)
{
unsigned char p;
if (pos>=0x10)
p=pos+0xb0; //是第二行則命令代碼高4位為0xc
else
p=pos+0x80; //是第二行則命令代碼高4位為0x8
WriteCommand (p);//寫命令
WriteData (c); //寫數據
}
/******************************************************************/
/* 寫入字元串函數 */
/******************************************************************/
void ShowString (unsigned char line,char *ptr)
{
unsigned char l,i;
l=line<<4;
for (i=0;i<16;i++)
ShowChar (l++,*(ptr+i));//循環顯示16個字元
}
/******************************************************************/
/* 初始化函數 */
/******************************************************************/
void InitLcd()
{
DelayMs(15);
WriteCommand(0x38); //display mode
WriteCommand(0x38); //display mode
WriteCommand(0x38); //display mode
WriteCommand(0x06); //顯示游標移動位置
WriteCommand(0x0c); //顯示開及游標設置
WriteCommand(0x01); //顯示清屏
}
/******************************************************************/
/* 主函數 */
/******************************************************************/
void main(void)
{
EX0init(); //初始化外部中斷
TIM0init();//初始化定時器
InitLcd(); //初始化液晶
DelayMs(15);
sprintf(Test1," haixiang MCU "); //顯示第一行固定信息
ShowString(0,Test1);
sprintf(TimeNum,"Code ");//顯示第二行固定信息
ShowString(1,TimeNum);
while(1)//主循環
{
if(irok) //如果接收好了進行紅外處理
{
Ircordpro();
irok=0;
}
if(irpro_ok) //如果處理好後進行工作處理,如按對應的按鍵後顯示對應的數字等
{
Ir_work();
}
}
}
㈡ 51單片機紅外解碼C程序
單片機採用外部中斷P3.3管腳和紅外接收頭的信號線相連,中斷方式為邊沿觸發方式。並用定時器0計算中斷的間隔時間,來區分前導碼、二進制的「1」、「0」碼。並將8位操作碼提取出來在數碼管上顯示。
// 解碼值在Im[2]中,當IrOK=1時解碼有效。
/* 51單片機紅外遙控解碼程序 */
//用遙控器對准紅外接收頭,按下遙控器按鍵,在數碼管前兩位上就會顯示對應按鍵的編碼
#include <reg52.h>
#define uchar unsigned char
sbit la=P2^6;
sbit wela=P2^7;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar f;
#define Imax 14000 //此處為晶振為11.0592時的取值,
#define Imin 8000 //如用其它頻率的晶振時,
#define Inum1 1450 //要改變相應的取值。
#define Inum2 700
#define Inum3 3000
unsigned char Im[4]={0x00,0x00,0x00,0x00};
uchar show[2]={0,0};
unsigned long m,Tc;
unsigned char IrOK;
void delay(uchar i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
void display()
{
la=0;
P0=table[show[0]];
la=1;
la=0;
wela=0;
P0=0xfe;
wela=1;
wela=0;
delay(5);
P0=table[show[1]];
la=1;
la=0;
P0=0xfd;
wela=1;
wela=0;
delay(5);
} //外部中斷解碼程序
void intersvr1(void) interrupt 2 using 1
{
Tc=TH0*256+TL0; //提取中斷時間間隔時長
TH0=0;
TL0=0; //定時中斷重新置零
if((Tc>Imin)&&(Tc<Imax))
{
m=0;
f=1;
return;
} //找到啟始碼
if(f==1)
{
if(Tc>Inum1&&Tc<Inum3)
{
Im[m/8]=Im[m/8]>>1|0x80; m++;
}
if(Tc>Inum2&&Tc<Inum1)
{
Im[m/8]=Im[m/8]>>1; m++; //取碼
}
if(m==32)
{
m=0;
f=0;
if(Im[2]==~Im[3])
{
IrOK=1;
}
else IrOK=0; //取碼完成後判斷讀碼是否正確
}
//准備讀下一碼
}
}
/*演示主程序*/
void main(void)
{
unsigned int a;
m=0;
f=0;
EA=1;
IT1=1;EX1=1;
TMOD=0x11;
TH0=0;TL0=0;
TR0=1;//ET0=1;
while(1)
{
if(IrOK==1)
{
show[1]=Im[2] & 0x0F; //取鍵碼的低四位
show[0]=Im[2] >> 4;
IrOK=0;
}
for(a=100;a>0;a--)
{
display();
}
}
}
解碼程序這個就能實現
㈢ 求單片機紅外遙控解碼識別長按和短按鍵的C語言例子
以NEC格式為例:
按鍵一次: 依次發送 引導碼 + 地址 + 地址取反 + 數據 + 數據取反
長按鍵: 隔110ms左右發一次引導碼(重復),並不帶任何數據(全部為高電平)
所以根據這個特點可以識別長按鍵:
程序接收一幀數據後,提取出地址和數據,然後判斷
......
//有地址和數據的,為一次按鍵
.....
//地址和數據為空的,為重復按鍵
if((ir_addr_code==0xffff)&&(ir_origin_data==0xff)&&(ir_data==0xff))
{
repeat=1;
key= last_key;
}
㈣ 知道了紅外遙控的編碼(16位1101 0011 1001 0010)請問怎樣在單片機里解碼
;遙控器讀碼程序(晶振為11.0592),該程序能讀出遙控器的控制碼,並通過LED顯示出來
;OMEN 2005/1/16於TCL
;***************************************************************
A_BIT EQU 20H ;數碼管個位數存放內存位置
B_BIT EQU 21H ;數碼管十位數存放內存位置
NO_OUT EQU 24H ;最終控制號碼存放單元
A_NO EQU 25H ;數碼管個位數對應代碼存放內存位置
B_NO EQU 26H ;數碼管十位數對應代碼存放內存位置
;22H,23H為控制碼及其反碼的存放單元
;*******************<<主程序>>***********************************
ORG 0000H
AJMP 0030H
ORG 0003H ;外部中斷P3.2腳INT0入口地址
AJMP INT ;轉入外部中斷服務子程序(解碼程序)
ORG 0030H
AJMP MAIN ;轉入主程序
;***************************************************************
MAIN: MOV NO_OUT,#0H
SETB EA ;打開CPU總中斷請求
SETB IT0 ;設定INT0的觸發方式為脈沖負邊沿觸發
SETB EX0 ;打開INT0中斷請求
LOOP: MOV A,NO_OUT;將按鍵的鍵值通過P1口的8個LED顯示出來!
CPL A ;由於P1發光二極體顯示的是電平的反狀態,所以取反
MOV P1,A ;發光二極體顯示輸出
LCALL DISPLAY;LED數碼管顯示輸出
AJMP LOOP;循環
;********************<<中斷接受遙控程序>>************************
;以下為進入P3.2腳外部中斷子程序,也就是解碼程序
INT:
PUSH ACC
PUSH PSW ;將PSW和ACC推入堆棧保護
CLR EA ;暫時關閉CPU的所有中斷請求
MOV R6,#10
SB: LCALL DL865;調用865微秒延時子程序
JB P3.2,EXIT;延時865微秒後判斷P3.2腳是否出現高電平如果有就退出解碼程序
DJNZ R6, SB;重復10次,目的是檢測在8650微秒內如果出現高電平就退出解碼程序
;以上完成對遙控信號的9000微秒的初始低電平信號的識別。
JNB P3.2, $ ;等待高電平避開9毫秒低電平引導脈沖
LCALL DL4737 ;延時4.74毫秒避開4.5毫秒的結果碼
MOV R7,#16;忽略前26位系統識別碼
JJJJA:JNB P3.2,$;等待地址碼第一位的高電平信號
LCALL DL865;高電平開始後用865微秒的時間尺去判斷信號此時的高低電平狀態
MOV C,P3.2;將P3.2引腳此時的電平狀態0或1存入C中
JNC UUUA;如果為0就跳轉到UUUA
LCALL DL1000;檢測到高電平1的話延時1毫秒等待脈沖高電平結束
UUUA: DJNZ R7,JJJJA
MOV R1,#22H ;設定22H為起始RAM區
MOV R2,#2;接收從22H到23H的2個內存,用於存放操作碼和操作反碼
PP: MOV R3,#8;每組數據為8位
JJJJ: JNB P3.2,$;等待地址碼第一位的高電平信號
LCALL DL865;高電平開始後用865微秒的時間尺去判斷信號此時的高低電平狀態
MOV C,P3.2;將P3.2引腳此時的電平狀態0或1存入C中
JNC UUU;如果為0就跳轉到UUU
LCALL DL1000;檢測到高電平1的話延時1毫秒等待脈沖高電平結束
UUU: MOV A,@R1;將R1中地址的給A
RRC A;將C中的值0或1移入A中的最低位
MOV @R1,A;將A中的數暫時存放在R1數值的內存中
DJNZ R3,JJJJ;接收滿8位換一個內存
INC R1;對R1中的值加1,換下一個RAM
DJNZ R2,PP ;接收完8位數據碼和8位數據反碼,存放在22H/23H中
MOV A,22H
CPL A;對22H取反後和23H比較
CJNE A,23H,EXIT;如果不等表示接收數據發生錯誤,放棄
MOV A,22H
MOV NO_OUT,A
;LCALL EEPROM_C ;清除以前的保存的碼
;LCALL DL4737
;LCALL EEPROM_W ;把碼存在單片機內部的EEPROM里
;LCALL DL4737
CLR P3.6;蜂鳴器鳴響-嘀嘀嘀-的聲音,表示解碼成功
LCALL DL4737
LCALL DL4737
LCALL DL4737
SETB P3.6;蜂鳴器停止
lcall DL4737
EXIT: SETB EA ;允許中斷
POP PSW
POP ACC ;將PSW和ACC推入堆棧保護
RETI ;退出解碼子程序
;*******************<<LED數碼管顯示子程序>>**********************
DISPLAY:
MOV A,NO_OUT ;將NO_OUT分成個位和16位
ANL A,#0FH ;取低四位放在a_bit
MOV A_BIT,A ;個位
MOV A,NO_OUT ;
RR A
RR A
RR A
RR A ;四次移動,把高四位移到低四位
ANL A,#0FH;取高四位放在B_bit
MOV B_BIT,A ;個位在b
MOV DPTR,#NUMTAB ;指定查表啟始地址
MOV A,A_BIT ;取個位數
MOVC A,@A+DPTR ;查個位數的7段代碼
MOV A_NO,A
MOV A,B_BIT ;取十位數
MOVC A,@A+DPTR ;查十位數的7段代碼
MOV B_NO,A
DPLOP:MOV A,A_NO
MOV P0,A ;送出個位的7段代碼
;SETB P2.1;關閉十位顯示,防止鬼影
CLR P2.0 ;開個位顯示
LCALL DL40 ;顯示4737微秒
SETB P2.0;關閉個位顯示,防止鬼影
MOV A,B_NO
MOV P0,A ;送出十位的7段代碼
CLR P2.1 ;開十位顯示
LCALL DL40 ;顯示4737微秒
SETB P2.1;關閉十位顯示,防止鬼影
RET
;**********************<<延時程序>>******************************
DL865: MOV R4,#12 ; 1.09*(2R5+4)*R4+2延時子程序1,精確延時865微秒
D1: MOV R5,#31
DJNZ R5,$
DJNZ R4,D1
RET
DL4737: MOV R4,#12 ;延時子程序2,精確延時4737微秒
D2: MOV R5,#179
DJNZ R5,$
DJNZ R4,D2
RET
DL1000: MOV R4,#17;延時程序3,精確延時1000微秒
D3: MOV R5,#25
DJNZ R5,$
DJNZ R4,D3
RET
DL40: MOV R4,#1;延時程序4,精確延時40/17微秒
D4: MOV R5,#1
DJNZ R5,$
DJNZ R4,D4
RET
;****************************************************************
;如果是共陽數碼管的顯示代碼 1-F 16個代碼
NUMTAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH ;STC新板的
END
㈤ 單片機紅外遙控器解碼程中,所有按鍵的地址碼都相同嗎
單片機紅外遙控器編碼一般由引導碼+地址基桐橋碼(16位)+命令碼(16位)組成,在普搏猛通的遙控器上所有的按鍵只是命令輪燃碼不同,地址碼是不變的
㈥ 單片機控制紅外遙控編碼解碼中定時器和外部中斷的作用是什麼紅外遙控編碼解碼的大致步驟是什麼
同時使用上定時器 跟 外中斷 的紅外程序,只有解碼程序。而且該方式,只能解析 使用不同時間長度代表數據「0」、「1」 的波形(如數據『1』的時間長度 2倍於數據『0』的時間)。
解析原理:外部中斷接 紅外輸入,當有 紅外信號的時候,該引腳會有波形輸入(N多下降沿),觸發外部中斷,通過記錄 每2次中斷的時間間隔,可以判斷此段時間對應的數據(0/1)。一般「數據」長度為32位數據
注意點:
①初次產生外中斷的時候,並無 時間記錄,不需要進行時間判斷;
②第二次中斷與第一次中斷 之間 的時間,是 紅外的引導碼,該時間一般多倍於數據時間(一般為ms級時間);
③第三次中斷與第二次中斷的時間,即為 第一個數據 的時間;
④第34次中斷與第33次中斷的時間間隔,即為 第32個數據的時間;
⑤後面 可能存在 停止位,是否存在,由遙控器決定;不過,一般都直接忽略該位,除非該位是由自己製作的遙控器 發出 的校驗位;
⑥後面 可能存在 連發碼,是否存在,由遙控器決定;
另外:一般紅外數據的每個位元組都是LSB在前,MSB在後的( 低位先發,高位後發)
軟體要處理以下情況:
①干擾的處理,有些紅外接收頭不僅僅對38KHz頻率光有反應,可能對人體紅外、日光燈紅外一樣有反應,那就存在干擾。如果它只產生一次干擾,就會使系統卡在引導碼接收階段;
②引導碼時間過短、過長 的處理;
③接收數據位數不足的處理;
④完成32位數據接收後,處理接收爛尾:後面不會有中斷(如果需接收停止位、連發碼,就增加對應數據長度),需要停止計時。
⑤進行數據校對,一般第一位元組跟第二位元組互為反碼,第三位元組跟第四位元組互為反碼,而且第一位元組 代表 一個地址、一個密碼,只有地址、密碼正確,才能算合法的操作。