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