📄 irrecv.c
字号:
/*********************************************************************/
/* 模 块 名:单片机(C51) 文件名:IRRecv.c */
/* 提交日期:2006年1月01日 作 者:金雨和(jinyuhe@163.com) */
/* 版 本:V1.0 --Copyright(c) 2006-2008 */
/* 描 述:单片机(C51)红外接收程序 */
/* 修改记录: */
/* 日 期 版本 修改人 修改内容 */
/* 1. */
/*********************************************************************/
#include <Reg935.h>
#include <stdio.h>
#include "uart.h"
/* IO脚定义 */
#define IR_SIGNAL KB0 //红外输入
#define IR_LED TxD //红外指示灯信号
#define RDIR OCB //reserved
#define IIC_INT KB1 //IIC中断脚
#define QUIETLED KB3 //静音指示灯
#define MUTELED KB6 //哑音指示灯
/* 脉冲检测范围定义,此脉冲通过定时器0检测,故脉冲宽度与定时器定时器值设置有关 */
/* 当定时器0为方式2时,定时值为TH0=00x10,TL0=0x10时,采用如下组值 */
#if 0
#define MIN_BIT0_PLS 9 //bit 0 脉冲宽度最小值
#define MAX_BIT0_PLS 16 //bit 0 脉冲宽度最大值
#define MIN_BIT1_PLS 37 //bit 1 脉冲宽度最小值
#define MAX_BIT1_PLS 45 //bit 1 脉冲宽度最大值
#define MIN_CODE_PLS 100 //前导码脉冲宽度最小值
#define MAX_CODE_PLS 125 //前导码脉冲宽度最大值
#define MIN_CONT_PLS 52 //连续按键脉冲宽度最小值
#define MAX_CONT_PLS 60 //连续按键脉冲宽度最大值
#define INVALID_PLS 200 //大于此值认为是无效脉冲值
#endif
/* 当定时器0为方式1时,定时值为TH0=00x10,TL0=0x10时,采用如下组值 */
#define MIN_BIT0_PLS 3 //bit 0 脉冲宽度最小值
#define MAX_BIT0_PLS 7 //bit 0 脉冲宽度最大值
#define MIN_BIT1_PLS 14 //bit 1 脉冲宽度最小值
#define MAX_BIT1_PLS 19 //bit 1 脉冲宽度最大值
#define MIN_CODE_PLS 40 //前导码脉冲宽度最小值
#define MAX_CODE_PLS 50 //前导码脉冲宽度最大值
#define MIN_CONT_PLS 21 //连续按键脉冲宽度最小值
#define MAX_CONT_PLS 24 //连续按键脉冲宽度最大值
#define INVALID_PLS 90 //大于此值认为是无效脉冲值
/* 标志位定义 */
bit g_rsFlag; //收到一键码
bit g_RSDA1; //引导码第一个下降沿指示,表示可能一按键到来
bit g_RSDA2; //可能一有效高脉冲
bit g_RSDA3; //误码,非有效按键
bit g_IR_SF; //连续按键指示
/* 键值及用户码保存字 */
unsigned char data g_rsData; //键码,返回给主程序
unsigned char data g_insr0; //定时器一计数器,一次中断为0.1ms,主要记录脉冲宽度
unsigned char data g_insr1; //Insr1=(valid)insr0 transfer to int1
unsigned char data g_pulseNum; //脉冲数,一个键码总共有33个脉冲信号
unsigned char data g_keyUser; //user code
unsigned char data g_keyValue; //key value
unsigned char data g_keyValueF; //用户码反码
unsigned char data g_keyUserF; //键值反码
unsigned char data g_keyPressed; //连续按键不放,spying the continue pressing a key
extern unsigned char xdata g_ucI2CSendBuf[MAX_I2CDATALEN]; //IIC数据缓存
extern unsigned char xdata g_ucI2CSendBuf_Len; //IIC数据缓存内容长度
extern unsigned char xdata g_ucI2CSendBuf_offset; //IIC缓存数据读取当前位移
/*******************************************************************
** 函 数 名: IRRecvInit()
** 输 入: 无
** 输 出: 无
** 描 述: 红外接收初始化。
** 全局变量:
** g_pulseNum -- 脉冲数
** g_keyPressed -- 连续按键标志
** g_rsFlag -- 标志,表示已正确接收到红外键码
** 调用模块: 无
** 被调模块: 无
** 作 者:
** 创建日期: 2006年1月15日
** 修 改:
** 日 期 版本 修改人 修改内容
** 1.
********************************************************************/
void IRRecvInit()
{
/* ------------------ 初始化 ------------------------- */
g_rsFlag = 0; //No active
g_IR_SF = 0; //连续按键指示
g_RSDA1 = 0; //引导码第一个下降沿指示,表示可能一按键到来
g_RSDA2 = 0; //可能一有效高脉冲
g_RSDA3 = 0; //误码,非有效按键
g_pulseNum = 0x00; //比特流bit计数器
g_insr0 = 0x00; //记录一次脉冲脉宽,单位为0.1ms
g_insr1 = 0x00; //记录一次脉冲脉宽,单位为0.1ms
g_keyPressed = 0x00;//spying the continue pressing a key
//红外接收 仅为输入
P0M1 = P0M1 | 0x01; //Input status,set P1.1 input mode
P0M2 = P0M2 & 0xFE;
IR_SIGNAL = 1;
//IR_LED = 0; //Init completed,turn off the ir indicator led
}
/*******************************************************************
** 函 数 名: timer0_Init()
** 输 入: 无
** 输 出: 无
** 描 述: 初始化定时器0。
** 全局变量: 无
** 调用模块: 无
** 被调模块: 无
** 作 者:
** 创建日期: 2006年1月15日
** 修 改:
** 日 期 版本 修改人 修改内容
** 1.
********************************************************************/
void timer0_Init()
{
/* 使能定时器0中断 1 */
TMOD = TMOD | 0x01;
TR0 = 1;
ET0 = 1;
// TL0 = 0xB0; //100H-CEH=32H=50X2uS=100uS
// TH0 = 0xFE; //定时器0 happen per 0.1MS
TL1 = 0xD8; //100uS
TH1 = 0xFD; //定时器0 happen per 0.1MS
}
/*******************************************************************
** 函 数 名: timer0_Isr()
** 输 入: 无
** 输 出: 无
** 描 述: 定时器0中断函数,每0.1ms检测是否有脉冲。
** 全局变量:
** g_pulseNum -- 脉冲数
** g_keyPressed -- 连续按键标志
** 调用模块:
** checkPulse -- 检测脉冲
** 被调模块:
** 作 者: 金雨和
** 创建日期: 2006年1月15日
** 修 改:
** 日 期 版本 修改人 修改内容
** 1.
********************************************************************/
void timer0_Isr() interrupt 1
{
/* =====timer0: high pulse detect ========= */
if(g_RSDA1) //RSDA1 为1,IR_SIGNAL有下降沿来过,可能是一按键已开始,转到处理bit流
{
if(IR_SIGNAL) //IR_SIGNAL是否高,则INSR0+=1,若为低则判断脉冲宽度是否为有效
{
g_insr0++; //step one,inc about 0.1 ms
}
else //IR_SIGNAL =0,为低,在此检测遥控信号的第一个下降沿
{
if(g_RSDA3) //查询此次是否为有效按键
{
g_insr0 = 0;
g_pulseNum = 0;
}
else
{
//有效脉宽值,MIN_BIT0_PLS为bit 0的脉宽值是最小的,所以至少要比bit 0脉宽最小值大才能算有效脉宽
if(g_insr0 > MIN_BIT0_PLS) //if INSR0<3,pulse width<0.3ms, exit,not a valid pulse
{
if((g_insr0 > MIN_CODE_PLS)&&(g_insr0 < MAX_CODE_PLS)) //检测到前导码
{
g_pulseNum = 0;
g_keyPressed = 0x00;
}
//MAX_BIT1_PLS为bit 1的脉宽值是最大的,以下比较可以得到bit 0或者bit 1的脉宽
if(g_insr0 <= MAX_BIT1_PLS) //bit 0或者bit 1脉冲,<2ms continue
{
g_IR_SF = 0;
g_pulseNum++; //计算脉宽,insr0>=3,bit counter
g_insr1 = g_insr0;
g_insr0 = 0x00;
}
else
{
if(g_insr0 >= MAX_CONT_PLS) //大于连续按键最大脉宽即为前导码
{
g_IR_SF = 0;
//g_keyPressed = 0x00;
g_pulseNum++; //计算脉宽,insr0>=3,bit counter
g_insr1 = g_insr0; //High level counter
g_insr0 = 0x00;
g_RSDA2 = 1; //a high level,a valid pulse
}
else //连续按键
{
g_IR_SF = 1; //2ms<Pulse width<2.5ms,translate the same key value
g_RSDA2 = 1;
}
}
checkPulse();
}
}
}
}
else
{
if(!IR_SIGNAL)
{
g_RSDA1 = 1; //ir_sign fall,指示遥控按键操作的第一个下降沿
g_RSDA2 = 0; //no high pulse,RSDA2=0,脉冲指示清0
g_IR_SF = 0; //连续按键指示清0
g_insr0 = 0x00; //counter init,TIM0计数器清0
g_pulseNum = 0x00; //bit cnt init
}
}
// TL0 = 0xB0; //100uS
// TH0 = 0xFE; //定时器0 happen per 0.1MS
TL1 = 0xD8; //100uS
TH1 = 0xFD; //定时器0 happen per 0.1MS
}
/*******************************************************************
** 函 数 名: checkProc()
** 输 入: 无
** 输 出: 无
** 描 述: 每0.5ms分析脉冲波形。
** 全局变量:
** g_keyPressed -- 连续按键标志
** 调用模块:
** pulseProc -- 脉冲处理
** 被调模块:
** 作 者: 金雨和
** 创建日期: 2006年1月15日
** 修 改:
** 日 期 版本 修改人 修改内容
** 1.
********************************************************************/
void checkPulse()
{
if(g_RSDA2) //有效脉冲
{
if(g_IR_SF) //连续按键,所谓连续按键就是按住一个键不放,
{ // 2.0ms<脉宽<2.5ms,为连续按键
g_keyPressed++;
g_IR_SF = 0; //连续按键标志清零
g_RSDA1 = 0;
if(g_keyPressed > 6) //收到10个连续按键脉冲才认为是有效连续按键
{
g_keyPressed = 0x00;
g_rsFlag = 1; //RSFLAG indicate remote data is active
}
}
else //按键正常波形
pulseProc(g_pulseNum); //正常按键波形处理
}
else //无效脉冲,退出
{
if(g_RSDA1)
if(g_insr0 > INVALID_PLS)
g_RSDA1 = 0;
}
}
/*******************************************************************
** 函 数 名: pulseProc()
** 输 入:
** pulseNum -- 脉冲数
** 输 出: 无
** 描 述: 脉冲处理函数。
** 全局变量:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -