最近自己在网上搜了很多资料,发现很多的红外解码,关于重码的处理的代码很少,分享一下红外解码包括重码的处理。
使用单片机:EN8F156
功能说明:红外遥控器解码,只使用定时器T0定时100us进行按键解码,处理按键短按与长按,将解码的数据通过串口打印。
/***************************************
功能说明:红外遥控器解码,定时器T0定时100us进行按键解码,处理按键短按与长按,串口打印解码数据。
****************************************/
#include "SYSCFG.h"
#define uchar unsigned char
#define uint unsigned int
#define IR_PIN PA2 //红外输入
#define PIN_TX PC0 //串口发射
//IR接收变量
#define IR_Long_Time 20 //110*20 = 2200ms
uchar Receive_Count = 0; //红外接收计位数
uchar Low_Level_Time = 0; //低电平时间
uchar High_Level_Time = 0; //高电平时间
uchar UserCode_High = 0;
uchar UserCode_Low = 0; //存放用户码1
uchar Data_Code = 0; //存放数据码
uchar IR_Temp = 0; //存放数据码反码
uchar Repeat_Count = 0; //重码计数
//IR接收标志
bit Data_Receive_Flag = 0; //数据接收标志
bit Begin_Flag = 0; //同步码标志
bit Receive_Error_Flag = 0; //接收失败
bit Start_Receive_Flag = 0; //开始标志
bit Receive_Over_Flag = 0; //键码解码完毕
bit Repeat_Flag = 0; //重码标志
bit Ready_Repeat_Det_Flag = 0; //准备接受重码
/*-------------------------------------------------
* 函数名:POWER_INITIAL
* 功能: 上电系统初始化 系统时钟4MhZ/2 = 2MhZ
* 输入: 无
* 输出: 无
--------------------------------------------------*/
void MCU_INIT(void)
{
OSCCON = 0B01010001;//WDT 32KHZ IRCF=101=4MHZ/2=2MHZ,0.5US/T
//Bit0=1,系统时钟为内部振荡器
//Bit0=0,时钟源由FOSC<2:0>决定即编译选项时选择
OPTION = 0B00001000;//Bit4=1 WDT MODE,PS=000=1:1 WDT RATE
//Bit7(RAPU)=0 ENABLED PULL UP PA
TRISA = 0x04; //PA2输入
TRISC = 0x00; //
PORTA = 0B00000000; //
PORTC = 0B00000000; //
WPUA = 0B00000000; //PA端口上拉控制 1-开上拉 0-关上拉
WPUC = 0B00000000; //PC端口上拉控制 1-开上拉 0-关上拉
MSCKCON = 0B00000000;//6B->0,禁止PA4,PC5稳压输出
//5B->0,TIMER2时钟为Fosc
//4B->0,禁止LVR
CMCON0 = 0B00000111; //关闭比较器,CxIN为数字IO口
ANSEL = 0B00000000; //关闭模拟输入
PAIF =0; //清 PA INT中断标志位
PAIE =0; //关闭 PA INT中断
GIE = 1;
}
//**************中断处理**********************************
void interrupt ISR(void)//PIC_HI-TECH使用
{
//定时器0的中断处理**********************
if(T0IE && T0IF)//100us
{
TMR0 = 76; //注意:对TMR0重新赋值TMR0在两个周期内不变化
if(IR_PIN==0) //低电平期间。
{
if(Data_Receive_Flag==1) //是否找到同步头?如果找到同步头就由低到高开始接收
{
if(High_Level_Time>=13&&High_Level_Time<=20) //是高电平 1690us
{
Receive_Count++;
IR_Temp>>=1; //右移动一位
IR_Temp=IR_Temp|0x80; //高位补1
}
else if(High_Level_Time>=2&&High_Level_Time<=8) //是低电平 560us
{
Receive_Count++;
IR_Temp>>=1; //右移一位,高位补0
}
else
Receive_Error_Flag=1;
if(Receive_Error_Flag==1) //数据错误,重新解码
{
Begin_Flag=0;
Receive_Count=0;
}
else
{
if(Receive_Count==8)
UserCode_High=IR_Temp; //用户码高
if(Receive_Count==16) //用户码低
UserCode_Low=IR_Temp;
if(Receive_Count==24) //键码
Data_Code=IR_Temp;
}
if(Receive_Count==32) //32位数据接收完毕
{
Begin_Flag=0;
Receive_Over_Flag = 1;
}
}
if(High_Level_Time>30&&High_Level_Time<60) //判断同步头 4.5ms
{
Begin_Flag=1; //检测正确的同步头
Receive_Count=0; //接收位数,清除0
Data_Code = 0; //收到正确的引导码将上一次的键码清零
Ready_Repeat_Det_Flag = 0;
Repeat_Flag = 0;
Repeat_Count = 0;
}
if(Ready_Repeat_Det_Flag) //重码检测
{
if(High_Level_Time>15&&High_Level_Time<=30) //收到 低脉冲8ms+高脉冲2.5ms 认为是重码 每隔110ms收到重码
{
Repeat_Count++;
if(Repeat_Count >= IR_Long_Time) //长按时间设置110*20 = 2200ms
{
Repeat_Count = IR_Long_Time-1;
Repeat_Flag = 1; //长按标志 需手动清标志
}
}
}
Low_Level_Time++; //低脉冲计数
High_Level_Time=0;
Data_Receive_Flag=0;
Receive_Error_Flag=0; //接收失败标志
Start_Receive_Flag=1; //开始接收
}
if(Start_Receive_Flag==1)
{
if(IR_PIN==1) //高电平期间
{
High_Level_Time++; //高脉冲计数
if(Begin_Flag==1) //收到正确的引导码 低9ms+高4.5ms 准备接收32位数据
Data_Receive_Flag=1; //数据接收标志
else
{
if(Low_Level_Time>80&&Low_Level_Time<110)
{
Ready_Repeat_Det_Flag = 1; //准备重码检测
}
Low_Level_Time = 0; //清低脉冲计数
}
}
}
T0IF = 0;
}
}
/*-------------------------------------------------
* 函数名称:TIMER0_INITIAL
* 功能:初始化设置定时器v
* 相关寄存器:
* 设置TMR0定时时长100us
-------------------------------------------------*/
void TIMER0_INITIAL (void)
{
//OPTION = 0B00000111;
//Bit5 T0CS Timer0时钟源选择
//1-外部引脚电平变化T0CKI 0-内部时钟(FOSC/2)
//Bit4 T0CKI引脚触发方式 1-下降沿 0-上升沿
//Bit3 PSA 预分频器分配位 0-Timer0 1-WDT
//Bit2:0 PS2 8个预分频比 000 - 1:2
TMR0 = 56;
T0IF = 0;//清空T0软件中断
T0IE = 1;//开定时器/计数器0中断
}
/*-------------------------------------------------
* 函数名称:100us延时
* 功能:
* 输入参数:Time 延时时间长度 延时时长TimeUs
* 返回参数:无
-------------------------------------------------*/
void delay100us(void)
{
unsigned char Time;
Time = 26;
while(Time--)
{
//NOP();
}
}
/*-------------------------------------------------
* 函数名称:DelayMs
* 功能: 短延时函数
* 输入参数:Time 延时时间长度 延时时长Timems
* 返回参数:无
-------------------------------------------------*/
void DelayMs(unsigned char Time)
{
unsigned char a,b;
for(a=0;a<Time;a++)
{
for(b=0;b<10;b++)
{
delay100us(); //快1%
}
}
}
/*-------------------------------------------------
* 函数名称:IO口模拟串口发射
* 功能:
* 输入参数:
* 返回参数:无
-------------------------------------------------*/
void TxSend(uchar dat)//发送八位数据
{
uchar i;
GIE = 0;
PIN_TX = 0;
delay100us();
for(i=0; i<8; i++)
{
if(dat & 1) PIN_TX = 1;
else PIN_TX = 0;
dat >>= 1;
delay100us();
}
PIN_TX = 1;
GIE = 1;
delay100us();
delay100us();
}
/*-------------------------------------------------
* 函数名称:红外按键处理
* 功能: 处理键码和重复码
* 输入参数:
* 返回参数:
-------------------------------------------------*/
void IR_HANDLE(void)
{
if(Receive_Over_Flag) //短按处理
{
Receive_Over_Flag = 0;
TxSend(Data_Code); //将短按的键码打印
}
if(Repeat_Flag) //长按处理
{
Repeat_Flag = 0;
if(Data_Code == 0x45) //键码=0x45
{
TxSend(0xaa); //如果是0x45长按 发送0xaa
}
}
}
/*********************************************************
* @说明 main
* @参数 无
* @返回 无
* @注意
******************************************************/
void main(void)
{
MCU_INIT();
TIMER0_INITIAL();
while(1)
{
IR_HANDLE();
}
}