51.红外通信

该代码实现了一个红外遥控信号的解码过程,通过检测高低电平时间来解析遥控器发送的地址码和数据码,并在LCD1602显示器上显示。程序中包含了红外初始化、中断服务函数、LCD显示函数以及按键处理函数,能够识别并响应特定的遥控器指令。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hwtx.c

#include "system.h"	   //把timer0.h文件包含进来
#include "led.h"
#include "hwtx.h"	
//#include "user.h"
#include "lcd1602.h"

extern uint count_100us;
uint num_100us=0; //记录低电平时间
uchar ind=0; 
uchar inddd; 
uchar lfm; 
uchar  remotecode[4]; //数组来保存地址码,地址反码,数据码,数据反码
uchar remotestat=0;  //0表示未解码,1表示解码中,2表示解好码
uchar x=0; //记录32个数据码
void IrInit()  //外部中断初始化
{
	IT0=1;//下降沿触发
	EX0=1;//打开中断0允许
	EA=1;	//打开总中断


}

void ReadIr() interrupt 0
{

 static uchar dat,i,j;
  uchar k=0;
 static uint  y=0;
 static uint  z=0;
 static uint  m=0;
  if(ind==0)   //第一次进中断
   {
     count_100us=0; //先清空定时器计算清零,开始捕获
     ind=1;         
   }
  else if(ind==1)  //第二次进中断
  {
    num_100us=count_100us;  //就可以计算一个时间周期的时间
    count_100us=0;          //计算清理,为下次中断计数
  if((num_100us<150)&&(num_100us>115)) //判断前导码是否正确
	 {
      remotecode[0]=remotecode[1]=remotecode[2]=remotecode[3]=0;
			ind=2;   //进入解码
      led3=0;
	 }
    else if ((num_100us<1300)&&(num_100us>850))
   {
//    led5=~led5;
    ind=0; 
    lfm=1;
   }
   else lfm=0; 
  }
  else if(ind==2)  //进入解码状态
  {
    num_100us=count_100us;  //计算每个周期的时间
    count_100us=0;           //计算清理,为下次中断计数

  if((num_100us<13)&&(num_100us>9)) {  remotecode[x/8]&=~(0x01<<(x%8));led4=0;}	//数据对应位清0led4=0;}//如果一个周期是1.125ms左右,那么就是数据0  
  else if((num_100us<24)&&(num_100us>18)) {remotecode[x/8]|=(0x01<<(x%8));led5=0;}//如果一个周期是2.25ms左右,那么就是数据1
  //remotecode[32]/84个数组,每个字节数组8bit <<x%8,就是每个数组移位8
// if((num_100us<13)&&(num_100us>9)) {  remotecode[x>>3]&=~(0x01<<(x%8));}	                                    
// else if((num_100us<24)&&(num_100us>18)) {remotecode[x>>3]|=(0x01<<(x%8));}//如果一个周期是2.25ms左右,那么就是数据1


// else					//接收出错
//		{
//			x=0;			//数据位置指针清0
//			ind=1;			//置状态为1
//		}
  x++;
   
    if(x>=32)  //总共有32个高低电平
		 {
			x=0;
			ind=0;

		if((remotecode[2]+remotecode[3])==0xff)  //判断数据码正反是否正确
			{
				led7=~led7;  
        inddd=3;

        LCD_ShowHexNum(2,1,remotecode[0],2);	//显示遥控器地址码
			  LCD_ShowHexNum(2,7,remotecode[2],2);	//显示遥控器命令码

//       if(remotecode[2]==0x0C){y++;}
//       else if(remotecode[2]==0x18){y--;}
//       else if(remotecode[2]==0x5E){led1=1;}
//			 else if(remotecode[2]==0x08){led2=1;}
			}
       
		else {x=0;ind=0;}
		 }
   }
    
    if(inddd==3)
    { 
     for(k=0;k<5;k++)
      {
			
      }
      inddd=0;
    } 
     if(lfm==1&&remotecode[2]==0x0c)
     {
        led1=~led1;
     
     }
     else if(lfm==1&&remotecode[2]==0x18)
     {
        led1=~led1;
      
        
     }
}

//void ReadIr() interrupt 0
//{

