315-433MHZ學習遙控器芯片設置說明
支持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次,說明已學習過的遙控器已被清空。
電路原理圖如下:
51hei.png (25.21 KB, 下載次數: 111)
下載附件
2023-6-11 04:52 上傳
下載燒錄說明
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);
- }
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
Keil代碼下載:
學習型無線遙控解碼程序2023.7z
(192.14 KB, 下載次數: 522)
2023-10-9 15:17 上傳
點擊文件名下載附件
433M無線解碼程序 下載積分: 黑幣 -5
|