/********************************************************************
红外遥控NEC解码程序:
通过串口将红外遥控的按键解码到电脑上。
红外遥控:采用NEC编码格式的38K通用红外遥控器
四位数码管:TM1637四位数码管显示模块
*********************************************************************/
#include <reg52.h>
#include "intrins.h" //包含_nop_()指令头文件
#define nop _nop_();_nop_();_nop_();_nop_();_nop_(); //宏定义
typedef unsigned char uchar;
uchar count;
uchar wedat[33];
uchar dat[4];
bit receive_flag , chuli_data_ok;
/********************定义控制端口**********************/
sbit CLK=P2^2; //定义CLK
sbit DIO=P2^3; //定义DIO
sbit bus=P3^2; //红外中断为外部中断0
/********************定义数据*************************/
unsigned char code CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //共阴显示数据0-F
/********************延时函数,延时nms******************/
void delay_nms(unsigned int n)
{
unsigned int i;
while(n--)
for(i=0;i<550;i++);
}
/********************Start函数*************************/
void I2CStart()
{
DIO=1;
CLK=1;
nop;
DIO=1;
nop;
DIO=0;
nop;
CLK=0;
}
/********************Stop函数*************************/
void I2CStop()
{
CLK=0;
nop;
nop;
DIO=0;
nop;
nop;
CLK=1;
nop;
nop;
nop;
DIO=1;
nop;
CLK=0;
DIO=0;
}
/***************发送8bit数据,从低位开始**************/
void I2CWritebyte(unsigned char oneByte)
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK=0;
if(oneByte&0x01)
DIO=1;
else
DIO=0;
nop;
CLK=1;
oneByte=oneByte>>1;
}
//8位数据传送完
CLK = 0; //判断芯片发过来的ACK应答信号
nop;
while(DIO==1);
nop;
CLK = 1;
nop;
}
/************显示函数,固定地址写数据************/
void disp(unsigned char add,unsigned char value)
{
I2CStart();
I2CWritebyte(0x40);
I2CStop();
I2CStart();
I2CWritebyte(add); //地址命令设置:写入add对应地址
I2CWritebyte(value); //给add地址写数据
I2CStop();
I2CStart();
I2CWritebyte(0x8a); //显示控制命令:开显示,脉冲宽度为11/16.
I2CStop();
}
/********************************************************************
中断与定时的初始化程序
*********************************************************************/
void init()
{
//定时器初始化
TMOD=0x22;//定时器1,0都是8位自动重装寄存器
RCAP2H=0xfe; // 寄存器对(RCAP2H、RCAP2L)是定时器2 在16 位捕获方式
RCAP2L=0xff; // 或16 位自动重装载方式下的捕获/自动重装载寄存器。
TH2=(65535-256)/256;
TL2=(65535-256)%256;
EA=1;
ET2=1;
//红外中断初始化
IT0=1; //红外外部中断0,脉冲信号的下降沿触发
EX0=1; //外部中断0允许位
}
void timer0() interrupt 5
{
TF2=0;
count++;
}
/********************************************************************
红外中断服务程序
*********************************************************************/
void EX_INT0() interrupt 0 //红外遥控信号进入中断服务程序
{
static uchar num; //静态变量,每次进入其值不变,num是每个脉宽的编号
static uchar flag,flag1; //辅助标志位
TR2 = 1; //当IT0下降沿发生,脉宽进入,打开定时器2
if(flag == 1) //第一次flag=0,不执行下面程序,直接出中断程序,下次进入执行
{
if(( count < 60) && (count >= 40) ) //检测起始码宽度,符合条件进入
{
num = 0; //起始码编号为0,存入数组中
flag1 = 1; //辅助标志位,用于进入下面程序
}
}
if(flag1 == 1) //第二次进入中断后将33和脉宽依次存入数组中,编号为0~32
{
wedat[num] = count; //读取T2定时器中断程序中的计数值
count = 0; //都去完成后,清零
num++; //编号++
}
flag = 1; //第一次flag=0,第二次进入后为1,开始执行脉宽存储程序
if(num > 32) //如果num大于32,也就是说33个脉宽都存入了,0~32,33个。1位起始码,16位用户码,16位键码
{
receive_flag = 1; //存储完成后标志位置1,用于主函数中判断
num = 0; //编号清零,用于下次按键后,红外进入
flag = 0; //辅助标志位清零
flag1 = 0; //辅助标志位清零
TR2 = 0; //关闭定时器T2,等待下次按键后,进入中断程序再次启动
}
}
/********************************************************************
处理脉宽数据
*********************************************************************/
void chulidata() //处理存储脉宽的数组
{
uchar i,j,z=1,byte,temp; //此处z=1,是因为wedat[0]是起始码,z=1可以将起始码直接过
for( i=0 ; i<4 ; i++ ) //4个字节处理
{
for( j = 0 ; j < 8 ; j++ ) //8位依次处理
{
temp = wedat[z]; //将每个数组里的脉宽赋值给变量temp
if(temp > 6) //如果32个脉宽中哪个脉宽计数时间大于6,也就是1536us,那肯定就是1
{
byte = byte | 0x80; //如果是1,那就给byte的最高位置1
}
if( j < 7 ) //如果一个字节还没处理完
{
byte = byte >> 1; //每次循环到这里,byte的每一位都右移一位,也就
}
z++; //每处理完一个字节,序号Z++,共处理4个字节
}
dat[i] = byte; //将byte赋值,依次给dat[0],dat[1],dat[2],dat[3]
byte = 0; //byte清零;
}
chuli_data_ok = 1; //4个字节接收完毕标志位,用于主函数判断
}
/********************************************************************
主函数
*********************************************************************/
void main()
{
int i=0;
init();
while(1)
{
if(receive_flag) //判断是否接收并储存脉宽完毕
{
chulidata(); //处理数据
receive_flag=0; //标志位置0
if(chuli_data_ok) //如果4个字节数据处理完成
{
SBUF=dat[2]; //依次上送
if(dat[2]==0x15)
{
i++;
if(i==10) i=0;
disp(0xc0,CODE[i]); //第一段数码管显示
delay_nms(1);
disp(0xc1,CODE[i]); //第二段数码管显示
delay_nms(1);
disp(0xc2,CODE[i]); //第三段数码管显示
delay_nms(1);
disp(0xc3,CODE[i]); //第四段数码管显示
delay_nms(1);
}
if(dat[2]==0x07)
{
i--;
if(i==0) i=9;
disp(0xc0,CODE[i]); //第一段数码管显示
delay_nms(1);
disp(0xc1,CODE[i]); //第二段数码管显示
delay_nms(1);
disp(0xc2,CODE[i]); //第三段数码管显示
delay_nms(1);
disp(0xc3,CODE[i]); //第四段数码管显示
delay_nms(1);
}
while(!TI); //是否上送完毕
TI = 0; //将传送成功标志位置0
chuli_data_ok=0; //标志位置0
}
}
}
}
评论0