⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irrecv.c

📁 此代码实现功能为:在philips P89LPC935单片机上实现红外遥(对应红外发送芯片为:HT6222)控解码接收
💻 C
📖 第 1 页 / 共 2 页
字号:

/*********************************************************************/
/* 模 块 名:单片机(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 + -