// static uchar dat,i,j;
//  uchar k=0;
// static uint  y=0;
// static uint  z=0;
// static uint  m=0;
//  if(ind==0)   //第一次进中断
//   {
//     count_100us=0; //先清空定时器计算清零,开始捕获
//     ind=1;         
//   }
//  else if(ind==1)  //第二次进中断
//  {
//    num_100us=count_100us;  //就可以计算一个时间周期的时间
//    count_100us=0;          //计算清理,为下次中断计数
//  if((num_100us<150)&&(num_100us>115)) //判断前导码是否正确
//	 {
//      remotecode[0]=remotecode[1]=remotecode[2]=remotecode[3]=0;
//			ind=2;   //进入解码
//      led3=0;
//	 }
//    else if ((num_100us<1300)&&(num_100us>850))
//   {
////    led5=~led5;
//    ind=0; 
//    lfm=1;
//   }
//   else lfm=0; 
//  }
//  else if(ind==2)  //进入解码状态
//  {
//    num_100us=count_100us;  //计算每个周期的时间
//    count_100us=0;           //计算清理,为下次中断计数
//    j=x>>3;//j=ind/8;//第ind个码  放在数组的第j个字节里面

//  if((num_100us<13)&&(num_100us>9)) { remotecode[j]&=(~0x80);led4=0;}//如果一个周期是1.125ms左右,那么就是数据0
//   else if((num_100us<24)&&(num_100us>18)) {remotecode[j]|=0x80;led5=0;} //如果一个周期是2.25ms左右,那么就是数据1
//   // else{ind=0;x=0;return;}  //否则解码失败,退出
//    x++;
//		i++;	//记录我的remotecode[j]移了多少次
//		if(i!=8){remotecode[j]>>=1;}  //每移动8次保存一位数组
//		else{i=0;}
//    if(x>=32)  //总共有32个高低电平
//		 {
//			x=0;
//			ind=0;

//		if((remotecode[2]+remotecode[3])==0xff)  //判断数据码正反是否正确
//			{
//				led7=~led7;  
//        inddd=3;

//        LCD_ShowHexNum(2,1,remotecode[0],2);	//显示遥控器地址码
//			  LCD_ShowHexNum(2,7,remotecode[2],2);	//显示遥控器命令码

////       if(remotecode[2]==0x0C){y++;}
////       else if(remotecode[2]==0x18){y--;}
////       else if(remotecode[2]==0x5E){led1=1;}
////			 else if(remotecode[2]==0x08){led2=1;}
//			}
//       
//		else {x=0;ind=0;}
//		 }
//   }
//    
//    if(inddd==3)
//    { 
//     for(k=0;k<5;k++)
//      {
//			
//      }
//      inddd=0;
//    } 
//     if(lfm==1&&remotecode[2]==0x0c)
//     {
//        led1=~led1;
//     
//     }
//     else if(lfm==1&&remotecode[2]==0x18)
//     {
//        led1=~led1;
//      
//        
//     }
//}

hwtx.h

#include "system.h"	   //把timer0.h文件包含进来

void IrInit();

main.c

#include "system.h"
#include "key.h"
#include "lcd1602.h"
#include "hwtx.h"	
extern	uchar flag_1ms;	   //在其他模块中寻找其定义。另外,extern也可用来进行链接指定。


void main(void)			//程序的主函数
{
	Timer0_Init(); ////定时器0函数调用
  LCD_Init();
  IrInit();  //红外初始化

//  LCD_ShowChar(1,1,'b');			//11列显示字符A
//  LCD_ShowChar(2,5,"Hello");			//11列显示字符A
//	LCD_ShowString(1,3,"Hello");	//13列显示字符串Hello
//	LCD_ShowNum(1,9,66,2);			//19列显示数字66,长度为2
//	LCD_ShowSignedNum(1,12,-88,2);	//112列显示有符号数字-88,长度为2
//	LCD_ShowHexNum(2,1,0xA5,2);		//21列显示十六进制数字0xA5,长度为2
//	LCD_ShowBinNum(2,4,0xA5,8);		//24列显示二进制数字0xA5,长度为8
//	LCD_ShowChar(2,13,0xDF);		//213列显示编码为0xDF的字符
//	LCD_ShowChar(2,14,'C');			//214列显示字符C

	while(1)  			//大括号里面的东西,被不停的循环执行
	{ 

		//1ms进入一次
		if(flag_1ms==1)	//加了我之后,我的大括号里面的东西,被定期的1ms执行一次,反复执行	 	
		{
			flag_1ms=0;
//      LCD_Display();	//显示屏显示函数
      datapros();

		}
	}
}

lcd1602.c

#include "lcd1602.h"

