原帖:http://www.51hei.com/bbs/dpj-54638-1.html
// STC15f104模拟315M 2272解码程序
// 工作频率:12M
//说明:1路继电器输出,1LED指示,1微动开关K1。
// 按K1进入编辑模式,LED指示灯亮。
// 在编辑模式下 ,按下遥控器钮,存储有效的遥控码,退出编辑模式。
// 在编辑模式下 ,按K1退出编辑模式。
// 在编辑模式下 ,长按K1 (10S) 删除所有存储的遥控码。
// 在正常模式下 , 按下遥控器钮,及LED与继电器亮灭。
//优点: 能接收2262的1.2M-4.7M电阻编码,几乎所有的315M遥控器都兼容。
// 由于定时读引脚,抗干扰能力强 ,和硬件解码距离无区别。
//缺点:占用单片机资源比较多。能存储20条编码。
//#include <reg52.h>
#include "stc15f104w.h"
#include "flash.h"
typedef unsigned int u16; //16位无符号整型数
typedef unsigned char u8; //8位无符号整型数
sbit IR_INPUT = P3^3;
sbit KEY1 = P3^1;
sbit JD1 = P3^5;
sbit led1 = P3^2;
u8 T0RL = 0; //T0重载值的低字节
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 宽窄脉冲码中间值
// 遥控码发射时钟=1a, 1M电阻:1a=31us 5M电阻:1a=156us
//由于51单片机中断时间过短只能到 60us 用stc15f104的1T模式(同时钟频率下是51单片机6-12倍)————全兼容
bit WanCengBiaoJi = 0; // 读完一组数据的标记
u8 code YaoKongSu_4 = 4 ; //遥控码个数
u8 code DaiMaTiaoSu_20 = 20 ; //遥控条数
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; 延续 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; //定时器计数频率
tmp = (tmp * ms) / 1000; //计算所需的计数值
tmp = 65536 - tmp; //计算定时器重载值
tmp = tmp + 18; //补偿中断响应延时造成的误差
T2H = (u8)(tmp>>8); //定时器重载值拆分为高低字节
T2L = (u8)tmp;
AUXR &= 0xEF; // 启动T2定时器 方式 :16位重装模式计数器
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位重装模式计数器
TMOD |= 0x02; //配置T0为模式2
T0RL = tmp;
TH0 = tmp; //加载T0重载值
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
PT0 = 1; //配置T0中断为高优先级
}
/* 中断函数 读出同步码+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数
从定义中断为1a所用时间us数
则 同步头124个us数 窄脉冲4个us数 宽脉冲12个us数
*/
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中断服务函数,执行数码管扫描显示 */
void InterruptTimer2() interrupt 12
{
anjian();
chamiao();
WDT_CONTR=0x37; //喂狗 8.4S
}