包含了红外解码,自动根据波特率设置定时器溢出率以及使用定时器延时
串口部分:
void UART1_Init(u32 Boud)
{
u16 Temp = (65536 - FOSC/Boud/4);
SCON = 0x50;
T2L = Temp;
T2H = Temp >> 8;
AUXR |= 0x15; //启动定时器
ES = 1; //使能串口中断
}
char putchar(u8 c)
{
SBUF = c;
while(!TI);
TI = 0;
return c;
}
void UART1_ISR() interrupt 4 using 1
{
if(RI)
{
RI = 0; //清中断标志
}
// if(TI)
// {
// TI = 0; //清中断标志
// }
}
//定时器延时部分
#include "delay.h"
#define TICK_US (FOSC/1000000/12)
volatile u16 told = 0; //计数器旧值
volatile u16 tnow = 0; //计数器新值
volatile u16 tick = 0; //计数值
volatile u16 delay_tick = 0; //延时计数值
void delay_init(void)
{
T4L = 0;
T4H = 0;
T4T3M &= 0x0F;
T4T3M |= B1000_0000; //启动定时器 12T
told = 0;
tnow = 0;
tick = 0;
delay_tick = 0;
}
void delay(u16 us)
{
told = T4H << 8 | T4L;
tnow = 0;tick = 0;
delay_tick = us * TICK_US;
while(1)
{
tnow = T4H << 8 | T4L;
if(tnow != told)
{
if(tnow > told)
{
tick += tnow - told;
}
else //定时器溢出
{
tick += 65535 + tnow - told;
}
told = tnow;
if(tick >= delay_tick)
break;
}
}
}
//红外解码
#include "INT.h"
#include "USART.h"
u8 IR_Cnt = 0;
#define T51 (FOSC/1000000/12)
#define REMOTE_ID 0
//遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留
//[4]:标记上升沿是否已经被捕获
//[3:0]:溢出计时器
u8 IR_sta = 0;
u32 IR_Rec = 0;
sbit INT0 = P3^2;
void IR_Init(void)
{
IT0 = 0; //使能INT0上升沿和下降沿中断
EX0 = 1; //使能INT0中断
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TF0 = 0; //清除TF0标志
TL0 = 0; //设置定时初值
TH0 = 0; //设置定时初值
TR0 = 0; //定时器0开始计时
ET0 = 1;
}
//处理红外键盘
//返回值:
// 0,没有任何按键按下
//其他,按下的按键键值.
u8 IR_Scan(void)
{
u8 Key = 0;
if(IR_sta & (1<<6))//得到一个按键的所有信息了
{
u8 TEMP[2];
TEMP[0] = IR_Rec>>24; //得到地址码
TEMP[1] = (IR_Rec>>16)&0xff; //得到地址反码
if((TEMP[0] == (u8)~TEMP[1]) && TEMP[0] == REMOTE_ID)//检验遥控识别码(ID)及地址
{
TEMP[0] = IR_Rec>>8;
TEMP[1] = IR_Rec;
if(TEMP[0] == (u8)~TEMP[1])
Key = TEMP[0];//键值正确
}
if(Key == 0||(IR_sta&0X80) == 0)//按键数据错误/遥控已经没有按下了
{
IR_sta&=~(1<<6);//清除接收到有效按键标识
IR_Cnt = 0; //清除按键次数计数器
}
}
return Key;
}
void INT0_ISR(void) interrupt 0 using 1
{
if(INT0)//上升沿捕获
{
TL0 = 0; //设置定时初值
TH0 = 0; //设置定时初值
TR0 = 1; //定时器0开始计时
IR_sta |= 0X10; //标记上升沿已经被捕获
}
else //下降沿捕获
{
u16 Count_Time = 0;
Count_Time = TH0 << 8|TL0;
TL0 = 0; //设置定时初值
TH0 = 0; //设置定时初值
if(IR_sta & 0X10) //完成一次高电平捕获
{
if(IR_sta & 0X80)//接收到了引导码
{
if(Count_Time > (300 * T51) && Count_Time < (800 * T51)) //560为标准值,560us
{
IR_Rec <<= 1; //左移一位.
IR_Rec |= 0; //接收到0
}
else if(Count_Time > (1400 * T51) && Count_Time < (1800 * T51)) //1680为标准值,1680us
{
IR_Rec <<= 1; //左移一位.
IR_Rec |= 1; //接收到1
}
else if(Count_Time > (2200 * T51) && Count_Time < (2600 * T51)) //得到按键键值增加的信息 2500为标准值2.5ms
{
IR_Cnt++; //按键次数增加1次
IR_sta&=0XF0; //清空计时器
}
}
else if(Count_Time > (4200 * T51) && Count_Time < (4700 * T51)) //4500为标准值4.5ms
{
IR_sta|=1<<7; //标记成功接收到了引导码
IR_Cnt=0; //清除按键次数计数器
}
}
IR_sta &=~(1<<4);
}
}
void TIME0_ISR(void) interrupt 1 using 1
{
TL0 = 0; //设置定时初值
TH0 = 0; //设置定时初值
if(IR_sta&0x80)//上次有数据被接收到了
{
IR_sta &= ~0X10; //取消上升沿已经被捕获标记
if((IR_sta&0X0F) == 0X00)
IR_sta|=1<<6;//标记已经完成一次按键的键值信息采集
if((IR_sta&0X0F) < 14)
IR_sta++;
else
{
TR0 = 0; //定时器0开始计时
IR_sta&=~(1<<7);//清空引导标识
IR_sta&=0XF0; //清空计数器
}
}
}
|