📄 infraredray_basic_change.c
字号:
/*-------------------------
红外遥控嵌入式系统设计
By zheyu
Copyright 2008/12/27
All rights reserved.
----------------------------*/
/*$$$$$$$$$$$$$$$$$$$$$$$$$
功能:(按K1(P3.2)切换功能)
1、 使用配发的红外遥控器进行测试,能够识别遥控器发送出来的控制信号,用数码管显示(采用俱乐部长虹遥控器,P2为段码(P2.7接dp),P1为位码(P0.1接1),红外接收入器
接P3.3), LED接,用于确认接收成功。
2、 使用实验板上的按键实现一个红外遥控器,能够实现电视机的遥控,K2接P1.3(用于加1,选频道),K3接P1.2(用于确认发射),P3.7接红外发射器。
3、 使用实验板上的按键实现一个红外遥控接收器,能够实现对另外一组实验板的红外控制。(一机为SFR(发送状态),一机为CIE(接收状态),SFR机K2用于加1选数,
K3用于确认发送,CIE机接收仅可。
4、 学习型遥控器功能,K2用于更改要替换的频道,K3用于发射,K4接P1.1,用于表示现在开始接收,进入进入学习状态, LED,绿灯亮表示进入学习状态,闪两下表示学习成功
$$$$$$$$$$$$$$$$$$$$$$$$$$*/
#include <absacc.h>
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit output=P3^7;//发送
sbit sign=P1^5;//LED标志
sbit Inttrupt1=P3^3;//中断1
sbit Inttrupt0=P3^2;//中断0
sbit AddOne=P1^3;//加1操作,K2
sbit TransSure=P1^2;//确认发射操作,K3
sbit P00=P0^0;
sbit P01=P0^1;
sbit P02=P0^2;
sbit P03=P0^3;
sbit P04=P0^4;
sbit P05=P0^5;
sbit P06=P0^6;
sbit P07=P0^7;
//十个数 {0,1,2,3,4,5,6,7,8,9,空}
int numbers[11]={0xc0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF};
// 状态提示字符(用于提示,如CHL(channel)){L,H,C,O,S,I,A,E,F}
int Chars[9]={0xc7,0x89,0xc6,0xc0,0x92,0xf9,0x88,0x86,0x8e};
char StoreCodes[10][2]={{0x40,0x00},
{0x40,0x01},
{0x40,0x02},
{0x40,0x03},
{0x40,0x04},
{0x40,0x05},
{0x40,0x06},
{0x40,0x07},
{0x40,0x08},
{0x40,0x09}
};//用于储存不同的频道码
int buffer[6];//用于储存数码管显示的段码
int buffer1[2];//用于储存收到的值(0功能)仅需存储用户码和数据码
int buffer2[2];//用于储存第几个段码(即段码实际显示值)(2功能)仅变最后两位
int Model;
int channel;//当前为第几个频道
int sign1;//B代替sign1用于学习功能的中断开关
void InitCom(void);//初始化
void ComOutChar(void);//发送数据
void OutOne(void);
void OutZero(void);
void PreCode(void);
void delay528us(void);
void Delay8_44ms(void);
void Delay4_22ms(void);
void Delay3_5ms(void);
void Delay800us(void);
void Delay1ms(uint z);
void Display(void);
void Delay100us(void);
void reBuffer(void);
void reBuffer(void)
{
//使用配发的红外遥控器进行测试,能够识别遥控器发送出来的控制信号,用数码管显示
if(Model==0)
{
buffer[0]=numbers[buffer1[0]];
buffer[1]=numbers[0];
buffer[2]=numbers[10];
buffer[3]=Chars[0];//CHL(channel)
buffer[4]=Chars[1];
buffer[5]=Chars[2];
}
//使用实验板上的按键实现一个红外遥控器,能够实现电视机的遥控
if(Model==1)
{
buffer[0]=numbers[channel];//此处仅设计了0-9十个频道
buffer[1]=numbers[0];
buffer[2]=numbers[10];
buffer[3]=Chars[0];//COL(Control)
buffer[4]=Chars[3];
buffer[5]=Chars[2];
}
//使用实验板上的按键实现一个红外遥控接收器,能够实现对另外一组实验板的红外控制。
if(Model==2)//Transfer
{
buffer[0]=numbers[buffer2[0]];
buffer[1]=numbers[buffer2[1]];
buffer[2]=numbers[10];
buffer[3]=Chars[7];//SFE(transfer)
buffer[4]=Chars[8];
buffer[5]=Chars[4];
}
if(Model==3)//Recieve
{
buffer[0]=buffer[0];//直接接收到的是段码
buffer[1]=buffer[1];
buffer[2]=numbers[10];
buffer[3]=Chars[7];//CIE(recieve)
buffer[4]=Chars[5];
buffer[5]=Chars[2];
}
//学习型红外遥控器
if(Model==4)
{
buffer[0]=numbers[channel];
buffer[1]=numbers[0];
buffer[2]=numbers[10];
buffer[3]=Chars[6];//LEA(learn)
buffer[4]=Chars[7];
buffer[5]=Chars[0];
}
}
void Display(void)
{
/*%%%%%%%%%%%%%%%%%%%%%%%
P2=段码
P0=位码
//%%%%%%%%%%%%%%%%%%%%%%*/
int i;
P0=0xfe;
for(i=0;i<6;i++)
{
P2=buffer[i];
P0=P0<<1;
P0=P0|0x01;
Delay100us();
}
}
void main(void)
{
// uint TempCyc;
/* while(1)
{
sign=1;
Delay8_44ms();
sign=0;
Delay4_22ms();
}*/
InitCom();
EA=1;//允许CPU中断
IT0=0;//INT0下降沿有效
EX0=1;//开INT0中断
EX1=0;//关INT1中断,在需要的时候打开
Model=0;
sign1=0;
// ComOutChar();
while(1)
{
if(Model==0)
{
EX1=1;
}
if(Model==1)//对电视机遥控
{
EX1=0;
if(!AddOne)//加1命令
{
Delay8_44ms();
while(!AddOne);
if(channel++==0x09)
{
channel=0;
}
}
if(!TransSure)
{
Delay8_44ms();
P2=0xff;
while(!TransSure);
ComOutChar();
}
}
if(Model==2)//P3.2(外部中断)接K1,P3.3接接收器,P1.3接K2(加1),P1.4接K3(发射确认)
{
EX1=0;
if(!AddOne)//加1命令
{
Delay8_44ms();
while(!AddOne);
if(buffer2[0]++==0x09)
{
buffer2[0]=0;
if(buffer2[1]++==0x09)
buffer2[1]=0;
}
}
if(!TransSure)
{
Delay8_44ms();
P2=0xff;
while(!TransSure);
ComOutChar();
}
}
if(Model==3)
{
EX1=1;
}
if(Model==4)//学习功能,P3.2(外部中断)接K1,P3.3接接收器,P1.3接K2(加1),P1.4接K3(学习开始确认)
{
if(!sign1) EX1=0;
else EX1=1;
if(!AddOne)//加1命令
{
Delay8_44ms();
while(!AddOne);
if(channel++==0x09)
{
channel=0;
}
}
if(!TransSure)
{
Delay8_44ms();
while(!TransSure);
sign=0;
sign1=1;
}
}
reBuffer();//更改缓冲区(段码)的值
Display();//显示
}
}
//外部中断0,用于切换不同的模式(如通信、学习等状态),同时通信的两台机子应保持相同的状态
void INT0Fun(void) interrupt 0
{
P2=0xff;
Delay8_44ms();
if(!Inttrupt0)
{
Model++;//调至下一状态
if(Model==5)//四种状态切换完毕,回到第一种状态
Model=0;
while(!Inttrupt0);
}
}
//INT1中断,当数据发送过来时,会中断
void INT1Fun(void) interrupt 2
{
uchar IRCode[4],IROK;//IRCode用于储存接收的数据,IROK用于计数接收的数据个数。
uint TempCyc,TempCycB,TempCycA,si;
EX1=0;//外部中断0关闭
P2=0xff;
IROK=0;
si=0;
Delay3_5ms();//延时7ms
Delay3_5ms();
if(!Inttrupt1)//若经过延时,其仍为低电平,表明可能不是干扰,要处理,若为高电平,表明是干扰,跳到ENDCHK,此时由于IDOK=0,故其不会进行操作,仅会跳出该中断
{
Delay3_5ms();
for(TempCycA=0;TempCycA<4;TempCycA++)//用于计数接收到了几个有效数据,此处是要接收两个
{
if(!si) Delay800us();
if(Inttrupt1||si)//若经过延迟,其还为0,则表明其引导码前半部分太长——超时,故其跳出,若为1,表明其已有电平拉高,引导码已进入后半部分
{
si=0;
for(TempCyc=0;TempCyc<300;TempCyc++)
if(!Inttrupt1) break ;//若为0,则表明已经开始传数据了,则跳出该循环,若为1表明还没有开始(引导码还没有结束)
if(TempCyc<300)//若是没有<300,则表明其不是在P3_2口为0时跳出,而是超时了,此时就要跳出了。
{
for(TempCyc=0;TempCyc<8;TempCyc++)//接收一个有数据的8位
{
//此时应有一个超时的判定
while(!Inttrupt1);//等待P3_2为1,就是前半个高位已结束,开始用后面的低电平的长度来判断该位为0还是1
Delay800us();//跳过一个0位的0电平的长度
IRCode[TempCycA]=IRCode[TempCycA]>>1;//将当前所接收到的数据右移一位,将已经确定的数据保存起来。
if(Inttrupt1)//当延迟750us后,若其仍为低则其已释放又开始下一个数据了,若为高则其已释放,为1
{
IRCode[TempCycA]=IRCode[TempCycA]|0x80;//将当前已经成功确定为1的位置为1
for(TempCycB=0;TempCycB<300;TempCycB++)
if(!Inttrupt1)
{
si=1;
break;
}//若又有数据来(0电位),则跳出该循环去接收下一位。
if(TempCycB>300)//若接收完一位,之后又没有在规定时间内收到,则超时,退出。
goto endchk;
}
}
}
else
goto endchk;
}
else
goto endchk;
IROK++;//当自定码和数据码都完成时加2
}
}
endchk://若成功发送完,这部分为显示成功,否则这时为超时
if(IROK==4)//若不为2,表明没有发送成功,是超时跳到这里,退出
{
if(Model==0)//若为判断遥控器信号状态,则接收到的值用于更改缓冲区的值
{
buffer1[0]=IRCode[2];
sign=0;
Delay1ms(500);
sign=1;
}
if(Model==3)//若为红外遥控接收器,则接收到的值用于更改缓冲区的值
{
buffer[0]=IRCode[0];
buffer[1]=IRCode[2];
sign=0;
Delay1ms(500);
sign=1;
} //判断用户码与用户反码,数据码与数据反码是否是互反的。
if(Model==4)//若为学习功能,则接收到的值用于更改当前的频道值
{
if(channel==0)
{
StoreCodes[0][0]=IRCode[0];
StoreCodes[0][1]=IRCode[2];
}
if(channel==1)
{
StoreCodes[1][0]=IRCode[0];
StoreCodes[1][1]=IRCode[2];
}
if(channel==2)
{
StoreCodes[2][0]=IRCode[0];
StoreCodes[2][1]=IRCode[2];
}
if(channel==3)
{
StoreCodes[3][0]=IRCode[0];
StoreCodes[3][1]=IRCode[2];
}
if(channel==4)
{
StoreCodes[4][0]=IRCode[0];
StoreCodes[4][1]=IRCode[2];
}
if(channel==5)
{
StoreCodes[5][0]=IRCode[0];
StoreCodes[5][1]=IRCode[2];
}
if(channel==6)
{
StoreCodes[6][0]=IRCode[0];
StoreCodes[6][1]=IRCode[2];
}
if(channel==7)
{
StoreCodes[7][0]=IRCode[0];
StoreCodes[7][1]=IRCode[2];
}
if(channel==8)
{
StoreCodes[8][0]=IRCode[0];
StoreCodes[8][1]=IRCode[2];
}
if(channel==9)
{
StoreCodes[9][0]=IRCode[0];
StoreCodes[9][1]=IRCode[2];
}
sign=0;
Delay1ms(500);
sign=1;
Delay1ms(200);
sign=0;
Delay1ms(500);
sign=1;
sign1=0;
} //判断用户码与用户反码,数据码与数据反码是否是互反的。
}
// EX1=1;
}
//向串口输出一个字符
void ComOutChar(void) using 0
{
// int i;
if(Model==1)//电视控制
{
while(1)
{
//这里似乎不支持用一个变量作为索引
if(channel==0) B=StoreCodes[0][0];
if(channel==1) B=StoreCodes[1][0];
if(channel==2) B=StoreCodes[2][0];
if(channel==3) B=StoreCodes[3][0];
if(channel==4) B=StoreCodes[4][0];
if(channel==5) B=StoreCodes[5][0];
if(channel==6) B=StoreCodes[6][0];
if(channel==7) B=StoreCodes[7][0];
if(channel==8) B=StoreCodes[8][0];
if(channel==9) B=StoreCodes[9][0];
// B=StoreCodes[4][0];
PreCode();
#pragma ASM
;发送原码
jb B.0,Out101
lcall OutZero
ajmp next10
Out101:
lcall OutOne
next10:
jb B.1,Out111
lcall OutZero
ajmp next11
Out111:
lcall OutOne
next11:
jb B.2,Out121
lcall OutZero
ajmp next12
Out121:
lcall OutOne
next12:
jb B.3,Out131
lcall OutZero
ajmp next13
Out131:
lcall OutOne
next13:
jb B.4,Out141
lcall OutZero
ajmp next14
Out141:
lcall OutOne
next14:
jb B.5,Out151
lcall OutZero
ajmp next15
Out151:
lcall OutOne
next15:
jb B.6,Out161
lcall OutZero
ajmp next16
Out161:
lcall OutOne
next16:
jb B.7,Out171
lcall OutZero
ajmp next17
Out171:
lcall OutOne
next17:
;发送反码
jnb B.0,Out100
lcall OutZero
ajmp next1001
Out100:
lcall OutOne
next1001:
jnb B.1,Out110
lcall OutZero
ajmp next1101
Out110:
lcall OutOne
next1101:
jnb B.2,Out120
lcall OutZero
ajmp next1201
Out120:
lcall OutOne
next1201:
jnb B.3,Out130
lcall OutZero
ajmp next1301
Out130:
lcall OutOne
next1301:
jnb B.4,Out140
lcall OutZero
ajmp next1401
Out140:
lcall OutOne
next1401:
jnb B.5,Out150
lcall OutZero
ajmp next1501
Out150:
lcall OutOne
next1501:
jnb B.6,Out160
lcall OutZero
ajmp next1601
Out160:
lcall OutOne
next1601:
jnb B.7,Out170
lcall OutZero
ajmp next1701
Out170:
lcall OutOne
next1701:
#pragma ENDASM
if(channel==0) B=StoreCodes[0][1];
if(channel==1) B=StoreCodes[1][1];
if(channel==2) B=StoreCodes[2][1];
if(channel==3) B=StoreCodes[3][1];
if(channel==4) B=StoreCodes[4][1];
if(channel==5) B=StoreCodes[5][1];
if(channel==6) B=StoreCodes[6][1];
if(channel==7) B=StoreCodes[7][1];
if(channel==8) B=StoreCodes[8][1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -