📄 红外.c
字号:
#include <at89x51.H>
#define IR_SYSCODE 0x00
#define SEGMENT P0
#define BIT_LED P2
void delay_100us(void);
void key_process(void);
void ir_init(void) ;
void display(void) ;
void breakdata(void);
void delay1s(void);
unsigned char ir_data;
bit ir_flag;
unsigned char ir_repeat;
unsigned char data display_bit,display_buffer[8];
unsigned char data time0_h,time0_l;
unsigned int idata time0_times;
unsigned int showdata;
unsigned char data TEMP;
int *point;
unsigned int shdata;
unsigned int keyin;
unsigned int kbempty;
unsigned char dataIR[6];//dataIR 0:syscode0
unsigned char width; // 1:syscode1
/**********************主程序********************************************************/
void main( void)
{
int q;
ir_init();
for(q=0;q<5;q++)
{
P0_7=1;
delay1s();
P0_7=0;
delay1s();
}
while(1)
{
unsigned int l,m;
for(m=0;m<6;m++)
{
for(l=0;l<2000;l++)
{
showdata=dataIR[m];
display();
}
}
//display();
/*1showdata=dataIR[1];
display();
delay1s();
showdata=dataIR[2];
display();
delay1s();
showdata=dataIR[3];
display();
delay1s();
showdata=dataIR[4];
display();
delay1s();
showdata=dataIR[5];
display();
delay1s();*/
}
}
void ir_init(void)
{
IE = 0x00;
EA = 1;
IT1 = 1;
EX1 = 1; /* Enable External Interrupt1 INT1 */
ir_flag = 0; /* Initialize ir_flag, Receive success mark. */
ir_repeat = 0; /* Initialize ir_repeat, Repear mark. */
ir_data = 0;
display_bit=1;
dataIR[6]=0X00;
}
/***************中断程序*****************************************/
void ir_svr(void) interrupt 2
{
unsigned char i=0; // 2:data
EX1 = 0; // 3:data negation
width = 0x00; // 4:oxoo end-mark
while(!P3_3) /* 计算引导电平的宽度 , 常规状态下INT1为高电平,由高电平跳变为低电平时(即下降沿)产生中断 */
{
delay_100us();//引导信号:9ms低电平
width++;
}
if (width < 80) /* 8ms=80*100us 如果不到8ms视为干扰信号 */
{
EX1 = 1; /* if low-level short than 9ms,then reset receiver 允许外部中断*/
return;
}
// 计算4.5ms低电平宽度
width = 0x00;
while(P3_3) /* Wait for boot signal 4.5ms high-level */
{
delay_100us();
width++; /* note width */
}
/* 判断是否是重复信号 2.5ms */
if (width < 30) /* 3ms=30*100us 如果不到3ms即视为2.5ms重复信号 */
{
ir_repeat++;
if(ir_repeat>2)
{
ir_flag = 1;
ir_repeat = 0;
}
EX1 = 1;
return;
}
ir_repeat = 0;
/* Receive new_press */
// 4.5ms新键码引导电平
if (width < 40) /* 4ms=40*100us 如果不到4ms视为错误信号,放弃接收 */
{
EX1 = 1;
return;
}
// 至此,引导码已校验,以下接收地址码和数据码,一共32位
while(i++ <48) /* receive 32bits */
{
while(!P3_3); /* Wait for 0.5625ms low-level passed */
width = 0x00;
while(P3_3) /* Wait for data signal high-level "1" 1680us; "0" 560us */
{
delay_100us();
width++; /* note high-level width */
}
ir_data <<= 1;
if (width > 0x08) /* identify "1" or "0" */
ir_data |= 0x01;
if (i==8) /* note IR_receive data */
dataIR[0] = ir_data;
if (i==16)
dataIR[1] = ir_data;
if (i==24)
dataIR[2] = ir_data;
if (i==32)
dataIR[3] = ir_data;
if (i==40)
dataIR[4]=ir_data;
if (i==48)
dataIR[5]=ir_data;
}
/* if (dataIR[2] != ~dataIR[3]) // 纠错较验
{
EX1 = 1;
return;
}*/
// 判断地址码是否正确
// if(dataIR[0] != IR_SYSCODE)
// return;
ir_data = dataIR[2];
ir_flag = 1; /* receive successful flag */
EX1 = 1;
for(i=0;i<4;i++)
{ P0_7=1;
delay1s();
P0_7=0;
delay1s();
delay1s();
}
}
/***********************************************************************************/
void polling_ir(void)
{
if(!ir_flag) // if no key press, direct return.
return;
else
ir_flag = 0;
// 功能处理
if(INT0)
P1 = ir_data; // display key_code to P1 with BCD
else
key_process(); // execute special function
//_nop_();
}
// 延时 100us
// crystal frequence: 12M Tosc = 1us
// DJNZ 指令 双字节 两周期 耗时 2*Tosc = 2*1us = 2us
// delay time = 2us * 48 = 96us
void delay_100us(void)
{
unsigned char i=48;
while(--i);
}
/****************display *********************/
/***********************************************/
unsigned char get_code (unsigned char i)
{
unsigned char p;
switch(i)
{
case 0: p=0x3F; break; /*0*/
case 1: p=0x06; break; /*1*/
case 2: p=0x5B; break; /*2*/
case 3: p=0x4F; break; /*3*/
case 4: p=0x66; break; /*4*/
case 5: p=0x6D; break; /*5*/
case 6: p=0x7D; break; /*6*/
case 7: p=0x07; break; /*7*/
case 8: p=0x7F; break; /*8*/
case 9: p=0x67; break; /*9*/
case 10: p=0x77; break; /*A*/
case 11: p=0x7C; break; /*B*/
case 12: p=0x39; break; /*C*/
case 13: p=0x5E; break; /*D*/
case 14: p=0x79; break; /*E*/
case 15: p=0x71; break; /*F*/
case 16: p=0x00; break; /*灭灯*/
default: break;
}
return ((~p) & 0x7F);
}
/**************************************************/
void display(void)
{
int f;
//showdata=dataIR[2];
breakdata();
for(f=0;f<6;f++)
{unsigned char i;
switch(display_bit)
{
case 1:i=0;break;
case 2:i=1;break;
case 4:i=2;break;
case 8:i=3;break;
case 16:i=4;break;
// case 32:i=5;break;
// case 64:i=6;break;
// case 128:i=7;break;
default:break;
}
BIT_LED=0;
SEGMENT=get_code(display_buffer[i]);
TEMP=SEGMENT;
BIT_LED=display_bit;
if(display_bit<0X32)
{display_bit=display_bit*2;}
else display_bit=0x01;
}
}
/******************数据拆分**********************/
void breakdata(void)
{ int j;
for(j=0;j<6;j++)
{
display_buffer[j]=showdata%16;
showdata=showdata/16;
//*(point+1);
}
}
/*******************************延时13us*********************************/
void delay1s(void)
{int i,j,k;
for(i=0;i<100;i++)
{for(j=0;j<30;j++)
{for(k=0;k<1;k++);}
}
}
/* 通常来说不器可以,但是最好配置一个计数器,主要用来做带宽处理,方便与由于硬件造成速率偏差的校正 [smilez] 2005-10-23 14:19:27
· 不好:所有的ir处理在中断处理!这不好 [xiaoliu5116] 2005-10-23 15:11:41
有更好的方法:每次中断,读Time值,得到一位数据的值:lead code 或repeat code 或数
据
!这样,系统反映速度快!ltisn的方法有个问题:一次ir解收 如果你的系统有led,当有ir时,你的led闪的很厉害!*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -