⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 remote_t2.c

📁 红外编程
💻 C
📖 第 1 页 / 共 2 页
字号:
//红外一开始发送一段13。5ms的引导码,引导码由9ms的高电平和4。5ms的低电平组成,跟着引导码是系统码,系统反码,按键码,按键反码,如果按着键不放,则遥控器则发送一段重复码,重复码由9ms的高电平,2。25ms的低电平,跟着是一个短脉冲,本程序经过试用,能解大部分遥控器的编码! 
#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; //开放中断
}




void ack(void) //发送ACK信号子程序
{
buf1_flag=0; //置接收标志位位零表示已经相应了,可以接收下一帧数据
REN=1; //接收使能
while(buf2_flag); //判断上一帧有没发送完,没有则继续等待
buf2=SEND; //初始化发送地址
*buf2=ACK; //将ACK信号存入发送缓冲里
buf2_length=1; //存入发送数据长度
buf2_flag=1; //置发送长度为1
SBUF=HEAD; //发送数据帧头
}

void nack(void) //发送NACK信号子程序
{
buf1_flag=0; //置接收标志位位零表示已经相应了,可以接收下一帧数据
REN=1; //接收使能
while(buf2_flag); //判断上一帧有没发送完,没有则继续等待
buf2=SEND; //初始化发送地址
*buf2=NACK; //将NACK信号存入发送缓冲里
buf2_length=1; //存入发送数据长度
buf2_flag=1; //置发送长度为1
SBUF=HEAD; //发送数据帧头
}

void free(void) //发送FREE信号子程序
{
buf1_flag=0; //置接收标志位位零表示已经相应了,可以接收下一帧数据
REN=1; //接收使能
while(buf2_flag); //判断上一帧有没发送完,没有则继续等待
buf2=SEND; //初始化发送地址
*buf2=FREE; //将FREE信号存入发送缓冲里
buf2_length=1; //存入发送数据长度
buf2_flag=1; //置发送长度为1
SBUF=HEAD; //发送数据帧头
}

void busy(void) //发送BUSY信号子程序
{
buf1_flag=0; //置接收标志位位零表示已经相应了,可以接收下一帧数据
REN=1; //接收使能
while(buf2_flag); //判断上一帧有没发送完,没有则继续等待
buf2=SEND; //初始化发送地址
*buf2=BUSY; //将BUSY信号存入发送缓冲里
buf2_length=1; //存入发送数据长度
buf2_flag=1; //置发送长度为1
SBUF=HEAD; //发送数据帧头
}

void download(void)
{
int i; //用于循环计数
i=buf1_length-3; //数据长度等于数据包长度减去一个字节控制字和两个字节地址
buf1=RECEIVE+1; //使指针指向地址
p.a[0]=*buf1++; //读入目标地址高字节
p.a[1]=*buf1++; //读入目标地址低字节
while(i--){ //长度减一直至为零
*p.p3++=*buf1++; //将接受缓冲里数据送到目标地址,并且两个指针加一
}
REN=1; //数据处理完,允许接收下一帧数据
buf1_flag=0; //置接收标志为零,表示已经处理完
free(); //发送FREE信号表示已经处理完处于空闲状态

}

void upload(void){
int i; //
while(buf2_flag); //判断上一帧有没发送完,没有则继续等待
buf1=RECEIVE+1; //将指针指向地址
buf2=SEND; //初始化发送地址
*buf2++=UPLOAD; //把控制字存进去并且指针加一
*buf2++=*buf1++; //把地址高字节复制过去
*buf2++=*buf1++; //把地址低字节复制过去
p.a[0]=*buf1++; //把数据长度高字节复制过去
p.a[1]=*buf1++; //把数据长度低字节复制过去
i=p.b; //把数据长度复制过去
buf1-=4; //将指针减4,使其指向地址处
p.a[0]=*buf1++; //把地址高字节复制过去
p.a[1]=*buf1++; //把地址低字节复制过去
buf1_flag=0; //已经对接受数据处理完毕
REN=1; //允许接收
buf2_length=i+3; //数据包长度等于数据长度加3
while(i--){ //判断数据长度是否为零,为零则不执行循环语句,同时长度减一
*buf2++=*p.p3++; //把数据复制到发送缓冲区
}
buf2=SEND;
buf2_flag=1; //置发送标志为1
SBUF=HEAD; //发送数据帧头
}

void run(void) //运行下载的程序
{
sub();
}


void delay1s(void){
for(i.b[0]=0;i.b[0]<0xffff;i.b[0]++){
i.b[0]=i.b[0]++;
i.b[0]=i.b[0]--;}
}

void ir_init(void)
{
	ir_flag=0; //将红外接收标志置为零
	for(ir=IR;ir<0xe0;ir++)
	{
		*ir=0; //将红外接收缓冲清零
	}
	EA=0; //禁止中断
	ES=0; //禁止串行中断
	ET2=1; //允许T2中断
	ir=IR; //初始化红外数据指针
	TR0=0; //禁止计数
	TH0=0; //将计数器置为0
	TL0=0;
	TF0=0; //清除溢出标志
	count.b=1; //初始化为零
	init:
	TR2=0;
	TL2=0x00;
	TH2=0xdc; //给T2赋一个初值,当计数器溢出时正好为6毫秒
	T2CON=0x0d; //EXEN2=1,TR2=1,C/T2=0,CP/RL2=1,工作于捕捉方式
	while(!TF2)
		; //查询计数器是否溢出
	TF2=0; //清除溢出位
	if(EXF2) //判断在此期间又没发生过电平变化
	{ //如果发生过变化则重新计数
		goto init; //等待下一次按键
	}
	else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -