支持1527 2264 2260 2262 SC5211 HS2240等解码,自动适应振荡电阻
2260 2262 2264 如果不进行人工地址编码,好多个遥控器地址编码一样的,只要学习一个遥控器,所有的遥控器都能同时用
一:如何设置自锁,互锁,点动输出
1:断电。按住学习键然后上电保持1-2秒钟后松开,学习灯闪3次,设置为自锁输出。
2:断电。按住学习键然后上电保持1-2秒钟后松开,学习灯闪1次,设置为互锁输出。
3:断电。按住学习键然后上电保持1-2秒钟后松开,学习灯闪2次,设置为点动输出。
二:遥控器学习:
以上输出模式设置后断开电源,然后上电,按一下学习键,学习灯保持亮,再按遥控器上的任意一键,学习灯熄灭,遥控器学习成功。重复上述操作可以学习多达20个遥控器。1527 2260 2262 2264等的遥控器可以混合学习使用。
三:如何清空已学习过的遥控器:
断电,按住学习键然后上电保持4秒以上再松开按键,学习灯闪烁4次,说明已学习过的遥控器已被清空。
电路原理图如下:
下载烧录说明
IRC频率选11.0592M
如果已烧录过的单片机,烧录前必须下载后恢复下出厂设置。才能再烧录,新单片机不用恢复
操作:按住学习键,上电保持10秒以上松开即可。
单片机源程序如下:
//内部晶振:11.0592M//测试芯片:STC15F104E/STC11F04W //By David Xu 2020/08/18 //硬件最简版 //实现2262、1527解码输出,学习、自适应多阻值,片内EEPROM存储相关信息 #include <reg52.h> #include <intrins.h> sfr AUXR=0x8e; sfr IAP_DATA = 0xC2; //片内EEPROM资源声明 sfr IAP_ADDRH = 0xC3; sfr IAP_ADDRL = 0xC4; sfr IAP_CMD = 0xC5; sfr IAP_TRIG = 0xC6; sfr IAP_CONTR = 0xC7; sfr P3M0 =0xb2; sfr P3M1 =0xb1; #define uchar unsigned char #define uint unsigned int sbit RF = P3^4; //射频引脚定义 sbit set = P3^3; //设置键定义 sbit keya = P3^0; //第一路 sbit keyb = P3^1; //第二路 sbit keyc = P3^2; //第三路 sbit keyd = P3^5; //第四路 uint ll_w; uchar hh_w; //高,低电平宽度 uchar ma_x; //接收到第几位编码了 uchar idata bma1,bma2,bma3; //用于接收过程存放遥控编码,编码比较两次,这是第一次 uchar idata mmb1,mmb2,mmb3; // 用于接收过程存放遥控编码,第二次 uchar key_data; uchar short_k; uchar mma1,mma2,mma3; //用于解码过程 uchar L_M_select; uchar xplx; uint s,s1; bit old_rc5; //保存上一次查询到的电平状态 bit tb_ok; //接收到同步的马时置1 bit rf_ok1,rf_ok2; //解码过程中的临时接收成功标志 bit rf_ok; //接收到一个完整的遥控命令后置1,通知解码程序可以解码了 bit study; //进入学习状态标志 bit system_int; //系统清零标志 bit m1,m2,m3,m4; bit flag_zs; bit decode_ok; //解码成功 uchar idata key_number[61]; void delay_1ms(uint x) //1毫秒延时 { uchar b,c; for(x;x>0;x--) { for(b=5;b>0;b--) { for(c=150;c>0;c--); } } } void BB(uint size,uchar Number) { if(Number) { for(Number;Number>0;Number--) { set=0; delay_1ms(size); set=1; delay_1ms(size); } } else { set=0; delay_1ms(size); set=1; } } void chick1527(uchar d) { uchar u; for(u=0;u<4;u++) { if(((d>>(u*2)) & 3)==2) { xplx=0x55; } } } //==================================================== /////////片内EEPROM读写驱动程序/////////////////////////// //==================================================== void IAP_Disable() //关闭IAP { //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态, //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关 IAP_CONTR = 0; //关闭IAP 功能 IAP_CMD = 0; //清命令寄存器,使命令寄存器无命令,此句可不用 IAP_TRIG = 0; //清命令触发寄存器,使命令触发寄存器无触发,此句可不用 IAP_ADDRH = 0; IAP_ADDRL = 0; }// //读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节 uchar read_add(uint addr) //读EEPROM { IAP_DATA = 0x00; IAP_CONTR = 0x84; //打开IAP 功能, 设置Flash 操作等待时间 IAP_CMD = 0x01; //IAP/ISP/EEPROM 字节读命令 IAP_ADDRH = addr>>8; //设置目标单元地址的高8 位地址 IAP_ADDRL = addr&0xff; //设置目标单元地址的低8 位地址 EA = 0; IAP_TRIG = 0x5a; //先送 46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此 IAP_TRIG = 0xa5; //送完 B9h 后,ISP/IAP 命令立即被触发起动 _nop_(); EA = 1; IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态, //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关 return (IAP_DATA); }//------------------------------------------------------------------------------ //字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据 void write_add(uint addr,uchar ch) //直接写EEPROM { IAP_CONTR = 0x84; //打开 IAP 功能, 设置Flash 操作等待时间 IAP_CMD = 0x02; //IAP/ISP/EEPROM 字节编程命令 IAP_ADDRH = addr>>8; //设置目标单元地址的高8 位地址 IAP_ADDRL = addr&0xff; //设置目标单元地址的低8 位地址 IAP_DATA = ch; //要编程的数据先送进IAP_DATA 寄存器 EA = 0; IAP_TRIG = 0x5a; //先送 46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此 IAP_TRIG = 0xa5; //送完 B9h 后,ISP/IAP 命令立即被触发起动 _nop_(); EA = 1; IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态, //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关 }//------------------------------------------------------------------------------ //擦除扇区, 入口:DPTR = 扇区地址 void Sector_Erase(uint addr) //扇区擦除 { IAP_CONTR = 0x84; //打开IAP 功能, 设置Flash 操作等待时间 IAP_CMD = 0x03; //IAP/ISP/EEPROM 扇区擦除命令 IAP_ADDRH =addr>>8; //设置目标单元地址的高8 位地址 IAP_ADDRL =addr&0xff; //设置目标单元地址的低8 位地址 EA = 0; IAP_TRIG = 0x5a; //先送 46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此 IAP_TRIG = 0xa5; //送完 B9h 后,ISP/IAP 命令立即被触发起动 _nop_(); EA = 1; }//------------------------------------------------------------------------------ void timeint() interrupt 1 //遥控接收,通过定时器0中断,定时去查询 { uchar x1; TF0=0; // 清除T0中断标志 TL0=0x30; //b5 TH0=0xff; //fe if (!RF) { ll_w++;old_rc5=0; } // 检测到低电平 低电平时间加1,记录本次电平状态 else // 检测到高电平 { hh_w++; if (!old_rc5) // 检测到从低到高的跳变,已检测到一个完整(高-低)电平周期 { if (((hh_w*16)<ll_w) && (hh_w*38)>ll_w ) //判同步码 { short_k=ll_w/31; ma_x=0; tb_ok=1; bma1=0; bma2=0; bma3=0; //根据不同 同步码 宽度,T0加载不同初值 } else if ((tb_ok)&&((ll_w>short_k*2)&&(ll_w<short_k*5))) // 10/14 { ma_x++; //已经接收到同步码,判0 if(ma_x>23) { if(!rf_ok1) { mma1=bma1;mma2=bma2;mma3=bma3;//将接收到的编码复制到解码寄存器中 rf_ok1=1; // 通知解码子程序可以解码了 tb_ok=0; s=5000; } else { mmb1=bma1;mmb2=bma2;mmb3=bma3;//将接收到的编码复制到解码寄存器中 rf_ok2=1; // 通知解码子程序可以解码了 tb_ok=0; } } } else if ((tb_ok)&&((ll_w>short_k/6)&&(ll_w<short_k*2))) // 3/5 { switch (ma_x) { case 0 : { bma1=bma1 | 0x80; break; }//遥控编码第1位 case 1 : { bma1=bma1 | 0x40; break; } case 2 : { bma1=bma1 | 0x20; break; } case 3 : { bma1=bma1 | 0x10; break; } case 4 : { bma1=bma1 | 0x08; break; } case 5 : { bma1=bma1 | 0x04; break; } case 6 : { bma1=bma1 | 0x02; break; } case 7 : { bma1=bma1 | 0x01; break; } case 8 : { bma2=bma2 | 0x80; break; } case 9 : { bma2=bma2 | 0x40; break; } case 10: { bma2=bma2 | 0x20; break; } case 11: { bma2=bma2 | 0x10; break; } case 12: { bma2=bma2 | 0x08; break; } case 13: { bma2=bma2 | 0x04; break; } case 14: { bma2=bma2 | 0x02; break; } case 15: { bma2=bma2 | 0x01; break; } case 16: { bma3=bma3 | 0x80; break; } case 17: { bma3=bma3 | 0x40; break; } case 18: { bma3=bma3 | 0x20; break; } case 19: { bma3=bma3 | 0x10; break; } case 20: { bma3=bma3 | 0x08; break; }//按键状态第1位 case 21: { bma3=bma3 | 0x04; break; } case 22: { bma3=bma3 | 0x02; break; } case 23: { bma3=bma3 | 0x01; if(!rf_ok1) { mma1=bma1;mma2=bma2;mma3=bma3;//将接收到的编码复制到解码寄存器中 rf_ok1=1; // 通知解码子程序可以解码了 tb_ok=0; s=5000; break; } else { mmb1=bma1;mmb2=bma2;mmb3=bma3;//将再次接收到的编码复制到解码寄存器中, rf_ok2=1; // 通知解码子程序可以解码了 tb_ok=0; break; } } } ma_x++; } else {ma_x=0; tb_ok=0; bma1=0; bma2=0; bma3=0;hh_w=1;ll_w=0;} //接收到不符合的高-低电平序列 ll_w=0;hh_w=1; } old_rc5=1; // 记录本次电平状态 } if(rf_ok1) //规定时间内接受到2帧相同的编码数据才有效 { s--; if(!s) rf_ok1=0; if(rf_ok2) { if((mma1==mmb1)&&(mma2==mmb2)&&(mma3==mmb3)) { rf_ok=1;rf_ok1=0;rf_ok2=0; } else { rf_ok=0; rf_ok1=0; rf_ok2=0; } } } if(rf_ok) //判断是否是学习状态&&() { EA=0; chick1527(mma1); if(xplx!=0x55){chick1527(mma2);} if(xplx!=0x55){chick1527(mma3);} if(xplx==0x55) { xplx=0; key_data=mma3 & 0x0f; mma3=mma3>>4; } else { xplx=1; key_data=0; for(x1=0;x1<4;x1++){if(((mma3>>(x1*2))&3)==3) key_data|=1<<x1;} mma3=0; } if(!study) { rf_ok=0; for(x1=0;x1<20;x1++) { if((mma1==key_number[x1*3+1])&&(mma2==key_number[x1*3+2])&&(mma3==key_number[x1*3+3])) { if((!((mma1==0)&&(mma2==0)))&&(!((mma1==0xff)&&(mma2==0xff)))&&key_data) { if(L_M_select==3) { m1=(key_data & 0x08); m2=(key_data & 0x04); m3=(key_data & 0x02); m4=(key_data & 0x01); } else { keya=(key_data & 0x08); keyb=(key_data & 0x04); keyc=(key_data & 0x02); keyd=(key_data & 0x01); } decode_ok=1; set=0; s1=12000; break; } } } EA=1; } } if(decode_ok) { s1--; if(!s1) { set=1; decode_ok=0; flag_zs=0; if(L_M_select==2) { keya=0; keyb=0; keyc=0; keyd=0; } } if((L_M_select==3)&&(!flag_zs)&&decode_ok) { flag_zs=1; if(m1)keya=!keya; if(m2)keyb=!keyb; if(m3)keyc=!keyc; if(m4)keyd=!keyd; } } } void key_buffer() //把遥控器码从 EEPROM 复制到DATA { uchar n; for(n=0;n<61;n++) { key_number[n]=read_add(0x0000+n); } } void KEY_study() //遥控器学习 { uchar num_rf; uchar d_num; if(study==1) { rf_ok=0; d_num=0; while(!rf_ok) { delay_1ms(100); d_num++; if(d_num>200) break; } d_num=0; if(rf_ok==1) { EA=0; num_rf=key_number[0]; //取已学习的遥控器数量 if(num_rf>20){num_rf=0;} //如果遥控器数量超过20个,覆盖最先学习的 key_number[num_rf*3+1]=mma1; key_number[num_rf*3+2]=mma2; key_number[num_rf*3+3]=mma3; key_number[0]=num_rf+1; Sector_Erase(0x0000); for(num_rf=0;num_rf<61;num_rf++) { write_add(0x0000+num_rf,key_number[num_rf]); } rf_ok=0; set=1; //学习成功 EA=1; } else { rf_ok=0; //操作超时 BB(300,4); } d_num=0; study=0; } } void system_res() //系统清零 { Sector_Erase(0x0000); write_add(0x0000,0x00); key_buffer(); } void set_scan() //判断学习键状态 { uchar h=0; while((!set)&&(!study)&&(!decode_ok)) { if(h>2) { study=1; h=0; while(!set); set=0; } delay_1ms(100); h++; } } void system_start() //上电初始化 { uchar h; P3M0=0x27; P3M1=0x10; P3=0xd8; L_M_select=read_add(0x0200); if((L_M_select>3)||(L_M_select==0))L_M_select=3; if(!set) { while(!set) { delay_1ms(50); h++; if(h>2) { while(!set) { delay_1ms(100); h++; if(h>90) { system_int=1; while(!set); } } if(system_int) { h=0; system_int=0; system_res(); delay_1ms(1500); BB(500,4); }
复制代码