原帖:http://www.zg4o1577.cn/bbs/dpj-54638-1.html
// STC15f104模擬315M 2272解碼程序
// 工作頻率:12M
//說明:1路繼電器輸出,1LED指示,1微動開關K1。
// 按K1進入編輯模式,LED指示燈亮。
// 在編輯模式下 ,按下遙控器鈕,存儲有效的遙控碼,退出編輯模式。
// 在編輯模式下 ,按K1退出編輯模式。
// 在編輯模式下 ,長按K1 (10S) 刪除所有存儲的遙控碼。
// 在正常模式下 , 按下遙控器鈕,及LED與繼電器亮滅。
//優(yōu)點: 能接收2262的1.2M-4.7M電阻編碼,幾乎所有的315M遙控器都兼容。
// 由于定時讀引腳,抗干擾能力強 ,和硬件解碼距離無區(qū)別。
//缺點:占用單片機資源比較多。能存儲20條編碼。
//#include <reg52.h>
#include "stc15f104w.h"
#include "flash.h"
typedef unsigned int u16; //16位無符號整型數(shù)
typedef unsigned char u8; //8位無符號整型數(shù)
sbit IR_INPUT = P3^3;
sbit KEY1 = P3^1;
sbit JD1 = P3^5;
sbit led1 = P3^2;
u8 T0RL = 0; //T0重載值的低字節(jié)
u8 ms =1;
u8 ircodex[3]; //解碼最終值
u8 ircode[6]; //解碼中間值
u8 code Tm_bz[]={ 31 ,156 ,114 ,134 ,2 ,16 ,8 };
//基準:0-1同步碼時間范圍, 2-3 同步碼124a范圍, 4-5 寬窄脈沖碼4-12a范圍, 5 寬窄脈沖碼中間值
// 遙控碼發(fā)射時鐘=1a, 1M電阻:1a=31us 5M電阻:1a=156us
//由于51單片機中斷時間過短只能到 60us 用stc15f104的1T模式(同時鐘頻率下是51單片機6-12倍)————全兼容
bit WanCengBiaoJi = 0; // 讀完一組數(shù)據(jù)的標記
u8 code YaoKongSu_4 = 4 ; //遙控碼個數(shù)
u8 code DaiMaTiaoSu_20 = 20 ; //遙控條數(shù)
bit Bianji = 0; //進入編輯標記
u8 E2BiaoJi;
u8 Tm1[50]; //0空位 1-24遙控碼脈沖 25同步碼 26-50第二次遙控碼脈沖
void ConfigTimer0(u8 ms);
void ConfigTimer2(u8 ms);
void xunhuanculi(bit add);
void Bian_ji();
void Led_jia();
void Flash_del();
void LED_jh(bit dat);
void Caozuo_csh();
void main()
{
EA = 1; //開總中斷
IR_INPUT = 1; //接收引腳
ConfigTimer2(5); //配置T2定時 ms
ConfigTimer0(124); //配置T0定時 0-255us
WDT_CONTR=0x37; //喂狗 8.4S
Caozuo_csh();
while (1)
{
if(WanCengBiaoJi == 1)
{ WanCengBiaoJi = 0;
xunhuanculi(0);//Tm1[50] 1-24脈沖解碼
xunhuanculi(1);//Tm1[50] 25-50脈沖解碼
if((ircode[0]==ircode[3]) && (ircode[1]==ircode[4]) && (ircode[2]==ircode[5]) && ms!=0) //2次編碼比較
{
if((ircodex[0]==ircode[0]) && (ircodex[1]==ircode[1]) && (ircodex[2]==ircode[2]))
{ ms=1; }
else //ircodex[3] 的值保存 0.75S 后清零
// ms=1; 延續(xù) ircodex[3]的值, ms=0; 啟動下一級比較
{
ircodex[0]=ircode[0];
ircodex[1]=ircode[1];
ircodex[2]=ircode[2];
if(Bianji==1)
{ ms = 1; Led_jia();}
else
{ ms=0;}
}
}
ET0 = 1;
}
}
}
//脈沖解碼
void xunhuanculi(bit add)
{
u8 i, j, x, m, dat;
u8 byt;
x = add*25+1;
m = add*3;
for(i=0; i<3; i++)
{ dat=i*8;
for(j=0; j<8; j++)
{ if(Tm1[dat+j+x]<=Tm_bz[6])
{ byt <<= 1; byt |= 0x01; }
else
{ byt <<= 1; }
}
ircode[i+ m ] = byt;
}
}
//LED指示 繼電器處理
void LED_jh(bit dat)
{
led1 = dat;
if(Bianji==0)
{ JD1 = dat;}
}
//初始化
void Caozuo_csh()
{
Bianji=0;
LED_jh(0);
P3M1= 0x08; // P3.1準雙向 P3.2推挽 P3.3高阻 P3.5推挽
P3M0= 0x24;
}
//刪除Flash內的編碼
void Flash_del()
{ if(Bianji==1)
{ eeprom_erase(0); Caozuo_csh(); }
}
//進入 退出編輯模式
void Bian_ji()
{ u8 i;
if(Bianji==0)
{ Bianji=1;
P3M1= 0x28; // P3.1準雙向 P3.2開漏 P3.3高阻 P3.5開漏
P3M0= 0x24;
LED_jh(1);
//讀出沒有遙控碼的空位
E2BiaoJi=0xff;
for(i=0; i<DaiMaTiaoSu_20; i++)
{
if(eeprom_read(i*4)==0xff)
{E2BiaoJi=i; break;}
}
}
else
{ Caozuo_csh(); }
}
//在編輯模式下,遙控器按一下,寫入一條有效的遙控碼
void Led_jia()
{ //把有效的遙控碼寫入Flash
u8 dat;
if (E2BiaoJi!= 0xff )
{ dat= E2BiaoJi*YaoKongSu_4;
eeprom_write(dat,0); //標記以寫入
eeprom_write(dat+1,ircodex[0]);
eeprom_write(dat+2,ircodex[1]);
eeprom_write(dat+3,ircodex[2]);
}
Caozuo_csh();
}
/* 配置并啟動T2,ms-T2定時時間 */
void ConfigTimer2(u8 ms)
{
unsigned long tmp; //臨時變量
tmp = 12000000 / 12; //定時器計數(shù)頻率
tmp = (tmp * ms) / 1000; //計算所需的計數(shù)值
tmp = 65536 - tmp; //計算定時器重載值
tmp = tmp + 18; //補償中斷響應延時造成的誤差
T2H = (u8)(tmp>>8); //定時器重載值拆分為高低字節(jié)
T2L = (u8)tmp;
AUXR &= 0xEF; // 啟動T2定時器 方式 :16位重裝模式計數(shù)器
AUXR |= 0x10; // 啟動T2定時器
IE2 &= 0xFB; // 使能T2中斷
IE2 |= 0x04; // 使能T2中斷
//ET2 = 1; //使能T2中斷
//T2R = 1; //啟動T2定時器
}
/* 配置并啟動T0,us-T0定時時間 */
void ConfigTimer0(u8 ms)
{
u8 tmp; //臨時變量
tmp = 256 -ms ; //計算定時器重載值
TMOD &= 0xF0; // 定時器工作方式 方式 :8位重裝模式計數(shù)器
TMOD |= 0x02; //配置T0為模式2
T0RL = tmp;
TH0 = tmp; //加載T0重載值
ET0 = 1; //使能T0中斷
TR0 = 1; //啟動T0
PT0 = 1; //配置T0中斷為高優(yōu)先級
}
/* 中斷函數(shù) 讀出同步碼+24位遙控編碼 2次 */
void EXINT1_ISR() interrupt 1
{ static bit a1,a2,a3;
static u8 Tm_zz=0;
static u8 Tm_js=0;
static u8 Tm=0;
//抗干擾用
a3=a2;
a2=a1;
a1=IR_INPUT;
if(a1==a3)
{a2=a1;}
//========
/*同步頭124a 窄脈沖4a 寬脈沖12a
==============================
定義中斷為124a
Tm=0時 算出1a所用時間us數(shù)
從定義中斷為1a所用時間us數(shù)
則 同步頭124個us數(shù) 窄脈沖4個us數(shù) 寬脈沖12個us數(shù)
*/
if(a3)
{
switch(Tm_zz)
{
case 0: if(Tm==0)
{
if((Tm_js<Tm_bz[0] )|| Tm_js>Tm_bz[1])
{ Tm_zz=0; Tm=0; Tm_js=0; TH0 = T0RL; }
else
{ Tm++; Tm_zz=2; TH0 = 256- Tm_js; TL0=TH0;}
}
else
{ if((Tm_js<Tm_bz[2] )|| Tm_js>Tm_bz[3] )
{ Tm_zz=0; Tm=0; Tm_js=0; TH0 = T0RL; }
else
{ Tm1[Tm]=256-TH0; Tm++; Tm_zz=2;}
}
break;
case 1: if((Tm_js<Tm_bz[4] )|| Tm_js>Tm_bz[5])
{ Tm_zz=0; Tm=0; Tm_js=0; TH0 = T0RL; }
else
{ Tm1[Tm]=Tm_js; Tm++; Tm_zz=2;}
break;
case 2: if( Tm==25)
{Tm_zz=3;}
if( Tm>=50)
{ ET0 = 0; WanCengBiaoJi =1; Tm_zz=0; Tm=0; Tm_js=0; TH0 = T0RL; }
break;
default:break;
}
}
else
{
switch(Tm_zz)
{
case 0: Tm_js++; break;
case 1: Tm_js++; break;
case 2: Tm_js=1; Tm_zz=1; break;
case 3: Tm_js=1; Tm_zz=0; break;
default:break;
}
}
}
//遙控碼與存儲的遙控碼比較處理
void chamiao()
{ u8 i,dat;
bit j;
ms++;
if(ms == 1)
{
EA=0 ;
for(i=0; i<DaiMaTiaoSu_20; i++)
{ dat= i*YaoKongSu_4;
if(eeprom_read(dat)==0)
{ if(eeprom_read(dat+1)==ircodex[0])
{ if(eeprom_read(dat+2)==ircodex[1])
{ if(eeprom_read(dat+3)==ircodex[2])
{ j= !led1;
_nop_();
led1 = j;
JD1 = j;
break;
}
}
}
}
else
{break;}
}
EA=1 ;
}
if(ms > 150 )
{//按下0.75S后清除遙控碼 作用:遙控器連按誤動作
ircodex[0]=0x00;
ircodex[1]=0x00;
ircodex[2]=0x00;
ms = 1;
}
}
//按鈕掃描 需在定時中斷中調用
void anjian()
{ static u16 JiShu=0;
static bit J=0;
static u8 keybuf = 0xff;
keybuf = (keybuf <<1) |KEY1;
if(keybuf == 0x00)
{ //在編輯模式下大于10S LED閃爍即可刪除Flash存儲
JiShu++;
if(JiShu>=1000)
{ if(Bianji==1)
{ JiShu=950;
J=!J;
led1=J;
}
else
{JiShu=1;}
}
}
else if(keybuf == 0xFF)
{
if(JiShu>0)
{ if(JiShu<950)//10S刪除Flash存儲的遙控碼
{Bian_ji();}
else
{Flash_del();}//小于10S進入編輯模式
JiShu=0;
}
}
}
/* T0中斷服務函數(shù),執(zhí)行數(shù)碼管掃描顯示 */
void InterruptTimer2() interrupt 12
{
anjian();
chamiao();
WDT_CONTR=0x37; //喂狗 8.4S
}