红外发送一开始发送一段13。5ms的引导码,引导码由9ms的高电平和4。5ms的低电平组成,跟着引导码是系统码,系统反码,按键码,按键反码,如果按着键不放,则遥控器则发送一段重复码,重复码由9ms的高电平,2。25ms的低电平,跟着是一个短脉冲,本程序是免费给大家,版权所有,不得用于商业目的,如需用到本程序到商业上请与本人联系jiang_xi_sheng@163.com,经本人同意后方可用于商业目的,本程序经过试用,能解大部分遥控器的编码!
- #include "at89x52.h"
- #define NULL 0x00//数据无效
- #define RESET 0X01//程序复位
- #define REQUEST 0X02//请求信号
- #define ACK 0x03//应答信号,在接收数据后发送ACK信号表示数据接收正确,也位请求信号的应答信号
- #define NACK 0x04//应答信号,表示接收数据错误
- #define BUSY 0x05//忙信号,表示正在忙
- #define FREE 0x06//空闲信号,表示处于空闲状态
- #define READ_IR 0x0b//读取红外
- #define STORE_IR 0x0c//保存数据
- #define READ_KEY 0x0d//读取键值
- #define RECEIVE 0Xf400//接收缓冲开始地址
- #define SEND 0xfa00//发送缓冲开始地址
- #define IR 0x50//红外接收缓冲开始地址
- #define HEAD 0xaa//数据帧头
- #define TAIL 0x55//数据帧尾
- #define SDA P1_7
- #define SCL P1_6
- unsigned char xdata *buf1; //接受数据缓冲
- unsigned int buf1_length; //接收到的数据实际长度
- unsigned char xdata *buf2; //发送数据缓冲
- unsigned int buf2_length; //要发送的数据实际长度
- bit buf1_flag; //接收标志,1表示接受到一个数据帧,0表示没有接受到数据帧或数据帧为空
- bit buf2_flag; //发送标志,1表示需要发送或没发送完毕,0表示没有要发送的数据或发送完毕
- unsigned char state1,state2; //用来标志接收字符的状态,state1用来表示接收状态,state2用来表示发送状态
- unsigned char data *ir;
- union{
- unsigned char a[2];
- unsigned int b;
- unsigned char data *p1[2];
- unsigned int data *p2[2];
- unsigned char xdata *p3; //红外缓冲的指针
- unsigned int xdata *p4;
- }p;
- //union{ //
- // unsigned char a[2]; //
- // unsigned int b;
- // unsigned char data *p1[2];
- // unsigned int data *p2[2];
- // unsigned char xdata *p3;
- // unsigned int xdata *p4; //地址指针
- //}q; //
- union{
- unsigned char a[2];
- unsigned int b;
- }count;
- union{
- unsigned char a[2];
- unsigned int b;
- }temp;
- union{
- unsigned char a[4];
- unsigned int b[2];
- unsigned long c;
- }ir_code;
- union{
- unsigned char a[4];
- unsigned int b[2];
- unsigned long c;
- unsigned char data *p1[4];
- unsigned int data *p2[4];
- unsigned char xdata *p3[2];
- unsigned int xdata *p4[2];
- }i;
- unsigned char ir_key;
- bit ir_flag; //红外接收标志,0为缓冲区空,1为接收成功,2为缓冲溢出
- void sub(void);
- void delay(void);
- void ie_0(void);
- void tf_0(void);
- void ie_1(void);
- void tf_1(void);
- void tf_2(void);
- void read_ir(void);
- void ir_jiema(void);
- void ir_init(void);
- void ir_exit(void);
- void store_ir(void);
- void read_key(void);
- void reset_iic(void);
- unsigned char read_byte_ack_iic(void);
- unsigned char read_byte_nack_iic(void);
- bit write_byte_iic(unsigned char a);
- void send_ack_iic(void);
- void send_nack_iic(void);
- bit receive_ack_iic(void);
- void start_iic(void);
- void stop_iic(void);
- void write_key_data(unsigned char a);
- unsigned int read_key_data(unsigned char a);
- void ie0(void) interrupt 0{ie_0();}
- void tf0(void) interrupt 1{tf_0();}
- void ie1(void) interrupt 2{ie_1();}
- void tf1(void) interrupt 3{tf_1();tf_2();}
- void tf2(void) interrupt 5{ //采用中断方式跟查询方式相结合的办法解 码
- EA=0; //禁止中断
- if(TF2){ //判断是否是溢出还是电平变化产生的中断
- TF2=0; //如果是溢出产生的中断则清除溢出位,重 新开放中断退出
- EA=1;
- goto end;
- }
- EXF2=0; //清除电平变化产生的中断位
- *ir=RCAP2H; //把捕捉的数保存起来
- ir++;
- *ir=RCAP2L;
- *ir++;
- F0=1;
- TR0=1; //开启计数器0
- loop:
- TL0=0; //将计数器0重新置为零
- TH0=0;
- while(!EXF2){ //查询等待EXF2变为1
- if(TF0)goto exit; //检查有没超时,如果超时则退出
- };
- EXF2=0; //将EXF2清零
- if(!TH0) //判断是否是长低电平脉冲过来了
- { //不是长低电平脉冲而是短低电平
- if(F0)count.b++; //短脉冲数加一
- temp.a[0]=RCAP2H; //将捕捉数临时存放起来
- temp.a[1]=RCAP2L;
- goto loop; //返回继续查询
- }
- else{ //是低电平脉冲,则进行处理
- F0=0;
- *ir=temp.a[0]; //把连续的短脉冲总时间记录下来
- ir++;
- *ir=temp.a[1];
- ir++;
- *ir=RCAP2H; //把长电平脉冲时间记录下来
- ir++;
- *ir=RCAP2L;
- ir++;
- if(ir>=0xda) {
- goto exit; //判断是否溢出缓冲,如果溢出则失败退出
- }
- goto loop; //返回继续查询
- }
- exit:
- ir_flag=1; //置ir_flag为1表示接收成功
- end:
- ;
- }
- void rs232(void) interrupt 4{
- static unsigned char sbuf1,sbuf2,rsbuf1,rsbuf2; //sbuf1,sbuf2用来接收发送临时用,rsbuf1,rsbuf2用来分别用来存放接收发送的半字节
- EA=0; //禁止中断
- if(RI){
- RI=0; //清除接收中断标志位
- sbuf1=SBUF; //将接收缓冲的字符复制到sbuf1
- if(sbuf1==HEAD){ //判断是否帧开头
- state1=10; //是则把state赋值为10
- buf1=RECEIVE; //初始化接收地
- 址
- }
- else{
- switch(state1){
- case 10:sbuf2=sbuf1>>4; //把高半字节右移到的半字节
- sbuf2=~sbuf2; //把低半字节取反
- if((sbuf2&0x0f)!=(sbuf1&0x0f)) //判断接收是否正确
- { //接收错误,有可能接收的是数据帧尾,也有可能是接收错误
- if(sbuf1==TAIL) //判断是否接收到数据帧尾
- { //是接收到数据帧尾
- buf1=RECEIVE; //初始化接收的地址
- if(*buf1==RESET) //判断是否为复位命令
- {
- ES=0;
- sbuf2=SP+1;
- for(p.p1[0]=SP-0x10;p.p1[0]<=sbuf2;p.p1
- [0]++)*p.p1[0]=0;
- }
- state1=0; //将接收状态标志置为零,接收下一个数据帧
- buf1_flag=1; //置接收标志为1,表示已经接收到一个数据帧
- REN=0; //禁止接收
- }
- else
- { //不是接受到数据帧尾,表明接收错误
- state1=0; // 将接收状态标志置为零,重新接收
- buf1=RECEIVE; //初始化发送的地址
- *buf1=NACK; //把NACK信号存入接收缓冲里
- buf1_flag=1; //置标志位为1,使主程序能对接收错误进行处理
- REN=0; //禁止接收
- }
- }
- else
- { //接收正确
- rsbuf1=~sbuf1; //按位取反,使高半字节变原码
- rsbuf1&=0xf0; //仅保留高半字节,低半字节去掉
- state1=20; //将状态标志置为20,准备接收低半字节
- }
- break;
- case 20:sbuf2=sbuf1>>4; //把高半字节右移到的半字节
- sbuf2=~sbuf2; //将低半字节取反
- if((sbuf2&0x0f)!=(sbuf1&0x0f)) //判断接收是否正确
- { //接受错误
- state1=0; // 将接收状态标志置为零,重新接收
- buf1=RECEIVE; //初始化接收的地址
- *buf1=NACK; //把NACK信号存入发送缓冲里
- buf1_flag=1; //置标志位为1,使主程序能对接收错误进行处理
- REN=0; //禁止接收
- }
- else
- {
- sbuf1&=0x0f; //仅保留低半字节,去掉高半字节
- rsbuf1|=sbuf1; //高低半字节合并
- *buf1++=rsbuf1; //将接收的数据保存至接收缓冲里,并且数据指针加一
- buf1_length++; //接收数据长度加一
- state1=10; //将state1置为10,准备接收下个字节的高半字节
- }
- break;
- }
- }
- }
- else{
- TI=0; //清除发送中断标志
- if(buf2_length) //判断发送长度是否为零
- { //发送长度不为零
- if(state2==0) //判断是否发送高半字节
- { //发送高半字节
- sbuf2=*buf2; //将要发送的字节送到sbuf2
- rsbuf2=~sbuf2; //取反,使高半字节变为反码
- sbuf2>>=4; //将高半字节右移到低半字节
- rsbuf2&=0xf0; //保留高半字节,去掉低半字节
- sbuf2&=0x0f; //保留低半字节,去掉高半字节
- rsbuf2|=sbuf2; //合并高低半字节
- SBUF=rsbuf2; //发送出去
- state2=10; //将state2置为10准备发送下半字节
- }
- else
- { //发送低半字节
- sbuf2=*buf2; //将要发送的字节送到sbuf2
- buf2++; //指针加一
- buf2_length--; //发送数据长度减一
- rsbuf2=~sbuf2; //取反,使低半字节变为反码
- rsbuf2<<=4; //将低半字节反码左移到高半字节
- rsbuf2&=0xf0; //保留高半字节,去掉低半字节
- sbuf2&=0x0f; //保留低半字节,去掉高半字节
- rsbuf2|=sbuf2; //合并高低半字节
- SBUF=rsbuf2; //发送出
- state2=0;
- }
- }
- else
- { //如果发送数据长度为零则发送数据帧尾
- if(buf2_flag){ //判断是否发过数据帧尾
- SBUF=TAIL; //将数据帧尾发送出去
- while(TI==0);
- TI=0;
- buf2_flag=0; //置发送标志为零,表示发送完毕
- }
- }
- }
- EA=1; //开放中断
- }