yzwzfyz 发表于 2017-4-17 23:14 谢谢了 这么详细的回答 辛苦了 我慢慢看懂它 |
wosiyabo 发表于 2017-4-17 23:56 你这个用到两个定时器?你看看我这个可以吗? void intersvr1(void) interrupt 2 //红外工作函数 { TR0=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; TR0=0; } else { IrOK=0; //取码完成后判断读码是否正确 } } //准备读下一码 } } |
例如:00FF45CB |
红外编码格式 厂商码+厂商补码+命令码+命令补码。 |
网上都有程序例子 先去试着看一下 然后自己在编写 |
//STC89C52RC_双倍速_外部晶振24MHz #include "reg51.h" #include "intrins.h" typedef unsigned char BYTE; typedef unsigned int WORD; #define uchar unsigned char #define uint unsigned int unsigned char ir_dat_buf[4] = {0}; //红外遥控接收码存放位置 unsigned char mode; //红外线接收模式缓存 sbit P32 = P3^2; //IR void Delay1120us(void) { TL1 = 0xC4; TH1 = 0xEE; TR1 = 1; while(!TF1); TR1 = 0; TF1 = 0; } void Delay840us(void) { TL1 = 0x38; TH1 = 0xF3; TR1 = 1; while(!TF1); TR1 = 0; TF1 = 0; } unsigned char ir_read(void) // 数据 0: 0.56ms低电平,0.56ms高电平 { // 数据 1: 0.56ms低电平,1.58ms高电平 unsigned char i,ir_temp = 0; for(i = 0; i < 8; i++) { while(!P32); //等待0.56ms低电平结束 Delay840us(); //从高电平开始延时0.84ms if(P32 == 1) { ir_temp = (ir_temp << 1) + 1; //读到数据1 Delay1120us(); //延时等待1.68ms高电平结束 } else { ir_temp = ir_temp << 1; //读到数据0 } } return ir_temp; } void main() { TMOD = 0x11; //set timer0 as mode1 (16-bit) TL0 = 0; //定时4ms TH0 = 0; TR0 = 1; //timer0 start running TF0 = 1; IT0 = 1; //set INT0 int type (1:Falling 0:Low level) ET0 = 1; //enable timer0 interrupt EX0 = 1; //enable INT0 interrupt EA = 1; //open global interrupt switch mode = 0;//红外线接收清除 while (1) { switch(mode) { case 1: {mode=0;}break; case 2: {mode=0;}break; case 3: {mode=0;}break; default: break; } } } void exint0() interrupt 0 //按键一次: 依次发送 引导码 + 地址 + 地址取反 + 数据 + 数据取反 { static unsigned i; EX0 = 0; //关闭外部中断,仍可以执行以下程序 for(i = 0; i < 10; i++) // 引导码由9ms低电平及4.5ms高电平组成, 接着是低8位地址码, 高8位地址码 { // 连发码由9ms低电平及2.25ms高电平组成, 跟着是0.56ms低电平, 然后都是高电平 Delay840us(); if(P32) //检测引导码9ms是否有高电平,有则退出 { EX0 = 1; return; } } while(!P32); //等待高电平的到来 注:尽量采用延时来检测,不然可能会进入死循环 Delay840us(); Delay840us(); // 检测连按; 延时2.52ms,检测是否有低电平,有表示按键连按,且退出 Delay840us(); if(!P32) { EX0 = 1; return; } while(P32); //等待4.5ms高电平结束,开始接收数据 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); ir_dat_buf[0] = ir_read(); ir_dat_buf[1] = ir_read(); ir_dat_buf[2] = ir_read(); ir_dat_buf[3] = ir_read(); EX0 = 1; //开启外部中断,等下次信号 } void tm0_isr() interrupt 1 using 1 { ET0 = 0;//禁止外部中断,防止在接收到数据后处理过程中,再按遥控造成冲突 TL0 = 0x60; //定时4ms TH0 = 0xC1; if(((ir_dat_buf[0] == 0x00) && (ir_dat_buf[1] == 0xff))&&((ir_dat_buf[2])== ~(ir_dat_buf[3])))//用户码0x00,0xFF { switch(ir_dat_buf[2]) { case 0x45: {mode=1;}break; case 0x46: {mode=2;}break; case 0x47: {mode=3;}break; default: break; } ir_dat_buf[0]=0;//清除红外线接收缓存 ir_dat_buf[1]=0;//清除红外线接收缓存 ir_dat_buf[2]=0;//清除红外线接收缓存 ir_dat_buf[3]=0;//清除红外线接收缓存 } ET0 = 1; //充许外部中断,处理完数据后再打开外部中断 } |
得到键码后的人机对话程序的复杂程度,与程序的目的相关。一般比较复杂,不在此细述。 |
很实用,很给力 |
本帖最后由 yzwzfyz 于 2017-4-17 23:28 编辑 解出:引导符、0、1后,依协议组装即可得到键码。 |
本帖最后由 yzwzfyz 于 2017-4-17 23:26 编辑 1、红色用接收模块HS0038B,从INT0输入,下沿产生中断。用T3计数红外脉冲宽度(是下沿到下沿)。 红外遥控器采用UPD6122控制芯片NEC编码格式,只取下沿。但红外模块接收会反转成上沿。 2、INT0中断后,记录上次红外宽度(下沿到下沿),再复位T3重新计数,准备计数下个脉冲宽度。 3、红外脉冲宽度数据:(有容错范围,即上下限) 3.1、引导码=5900H-78FFH 容错范围84%-115% *(9ms+4.5ms),做一个标记B_INFRLEAD=1,表示已有引导符; 3.2、0=0800H-0AFFH 容错范围87%-119% *(1.125ms+0.56ms); 3.3、1=0F00H-13FFH 容错范围85%-114% *2.25ms; 3.4、其它:放弃作废码处理,清B_INFRLEAD=0,表示尚无引导符; 3.5、计数T3溢出时,清0停止计数。(红外输入已结束,则T3停止不再计数) 注:用的是24MHz的晶振。 |
前几天也买了这个控制器。花了几天,写了人机对话程序。 现将红外解码部分的方案,告诉你。 |
小唐唐 发表于 2017-4-17 13:30 不太懂啊 ![]() |
红外遥控的毕设,同求啊 |
红外遥控编码 主要是时序很重要 网上都有程序例子 先去试着看一下 然后自己在编写 |