1. 求一個單片機紅外遙控器控制設計的源程序
程序太長,須仔細研究。
#definemain_GLOBALS
#include<reg51.h>
#include"main.h"
#include"SAA3010.h"
unsignedcharcounter;
unsignedchartemp;
sbitP2_0=0xA0;
sbitP2_1=0xA1;
sbitP2_2=0xA2;
sbitP2_3=0xA3;
voiddecode_init(void)
{
load_code_detected=0;
repeat_code_detected=0;
decode_error=0;
temp1=0;
temp2=0;
temp3=0;
temp4=0;
TH1=0;
TL1=0;
TR1=0;
}
voidmain(void)
{
EX0=1;
IT0=1;
TMOD=0x11;
ET0=1;
TH0=128;
TL0=0;
TR0=1;
P0=0;
TH1=0;
TL1=0;
decode_init();
EA=1;
counter=0;
data_available=0;
while(1)
{
if(data_available==1)
{
if(key_code==01)//display"1"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0xf9;
}
if(key_code==0x02)//display"2"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0xa4;
}
if(key_code==0x03)//display"3"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0xb0;
}
if(key_code==0x04)//display"4"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0x99;
}
if(key_code==0x05)//display"5"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0x92;
}
if(key_code==0x06)//display"6"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0x82;
}
if(key_code==0x07)//display"7"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0xf8;
}
if(key_code==0x08)//display"8"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0x80;
}
if(key_code==0x09)//display"9"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0x90;
}
if(key_code==0x00)//display"0"
{
P2_0=0;//選中四個數碼管
P2_1=0;
P2_2=0;
P2_3=0;
P0=0xc0;
}
data_available=0;
}
}
}
//**********************************************************************************************************************
voidkey_isr(void)interrupt0
{
EX0=0;//立即關閉外部中斷,轉為查詢方式解碼
led=0;//開LED表示收到紅外信號
temp=SAA3010_decode();//解碼
if(temp==1)gotokey_isr_exit;
counter=0;
key_isr_exit:
decode_init();
led=1;
EX0=1;
}
voidTimer0_isr(void)interrupt1
{
counter++;
if(counter>3)
{
if(led==0)led=1;
counter=0;
}
ET0=1;
}
#defineSAA3010_GLOBALS
#include<reg51.h>
#include"SAA3010.h"
#include"main.h"
//===========================================================================================================
//該函數的作用是每調用一次就在temp1-4組成的32bit長度的最低位上移入
//一個0或者1,數據由bitdata確定
voidSAA3010_cycle_data(unsignedcharbitdata)
{
temp4=temp4<<1;
if((temp3&0x80)==1)temp4=temp4|0x01;
elsetemp4=temp4&0xfe;
temp3=temp3<<1;
if((temp2&0x80)==1)temp3=temp3|0x01;
elsetemp3=temp3&0xfe;
temp2=temp2<<1;
if((temp1&0x80)==1)temp2=temp2|0x01;
elsetemp2=temp2&0xfe;
temp1=temp1<<1;
if(bitdata==1)temp1=temp1|0x01;
elsetemp1=temp1&0xfe;
}
//===========================================================================================================
//解碼出錯返回1,對則返回0
unsignedcharSAA3010_decode(void)
{
//-----------------------------------------------------------------------------------------------------------
unsignedcharcount=0;
TR1=1;//啟動計時
while(1)
{
while(ir_receive==0);//等待電平變高,不需要超時監測
TR1=0;//高電平(對發射電路而言)測試結束
high_level_time=TH1*256+TL1;//記錄高電平的數據
//-----------------------------------------------------------------------------------------------------------
TH1=0; TL1=0;TR1=1;//啟動對低電平的測試
//-----------------------------------------------------------------------------------------------------------
//處理低電平
if((high_level_time<750)||(high_level_time>1800))return1;//不是合格的電平
if((high_level_time>750)&&(high_level_time<1000)){SAA3010_cycle_data(0);count+=1;}//移入一個0
if((high_level_time>1500)&&(high_level_time<1800)){SAA3010_cycle_data(0);SAA3010_cycle_data(0);count+=2;}//移入兩個0
while(ir_receive==1)//等待電平變低
{
if(TH1>0x08)break;//高電平超時,正常情況下是測試結束,異常時則是出錯
}
TR1=0;//低電平(對發射電路而言)測試結束
if(TH1>0x08){break;}
low_level_time=TH1*256+TL1;//保存低電平的數據
TH1=0; TL1=0; TR1=1; //為增加計時的准確性,數據的處理都是在計時過程里
//-----------------------------------------------------------------------------------------------------------
//處理高電平
if((low_level_time<750)||(low_level_time>1800))return1;//不是合格的電平
if((low_level_time>750)&&(low_level_time<1000)){SAA3010_cycle_data(1);count+=1;}//移入一個0
if((low_level_time>1500)&&(low_level_time<1800)){SAA3010_cycle_data(1);SAA3010_cycle_data(1);count+=2;}//移入兩個0
}
if(count==26){SAA3010_cycle_data(1);count++;}
if(count!=27)return1;
led=0;
//提取按健信息
key_code=0;
if((temp1>>1)&0x01)key_code=key_code|0x01;
elsekey_code=key_code&0xfe;
if((temp1>>3)&0x01)key_code=key_code|0x02;
elsekey_code=key_code&0xfd;
if((temp1>>5)&0x01)key_code=key_code|0x04;
elsekey_code=key_code&0xfb;
if((temp1>>7)&0x01)key_code=key_code|0x08;
elsekey_code=key_code&0xf7;
if((temp2>>1)&0x01)key_code=key_code|0x10;
elsekey_code=key_code&0xef;
if((temp2>>3)&0x01)key_code=key_code|0x20;
elsekey_code=key_code&0xdf;
//提取系統信息
sys_code=0;
if((temp2>>5)&0x01)sys_code=sys_code|0x01;
elsesys_code=sys_code&0xfe;
if((temp2>>7)&0x01)sys_code=sys_code|0x02;
elsesys_code=sys_code&0xfd;
if((temp3>>1)&0x01)sys_code=sys_code|0x04;
elsesys_code=sys_code&0xfb;
if((temp3>>3)&0x01)sys_code=sys_code|0x08;
elsesys_code=sys_code&0xf7;
if((temp3>>5)&0x01)sys_code=sys_code|0x10;
elsesys_code=sys_code&0xef;
if((temp3>>7)&0x01)sys_code=sys_code|0x20;
elsesys_code=sys_code&0xdf;
data_available=1;
return0;
}
//===========================================================================================================
2. 基於51單片機的紅外遙控開關的C 程序
這個簡單就是一個解碼函靈敏而已!
int jiema()
{
unsigned int data,temp;
RESET:
for( i=0;i<8;i++ ) //**9ms
{
delay_nms(1);
if((PIND&0B00000100)==0B00000100 )
goto RESET; //是檢測在8毫秒內如果出現高電平就退出解碼程序
}
temp = 8000;
while( ( (PIND&0B00000100)==0B00000000 ) && (temp!=0) )
{temp--;}
// 等待4.5ms高電平的到來,避開9毫秒低電平引導脈沖
// temp--需0.25us, temp=8000可實現2ms延時,防止干擾脈沖造成的死機。
delay_nus(1804); //**4.5ms
for( j=0;j<4;j++)
{
for( i=0;i<8;i++ )
{
temp = 4000;
while( ((PIND&0B00000100)==0B00000000 ) && (temp!=0) )
{temp--;}
delay_nus(334);
if((PIND&0B00000100)==0B00000100 ) // 檢測到高電平1的話說明該位為1,延時1毫秒等待脈沖高電平結束
{
data |= (1<<i); // dataH= ~data dataL= data
delay_nus(379);
}
else data &= ~(1<<i); // 檢測到低電平0的話,說明該位為0,繼續檢測下一位
}
IR_BUF[j]=data;
}
if(IR_BUF[2] = ~IR_BUF[3]) //校驗
{
PORTA=IR_BUF[2];
delay_nms(500);
}
3. 單片機編程(紅外線遙控器)
這段程序的意思是將鍵值換算成ASCII碼字元表示;
0x30 表示ASCII碼的『0』,ASCII碼表裡面字元0的編號就是0x30;
0x37 的意思是當鍵值大於9時,鍵值用十六進制字元表示,0x37 實際上是『A』-10,『A』=0x41,『A』- 10 =0x37;比如鍵值是10,那麼輸出就是ASCII字元『A』;
4. 求51單片機紅外遙控程序
sbitIR_OUT=P3^2;
unsignedcharSigInfo[4];//存儲紅外按鍵編碼,SigInfo[2]為按鍵值
voidCmd_Require(void);
voidINT_Ext0()interrupt1//外部中斷0
{
u8i,j;
u16time=8000;
EA=0;
for(i=0;i<10;i++){
delay0_7ms();
if(IR_OUT){
EA=1;
return;
}
}
while(!IR_OUT);
delay2_5ms();
if(!IR_OUT){
EA=1;
return;
}
while(IR_OUT&&time){
time--;
}
time=8000;
for(i=0;i<4;i++){
for(j=0;j<8;j++){
SigInfo[i]>>=1;
while(!IR_OUT);
delay0_7ms();
if(IR_OUT){
SigInfo[i]|=0x80;
while(IR_OUT&&time){
time--;
}
time=8000;
}
}
}
Cmd_Require();
EA=1;
}
voidCmd_Require(void)
{
switch(SigInfo[2]){
case0x0c:
//此處代碼隨意
break;
case0x18:
//...
break;
//...
default:
break;
}
}
延時沒寫,因單片機而異的,要精確點才能解碼。
5. 單片機如何實現紅外遙控
以下文件是51單片機實現遙控解碼,通過數碼管顯示鍵碼的程序,P0口驅動數碼管段選,p2.6和p2.7為數碼管位選,接收頭連到P3.2口。此程序以通過驗證,可以直接編譯使用,另外還有一個繼電器和蜂鳴器的控制,不用可以屏蔽掉。
;********************************************************************************
;* 描述: *
;* 遙控鍵值讀取器 *
;* 數碼管顯示, P0口為數碼管的數據口 *
;* *
;********************************************************************************
;遙控鍵值解碼-數碼管顯示 *
;********************************************************************************/
#include <reg51.h>
#include <intrins.h>
void IR_SHOW();
void delay(unsigned char x);//x*0.14MS
void delay1(unsigned char ms);
void beep();
sbit IRIN = P3^2;
sbit BEEP = P3^7;
sbit RELAY= P1^3;
sbit GEWEI= P2^7;
sbit SHIWEI= P2^6;
unsigned char IRCOM[8];
unsigned char code table[16] =
{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
main()
{
IE = 0x81; //允許總中斷中斷,使能 INT0 外部中斷
TCON = 0x1; //觸發方式為脈沖負邊沿觸發
delay(1);
IRIN=1;
BEEP=1;
RELAY=1;
for(;;)
{
IR_SHOW();
}
} //end main
void IR_IN() interrupt 0 using 0
{
unsigned char i,j,k,N=0;
EA = 0;
I1:
for (i=0;i<4;i++)
{
if (IRIN==0) break;
if (i==3) {EA =1;return;}
}
delay(20);
if (IRIN==1) goto I1; //確認IR信號出現
while (!IRIN) //等 IR 變為高電平
{delay(1);}
for (j=0;j<4;j++)
{
for (k=0;k<8;k++)
{
while (IRIN) //等 IR 變為低電平
{delay(1);}
while (!IRIN) //等 IR 變為高電平
{delay(1);}
while (IRIN) //計算IR高電平時長
{
delay(1);
N++;
if (N>=30) {EA=1;return;}
}
IRCOM[j]=IRCOM[j] >> 1;
if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;}
N=0;
}//end for k
}//end for j
if (IRCOM[2]!=~IRCOM[3]) {EA=1;return;}
IRCOM[5]=IRCOM[2] & 0x0F;
IRCOM[6]=IRCOM[2] & 0xF0;
IRCOM[6]=IRCOM[6] >> 4;
beep();
EA = 1;
}
void IR_SHOW()
{
P0 = table[IRCOM[5]];
GEWEI = 0;
SHIWEI = 1;
delay1(4);
P0 = table[IRCOM[6]];
SHIWEI = 0;
GEWEI = 1;
delay1(4);
}
void beep()
{
unsigned char i;
for (i=0;i<100;i++)
{
delay(5);
BEEP=!BEEP;
}
BEEP=1;
}
void delay(unsigned char x)//x*0.14MS
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++) {}
}
}
void delay1(unsigned char ms)
{
unsigned char i;
while(ms--)
{
for(i = 0; i<120; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
6. 單片機C語言,紅外線遙控器,長按按鍵一直按下程序該怎樣區分呢
每種協議都是不一樣的,比如是日立的協議吧,就是通常說的一種,長按時發的第一個32位是對應的地址碼,命令碼及其反碼,但是按鍵一直按下時,則每隔固定時間發送的是重復碼,這個重復是固定一組編碼,與你按鍵對應的的地址和命令沒有任何關系,也就是說任何長按的重復碼都是一樣的;
而連續按則不同,按鍵松開後再按,則再次發送對應地址碼,命令碼及其反碼,不發送重復碼。
程序可以根據具體的編碼時序分支處理,若是連續按,則跳入一個分支,否則跳入長按處理,長按裡面判斷很簡單,則將上一次的結果重復一次即可。
7. 51單片機紅外遙控程序是什麼
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcden = P2^7;
sbit lcdrs = P2^6;
sbit lcdwr = P2^5;
sbit IR = P3^2;
uchar IRCOM[6];//數組,用於存儲紅外編碼
uchar code table1[] = "remote control";
uchar code table2[] = "CODE:";
void delayms(uchar x)// 延時x*0.14ms
{
uchar i;
while(x--)
for(i=0;i<13;i++){}
}
void delay(uchar x) //延時xms
{
uchar i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
/****************************LCD部分***********************************************/
void write_com(uchar com)
{
lcden = 0;
lcdrs = 0;
lcdwr = 0;
P0 = com;
delay(5);
lcden = 1;
delay(5);
lcden = 0; //別忘了lcden拉低
}
void write_date(uchar date)
{
lcden = 0;
lcdrs = 1;
lcdwr = 0;
P0 = date;
delay(5);
lcden = 1;
delay(5);
lcden = 0;
}
void lcd_init(void)
{
lcden = 0;
lcdrs = 0;
lcdwr = 0;
delay(5);
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
/*****************main()************************/
void main(void)
{
uchar count=0;
IR = 1;
lcd_init();
write_com(0x80);
while(table1[count]!='\0')
{
write_date(table1[count]);
count++;
delay(5);
}
count = 0;
write_com(0x80+0x40);
while(table2[count]!='\0')
{
write_date(table2[count]);
count++;
delay(5);
}
IE = 0x81; //開中斷
TCON = 0x01;//脈沖負邊沿觸發
while(1);
}
/*********************紅外中斷**************************/
void IR_time() interrupt 0
{
uchar i,j,TimeNum=0;//TimeNum用來計IR高電平次數 從而判斷是0還是1
EX0 = 0; //關閉中斷
delayms(5);
if(1 == IR)
{
EX0 = 1;
return;
}
while(!IR) //跳過9ms前導低電平
delayms(1);
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
while(IR) //跳過4.5ms的前導高電平
delayms(1);
while(!IR) //跳過0.56ms的低電平
delayms(1);
while(IR)
{
TimeNum++; //計時高電平時間從而判斷讀取的是0還是1
delayms(1);
}
if(TimeNum>=30)//按鍵按下時間過長 跳過
{
EX0 = 1;
return;
}
IRCOM[i] = IRCOM[i]>>1;
if(TimeNum >= 8) //8*0.14ms 這時讀取的是1;
{
IRCOM[i] = IRCOM[i]|0x80;
}
TimeNum = 0;
}
}
if(IRCOM[2]!=~IRCOM[3])//判斷八位數據和八位數據反碼是否相等
{
EX0 = 1;
return;
}
IRCOM[4] = IRCOM[2]&0x0f;//取低四位
IRCOM[5] = IRCOM[2]>>4; //IRCOM[5]取IRCOM[2]高四位
if(IRCOM[4] > 9) //轉換成字元
{
IRCOM[4] = IRCOM[4] + 0x37;
}
else
IRCOM[4] = IRCOM[4] + 0x30;
if(IRCOM[5] > 9)
{
IRCOM[5] = IRCOM[5] + 0x37;
}
else
IRCOM[5] = IRCOM[5] + 0x30;
delay(5);
write_com(0x80 + 0x40 + 5);
write_date(IRCOM[5]);
write_date(IRCOM[4]);
EX0 = 1; //重新開啟外部中斷
}
8. 這是一段51單片機的紅外遙控代碼,主要就是用了遙控器上的三個鍵。看不懂呀,求大神幫助注釋或解釋下
這就是一個紅外解碼程序,按標准來做就行了。普及一下紅外解碼知識:
採用脈寬調制的串列碼,以脈寬為0.565ms、間隔0.56ms、周期為1.125ms的組合表示二進制
的"0";以脈寬為0.565ms、間隔1.685ms、周期為2.25ms的組合表示二進制的"1,;上述"0"和
"1"組成的32位二進制碼經38kHz的載頻進行二次調制以提高發射效率,;達到降低電源功耗的
目的。然後再通過紅外發射二極體產生紅外線向空間發射,;遙控編碼是連續的32位二進制碼
組,其中前16位為用戶識別碼,能區別不同的電器設備,;防止不同機種遙控碼互相干擾。該
晶元的用戶識別碼固定為十六進制01H;後16位為8位操作碼(功能碼)及其反碼。
當一個鍵按下超過36ms,振盪器使晶元激活,將發射一組108ms的編碼脈沖,這108ms發射代碼
由一個起始碼(9ms),一個結果碼(4.5ms),低8位地址碼(9ms~18ms),高8位地址碼
(9ms~18ms),8位數據碼(9ms~18ms)和這8位數據的反碼(9ms~18ms)組成。如果鍵按下超
過108ms仍未松開,接下來發射的代碼(連發代碼)將僅由起始碼(9ms)和結束碼(2.5ms)
組成。
解碼的關鍵是如何識別"0"和"1",接收端而言,"0"是0.56ms的高+0.56ms的低。"1"是1.68ms
的高+0.56ms的低。所以可以根據高電平的寬度區別"0"和"1"。當高電平出現時開始延時,
0.56ms以後,若讀到的電平為低,說明該位為"0",反之則為"1",為了可靠起見,延時必須
比0.56ms長些,但又不能超過1.12ms,否則如果該位為"0",讀到的已是下一位的高電平,因此
取(1.12ms+0.56ms)/2=0.84ms最為可靠,一般取0.84ms左右均可。
9. 單片機做紅外遙控器的問題求教。。。
最簡單的就是通過定時器在P3.2腳輸出38K載波P3.1直接輸出串口數據
接收用3隻腳的紅外接收頭