/*******标准NEC编码遥控器*********/
/*采用PCA高速脉冲输出实现脉冲调制*/
/******红外载波信号频率38KHz******/
/*******YUAN HUA FEI*******/
#include<STC15W408AS.h>
#define uchar unsigned char
#define uint unsigned int
#define TOG0_OPEN 0X04//PCA翻转控制位开
#define TOG0_CLOSE 0XFB//PCA翻转控制位关
#define KEY P1 //矩阵键盘在P1口,P10~P15
sbit Ir = P3^7; //脉冲信号输出端口
uchar xdata CODEA=0X28;//用户码1
uchar xdata CODEB=0X04;//用户码2
uint xdata TS =0; //中断计数
uchar xdata Keycode; //存放读取到的键值
void delayms(uint ms)
{
uchar x,y;
for(ms;ms>0;ms--)
for(x=250;x>0;x--)
for(y=12;y>0;y--);
}
void Init_PCA() //初始化PCA
{
CMOD = 0x02; //设置PCA时钟源为系统时钟SYSclk/2
CCON = 0; //初始化PCA控制寄存器
CCAPM2 = 0X4D;//高速脉冲输出模式
CL = 0;
CH = 0; //当计数器值等于PCA寄存器值产生中断一次
CCAP2L =0X8A; //设置PCA寄存器初值
CCAP2H =0X00;
CR = 0; //PCA定时器关闭工作
EA = 1;
}
void PCA_INT() interrupt 7 using 1
{
TS++;
CCF2 = 0;//清中断标志
CL = 0; //复位PCA计数器
CH = 0;
}
void Infrared(uchar dat)
{
uchar xdata m,n;
uchar xdata user_code;//用户码
uchar xdata data_code;//数据码
CR = 1;
CCAPM2 |=TOG0_OPEN;//允许脉冲输出脉冲
while(TS<687);//9ms脉冲
TS = 0;
CCAPM2 &=TOG0_CLOSE;//关闭脉冲输出脉冲
Ir = 0;
while(TS<343);//4.5ms低电平
TS = 0;
for(m=0;m<2;m++)
{
if(m==0)user_code=CODEA;//用户码1
else user_code=CODEB;//用户码2
for(n=0;n<8;n++)//从最低位依次发送
{
if(user_code &0X01)
{
CCAPM2 |=TOG0_OPEN;//允许翻转输出脉冲
while(TS<43);//0.56ms脉冲
TS = 0;
CCAPM2 &=TOG0_CLOSE;//关闭翻转输出脉冲
Ir = 0;
while(TS<129);//1.69ms低电平
TS = 0;
}
else
{
CCAPM2 |=TOG0_OPEN;//允许翻转输出脉冲
while(TS<43);//0.56ms脉冲
TS = 0;
CCAPM2 &=TOG0_CLOSE;//关闭翻转输出脉冲
Ir = 0;
while(TS<43);//0.565ms低电平
TS = 0;
}
user_code >>=1;
}
}
for(m=0;m<2;m++)
{
if(m==0)data_code= dat;//数据码
else data_code=~dat;//数据码反码
for(n=0;n<8;n++)//从最低位依次发送
{
if(data_code &0X01)
{
CCAPM2 |=TOG0_OPEN;//允许翻转输出
while(TS<43);//0.56ms脉冲
TS = 0;
CCAPM2 &=TOG0_CLOSE;//关闭翻转输出
Ir = 0;
while(TS<129);//1.69ms低电平
TS = 0;
}
else
{
CCAPM2 |=TOG0_OPEN;//允许翻转输出
while(TS<43);//0.56ms脉冲
TS = 0;
CCAPM2 &=TOG0_CLOSE;//关闭翻转输出
Ir = 0;
while(TS<43);//0.565ms低电平
TS = 0;
}
data_code >>=1;
}
}
CCAPM2 &=TOG0_CLOSE;//关闭脉冲输出
CR = 0;Ir = 0;
}
void Key_code() //4X2矩阵键盘
{
char n=0;//按键释放时间,连按操作时可一直按着
KEY=0X3C;//先设置列输出低电平
if(KEY!=0X3C) //判断是否有按键按下
{
delayms(10);//延时消除按键抖动
if(KEY!=0X3C)//再次检测键盘是否按下
{
switch(KEY)//获取键码行值
{
case(0X38): Keycode=1;break;//第1行
case(0X34): Keycode=2;break;//第2行
case(0X2C): Keycode=3;break;//第3行
case(0X1C): Keycode=4;break;//第4行
}
}
KEY=0X03;//设置行输出低电平
delayms(1);//延时等待I/O口翻转再检测
if(KEY!=0X03)//再次检测键盘是否按下
{
switch(KEY)//将行值与列值相加得到键码
{
case(0X02):Keycode+=0;break;//第1列
case(0X01):Keycode+=4;break;//第2列
}
}
while((n<50)&&(KEY=0X03))//等待按键释放或计时退出
{
delayms(5);
n++;
}
Infrared(Keycode);//发送键码 数据
}
}
void main()
{
P3M0 = 0X80;//将P37设置为推挽输出模式
P3M1 = 0X00;
Init_PCA();
while(1)
{
Key_code();
}
} |