uchar a[16]="perchin designed";
uchar b[27]="welcome to the world of mcu";
void LCD_Delay()		//@12.000MHz 1ms
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_E=1;
	LCD_Delay();
	LCD_E=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_E=1;
	LCD_Delay();
	LCD_E=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602初始化函数
  * @param  
  * @retval 
  */
void LCD_Init(void)
{
	LCD_WriteCommand(0x38);
	LCD_WriteCommand(0x0C);
	LCD_WriteCommand(0x06);
	LCD_WriteCommand(0x01);
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else
	{
		LCD_WriteCommand(0x80|(Column-1)+0x40);
	}
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10);
	}
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData('0'+Number1/LCD_Pow(10,i-1)%10);
	}
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	unsigned char SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData('0'+SingleNumber);
		}
		else
		{
			LCD_WriteData('A'+SingleNumber-10);
		}
	}
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData('0'+Number/LCD_Pow(2,i-1)%2);
	}
}

lcd1602.h

#include "system.h"


//引脚定义
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
#define LCD_DataPort P0


void LCD_Init(void);
void LCD_SetCursor(unsigned char Line,unsigned char Column);   //显示屏显示函数
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

key.c

#include "key.h"	 //把led.h文件包含进来
#include "system.h"	   //把timer0.h文件包含进来
#include "led.h"
#include "lcd1602.h"
u8 KeyScan ()		//按键扫描函数
{
	static	uint timer=0;

	if(k1==0)
	{  
		timer++;
		if(timer==10){return 1;} //定时10毫秒返回
    else if(timer==1000){timer=500;return 1;} //否则长按不停加1
	}
	else if(k2==0)
	{
		timer++;  
		if(timer==10){return 2;} //定时10毫秒返回
		//else if(timer==1000){timer=900;return 2;} //否则长按不停加1
		else if(timer==1000){timer=500;return 2;} //否则长按不停加1
	}
	else if(k3==0)
	{
		timer++;
		if(timer==10){return 3;} //定时10毫秒返回
		else if(timer==1000){timer=500;return 3;} //否则长按不停加1
	}
	else if(k4==0)
	{
		timer++;
		if(timer==10){return 4;}  //定时10毫秒返回
    else if(timer==1000){timer=500;return 4;} //否则长按不停加1
	}
	else
	{
		timer=0;	   //定时清0
	}
	return 0;	
}

unsigned int Num;
void datapros()
{
	uchar key;
	key=KeyScan();	 //key=调用检测按键函数
	
	if(key==1)	   
	{
		
  }
	else if(key==2)
	  {
     Num--;
		 LCD_ShowNum(1,1,Num,5);
    }
  else if(key==3)
	  {
     
    }
  else if(key==4)
	  {
     
    }
}

key.h

#include "system.h"	   //把timer0.h文件包含进来

sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;	 //定义按键端口
		
u8 KeyScan ();		//按键扫描函数
void datapros();

system.c

#include "system.h"
 
uchar flag_1ms=0;
unsigned char count_0_1ms=0;
uint count_100us=0;
void	Timer0_Init(void)
{
	TH0 = T1MS>>8; //赋初值
	TL0 = T1MS;	   //赋初值
	TMOD = 0x01;  //设置定时器0用十六位定时器方式
    EA = 1;			 //打开总中断
  	ET0 = 1;		 //打开定时器0中断
  	TR0 = 1;		 //启动定时器0		
}

void Timer0() interrupt 1		 //中断号1
{	
	TH0 = T1MS>>8; //赋初值
	TL0 = T1MS;	   //赋初值
	
  
//  count_0_1ms++;
	if(count_0_1ms>=10)
	{
		flag_1ms=1;
		count_0_1ms=0;
	}
 count_100us++;
}

void	Delay_us(uint xus)
{
	for(;xus>0;xus--);
}

void	Delay_ms(uint xms)
{
	for(;xms>0;xms--)
	{
		Delay_us(1000);
	}
}

system.h

#include "reg51.h"


#define	uchar unsigned char	//定义无符号字符
#define	uint  unsigned int	//定义无符号整形

#define	u8 unsigned char	//定义无符号字符
#define	u16  unsigned int	//定义无符号整形

#define	FOSC	12000000L	//定义晶振频率		   
#define	T1MS	(65536-FOSC/12/10000)  //定时10毫秒的时候,计数器要写入的值

void	Delay_us(uint xus);	//us级延时
void	Delay_ms(uint xms);	//ms级延时
void	Timer0_Init(void);  	//定时器初始化


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值