📄 clock.h
字号:
//*********************************************
//MCU:AT89C2051 ,晶振频率:6 MHz
//用到定时器:T0,T1
//T1:供串口通讯使用
//T0:定时器产生mS延时
//制作人:平顶山工学院计算机系,郭猛
//**********************************************
uchar ComSendStr[11]={'R','e','c',':','K','e','y','0','0','\r','\n',}; //给PC发送接收码的数据缓冲区
uchar code HEX[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',};//16进制字符
//uchar RECS80_Start=0;
///////红外线发射接收接口部分//////////
sbit RF_IR=P1^7; //红外遥控 or 无线遥控
sbit IR_RXD=P3^2; //红外接收端口,INT0
sbit REC_LED=P3^7; //红外接收指示灯,低电平亮
/**********************RECS80编码************************************/
uchar Value=0; //得到的一个编码值.
uchar Cnt256; //Timer0定时器计数器
uchar IRbit;
uchar UserID,rUserID,OprCode,rOprCode; //用户识别码、用户识别码反码、操作码、操作码反码
/*********************RC-5编码****************************************/
uchar YKDatas[3]; //遥控码(一帧14位),YKDatas[0]: 0,1为start bits, 2 为control bit, YKtype=0
//YKDatas[1]: 3~7为system bits, YKtype=1
//YKDatas[2]: 8~13为command bits, YKtype=2
uchar YKcount, YKtype; //遥控已接收位数, 一帧的各段标志
void EnableINT0(bit En) ;
//重置所有数据
void YKReset()
{
Delay(100); //去重复
YKDatas[0] = YKDatas[1] = YKDatas[2] = 0;
YKcount = 0;
YKtype = 0;
EnableINT0(1);
}
void YKInit() //遥控接收初始化
{
TMOD |= 0x01; //T0选用方式1(16位定时)
IE |= 0x82; //开总中断, 开定时器0中断
IR_RXD = 1;
YKReset(); //重置数据,开外部中断0. EX0.
}
void YKSuccess() //接收到数据后会自动被调用
{
uchar i,j;
i=YKDatas[2]/16;
j=YKDatas[2]%16;
Send_String_Com("H",1);
Send_Char_Com(0x30);Send_Char_Com(0x30); //第一个字节:0
Send_Char_Com(0x30);Send_Char_Com(0x30); //第二个字节:0
Send_Char_Com(0x30);Send_Char_Com(0x30); //第三个字节:0
Send_Char_Com(HEX[i]);Send_Char_Com(HEX[j]);//第四个字节:0xij
Send_String_Com("\r\n",2);
REC_LED=1;Delay(200);REC_LED=0; //灯闪
EnableINT0(1); //恢复INT0中断
YKReset();
}
//0.256ms中断
void Init_Timer0() //由定时器T0产生0.256mS中断
{
TMOD |= 0x01; //递增计数器
TH0=0xFF; // Init msb_value
TL0=0x14; // Init lsb_value
TF0=0; // 清TF0标志
ET0=1; // Enable timer0 interrupt
TR0=1; //16bit重装定时器
}
/////定时器T0的中断服务子程序
void Timer0() interrupt 1 //T0中断
{
if(IRMode) //RECS80编码
{
EA=0;
TH0=0xFF;TL0=0x14; //FSC=11.0592MHZ,定时0.256mS
Cnt256++;
/*
if(IRbit==1)
{
if((Cnt256<=15) && IR_RXD) //9ms内仍是低电平,9ms外是高电平
{
RECS80_Start=0;
TR0=0; //暂停T0
EA=1;
return;
}
RECS80_Start=1;
}
*/
EA=1;
}else //RC5编码
{
//第一次进入中断前, 定时1/4位的时间:445us, 以后则定时一位时间1.778ms
//即在3/4位时间时, 判断该位是1还是0
//实际测试中, 位时间只在1.651ms(+- 1ms), 定时1/4位的时间:413us
bit in = ~IR_RXD; //一体化解码后, 有载频部分变为低电平, 即低电平实际为1, 高电平实际为0
//设置定时器初值
//模式1: TH0 = (2^16 - (1651/1.085)) / 2^8 = (65536 - 1651/1.085) / 256 = 250;
//TL0 = (65536 - 1651/1.085) % 256 = 14
TH0 = 250;
TL0 = 14;
YKDatas[YKtype] = YKDatas[YKtype] | in; //将数据放入最低位
YKcount++;
if(YKcount == 1 || YKcount == 2)
{
if(in == 0) //起始两位必须都为1
{
TR0 = 0;
//EnableINT0(1);
/*调试使用,发送错误提示信息.
Send_String_Com("Error:",6);Send_Char_Com(HEX[YKcount]);
Send_String_Com("\r\n",2);
*/
YKReset();
return;
}
}
if(YKcount == 3) //获取完Start bits 和control bit, 共3位
{
YKtype = 1;
}
else if((YKcount>=4) && (YKcount<=8)) //获取完system bits, 共5位
{
if(YKDatas[1] != 0) //系统码全为0才是正确的
{
TR0 = 0;
//EnableINT0(1);
/*调试使用,发送错误提示信息.
Send_String_Com("Error:",6);Send_Char_Com(HEX[YKcount]);
Send_String_Com("\r\n",2);
*/
YKReset();
return;
}
YKtype = 2;
}
else if(YKcount == 14) //获取完commond bits, 共6位
{
YKtype = 3;
}
else if(YKtype == 3) //等待最后1/4位时间结束, 实际延时1位时间
{
TR0 = 0; //接收结束, 停止定时器0
YKSuccess();
return;
}
else //将数据左移一位, 以便将一下位数据并于最低位
{
YKDatas[YKtype] = YKDatas[YKtype] << 1;
}
}
}
void INT0Count() interrupt 0 //INT0中断,接收并解码
{
EX1=0; //红外接收时,屏蔽掉INT1中断
if(~IRMode) //RC5编码
{
EnableINT0(0); //关闭外部中断0
//模式1: TH0 = (2^16 - (413/1.085)) / 2^8 = (65536 - 381) / 256 = 255;
//TL0 = (65536 - 381) % 256 = 131
TH0 = 255;
TL0 = 131;
TR0 = 1; //启动定时器0, 定时1/4位周期
}
else //RECS80编码
{
EA=0;
IRbit++;
IE0=0; //清除INT0中断标志IE0
if(IRbit==1) //红外引导码
{
Cnt256=0; //开始计时
TR0=1;
}
else if(IRbit==2)
{
TR0=0;
if(Cnt256>=20) //正确的引导码
{
Cnt256=0;Value=0;
TR0=1;
}else //错误的引导码
{
Cnt256=0;IRbit=0;Value=0;
Delay(100);
EA=1;EX1=0; //恢复INT1中断
return;
}
}else if(IRbit<=10)
{
TR0=0;
if(Cnt256<6) Value=Value & 0x7F;
else if(Cnt256>=6) Value=Value | 0x80;
Value=Value>>1;
if(IRbit==10)
{
UserID=Value;
Value=0;
}
Cnt256=0;
TR0=1;
}else if(IRbit<=18)
{
TR0=0;
if(Cnt256<6) Value=Value & 0x7F;
else if(Cnt256>=6) Value=Value | 0x80;
Value=Value>>1;
if(IRbit==18)
{
rUserID=Value;
Value=0;
}
Cnt256=0;
TR0=1;
}else if(IRbit<=26)
{
TR0=0;
if(Cnt256<6) Value=Value & 0x7F;
else if(Cnt256>=6) Value=Value | 0x80;
Value=Value>>1;
if(IRbit==26)
{
OprCode=Value;
Value=0;
}
Cnt256=0;
TR0=1;
}else if(IRbit<=33)
{
TR0=0;
if(Cnt256<6) Value=Value & 0x7F;
else if(Cnt256>=6) Value=Value | 0x80;
Value=Value>>1;
if(IRbit==33)
{
rOprCode=Value;
Value=0;IRbit=0;
//***************************************************************
Send_String_Com("H",1);
Send_Char_Com(HEX[UserID/16]);Send_Char_Com(HEX[UserID%16]);
Send_Char_Com(HEX[rUserID/16]);Send_Char_Com(HEX[rUserID%16]);
Send_Char_Com(HEX[OprCode/16]);Send_Char_Com(HEX[OprCode%16]);
Send_Char_Com(HEX[rOprCode/16]);Send_Char_Com(HEX[rOprCode%16]);
Send_String_Com("\r\n",2);
REC_LED=1;Delay(200);REC_LED=0; //灯闪
TR0=0;Cnt256=0;EA=1;EX1=0; //恢复INT1中断
return ;
//****************************************************************
}
Cnt256=0;
TR0=1;
}
EA=1;
}
EX1=0; //恢复INT1中断
}
void EnableINT0(bit En) //设置INT0工作模式
{
// EA=0;
if(~IRMode) IT0=0;else IT0=1; //RC5编码采用INT0采用低电平触发中断;RECS80采用后沿触发.
EX0=En; //开/关INT0中断
// EA=1;
}
void EnableINT1(bit En) //使能INT1中断.
{
IT1=1; //INT1采用后沿触发.
if (En) EX1=1;else EX1=0; //开启/关闭INT1中断
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -