51单片机嵌入式开发:14、STC89C52RC 之HX1838红外解码NEC+数码管+串口打印+LED显示

news2024/11/25 9:49:29

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

STC89C52RC 之HX1838红外解码NEC+数码管+串口打印+LED显示

  • STC89C52RC 之HX1838红外解码NEC+数码管+串口打印+LED显示
  • 1 概述
  • 2 硬件电路
    • 2.1 遥控器
    • 2.2 红外接收器电路
    • 2.3 STC89C52单片机电路
    • 2.4 数码管显示电路
    • 2.5 串口打印电路
    • 2.6 LED显示电路
  • 3 工程代码实现
    • 3.1 红外接收程序
    • 3.2 定时器程序
    • 3.3 数码管显示程序
    • 3.4 外部中断程序
    • 3.5 串口打印程序
    • 3.6 演示效果
  • 4 设计总结


STC89C52RC 之HX1838红外解码NEC+数码管+串口打印+LED显示

HX1838红外解码NEC+数码管+串口打印+LED显示

在这里插入图片描述

1 概述

对于C51单片机的设计思路,你可以使用类似的步骤来实现红外解码、数码管显示和LED显示的功能。下面是一个简单的设计思路:

在这里插入图片描述

(1) 连接HX1838红外解码器、数码管和LED到C51单片机。将HX1838的信号引脚连接到C51单片机的外部中断引脚(例如INT0),数码管的CLK引脚连接到C51单片机的某个IO口引脚,数码管的DIO引脚连接到C51单片机的另一个IO口引脚,LED连接到C51单片机的某个IO口引脚。
(2) 在C51的程序中,定义并初始化所需的IO口和外部中断。
(3) 编写中断服务函数来处理红外解码。当外部中断触发时,读取HX1838接收到的红外信号,并进行解码。
(4) 根据解码结果,使用适当的算法将解码结果转换为数码管的显示数据。
(5) 将数码管的显示数据发送到数码管的CLK和DIO引脚上,以控制数码管显示解码结果。
(6) 根据解码结果的状态,设置LED的引脚状态,以控制LED的显示。
(7) 通过循环等待的方式,持续接收和处理红外信号,并更新数码管和LED的显示。

2 硬件电路

2.1 遥控器

外部遥控器的编码见下图:

在这里插入图片描述

2.2 红外接收器电路

红外接收器电路见下图:

在这里插入图片描述

2.3 STC89C52单片机电路

单片机接口电路见下图:

在这里插入图片描述

2.4 数码管显示电路

数码管显示电路接口电路见下图,在数码管0和1进行显示16进制的红外线接收码:
在之前的章节,有相关数码管数显实现的方法,大家可以翻一翻。

在这里插入图片描述

2.5 串口打印电路

串口打印电路接口电路见下图(其实用下载电路也能实现串口的通讯):

在这里插入图片描述

在这里插入图片描述

2.6 LED显示电路

LED显示电路电路见下图:
根据不同的接收数据码,在8个LED灯进行显示,当对应位置为1时,led不亮。

在这里插入图片描述

3 工程代码实现

工程、主程序及includes.h如下:

在这里插入图片描述

//main.c文件

#include "includes.h"



/******************************************************************/
/*                    微秒延时函数  //10us                         */
/******************************************************************/
void delay_us(unsigned int us)//delay us
{
	while(us--)
	{
	}
}

/******************************************************************/
/*                    微秒延时函数                                */
/******************************************************************/
void delay_ms(unsigned int Ms)//delay us
{
	while(Ms--)
	{
		delay_us(100);
	}
}

/*------------------------------------------------
                    延时子程序
------------------------------------------------*/
void delay(unsigned int cnt) 
{
 while(--cnt);
}




/*------------------------------------------------
                    主函数
------------------------------------------------*/
void main (void)
{
	sys_timer_init();
	
	sys_exit_init();
	
	sys_uart_init();
	
	
//	sys_ledtube_on2();
//	
//	sys_ledtube_on1();
	
	delay(10);
	
	//首先定义处于什么状态,
	//tx1838_type = 1;
	
	
	printf("Hello world~~");
	while (1)
	{
//		sys_tx1838_test();
		if(tx1838_flag)
		{
			tx1838_flag = 0;
			hx1838_transform(tx1838_value);
		}
		
		sys_keynum_ledon(tx1838_value>>4,0);
		delay_ms(10);
		sys_keynum_ledon(tx1838_value&0xF,1);
		delay_ms(10);
	}
}

//includes.h文件

#ifndef __INCLUDES_H__
#define __INCLUDES_H__

//#include<reg52.h> 

#include<intrins.h> //汇编指令_nop_
#include<stdio.h> 	//标准输入输出

//_nop_(); 产生一条NOP指令
//作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。
//NOP指令为单周期指令,可由晶振频率算出延时时间。

//8051 为每个机器周期 12 时钟
//对于12M晶振,延时1uS。
//11.0592M晶振,延时1.0851uS。

//对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。


//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include "STC89C5xRC_RDP.h"

//应用层头文件
//#include "c51_gpio.h"
#include "c51_ledtube.h"
//#include "c51_key.h"
#include "c51_timer.h"
#include "c51_exit.h"
//#include "c51_lcd1602.h"
//#include "c51_iic.h"
#include "c51_tx1838.h"
#include "c51_uart.h"


extern void delay(unsigned int cnt);
extern void delay_us(unsigned int us);//delay us;
extern void delay_ms(unsigned int Ms);//delay Ms;


#endif

3.1 红外接收程序

实现红外nec解码和根据码位不同,在printf打印不同的字符串。
//c51_tx1838.c文件

#include "includes.h"


unsigned char tx1838_cnt = 0;
unsigned char tx1838_type = 0;
unsigned char tx1838_flag = 0;
unsigned char tx1838_repeat_flag = 0;


unsigned char tx1838_value = 0;
unsigned char tx1838_data[4] = {0};
unsigned int  tx1838_time = 0;


//void sys_tx1838_test(void)
//{
//	unsigned int time = 0;
//	if(!NEC)
//	{
//		while(!NEC);		//等待低电平结束
//		TH0 = 0;
//		TL0 = 0;
//		delay_us(1);
//		if(tx1838_type==4)
//		{
//			tx1838_type =1;
//		}
//		else
//		{
//			while(NEC)			//等待数据位计时
//			{
//				if(TH0>30)
//				{
//					tx1838_type =1;
//					break;
//				}
//			}
//		}
//		time =(TH0<<8)+TL0; //取得脉冲宽度
//	
//		switch(tx1838_type)
//		{
//			case 1:
//			{
//				if(time>3000 && time<7000) //接收到数据
//				{
//					tx1838_type = 2;
//					
//					tx1838_cnt = 0;		//接收位数量清0
//					tx1838_data[0] = 0;
//					tx1838_data[1] = 0;
//					tx1838_data[2] = 0;
//					tx1838_data[3] = 0;
//				}
//				else if(time>2000 && time<3000)//接收到重复码
//				{
//					tx1838_type = 3;
//				}
//				else
//				{
//					tx1838_type = 1;
//				}
//				break;
//			}
//			case 2:
//			{
//				tx1838_cnt ++ ;
//				if(time>168 && time<800) //接收到数据位为0的时间长度
//				{

//				}
//				else 
//				{
//					if(time>1100 && time<1800) //接收到数据位为1的时间长度
//					{
//						if(tx1838_cnt<=8)
//						{
//							tx1838_data[0] |= (1<<(tx1838_cnt-1));
//						}
//						else if(tx1838_cnt<=16)
//						{
//							tx1838_data[1] |= (1<<(tx1838_cnt-9));
//						}
//						else if(tx1838_cnt<=24)
//						{
//							tx1838_data[2] |= (1<<(tx1838_cnt-17));
//						}
//						else if(tx1838_cnt<=32)
//						{
//							tx1838_data[3] |= (1<<(tx1838_cnt-25));
//						}
//						else
//						{
//							tx1838_type = 1;
//							
//							tx1838_cnt = 0;		//接收位数量清0
//							tx1838_data[0] = 0;
//							tx1838_data[1] = 0;
//							tx1838_data[2] = 0;
//							tx1838_data[3] = 0;
//						}
//					}
//					else //重新解码 //接收到引导码或者结束码,或者接收到的是重复码,本章节不进行演示
//					{
//						tx1838_type = 1;
//						
//						tx1838_cnt = 0;		//接收位数量清0
//						tx1838_data[0] = 0;
//						tx1838_data[1] = 0;
//						tx1838_data[2] = 0;
//						tx1838_data[3] = 0;
//					}
//				}
//				
//				if(tx1838_cnt>=32)
//				{
//					tx1838_type = 4;
//					
//					switch(tx1838_data[3])//判断数码值
//					{
//						case 255:sys_keynum_ledon(0);break;//0 显示相应的按键值
//						case 254:sys_keynum_ledon(1);break;//1
//						case 253:sys_keynum_ledon(2);break;//2
//						case 252:sys_keynum_ledon(3);break;//3
//						case 251:sys_keynum_ledon(4);break;//4
//						case 250:sys_keynum_ledon(5);break;//5
//						case 249:sys_keynum_ledon(6);break;//6
//						case 248:sys_keynum_ledon(7);break;//7
//						case 247:sys_keynum_ledon(8);break;//8
//						case 246:sys_keynum_ledon(9);break;//9 显示相应的按键值

//					}
//				}
//				break;
//			}
//			case 3: //重复码
//			{
//				tx1838_type = 1;
//				sys_keynum_ledon(11);
//				break;
//			}
//			case 4: //结束码
//			{
//				tx1838_type = 1;
//				
//				tx1838_cnt = 0;		//接收位数量清0
//				
//				break;
//			}
//			case 5:
//			{
//				break;
//			}
//			default:
//				tx1838_type = 1;
//				break;
//		}
//			
//	}
//}



void sys_nec_test(void)
{
	if(tx1838_type==0)				//状态0,空闲状态
	{
		timer0_set(0);				//定时计数器清0
		timer0_run(1);				//定时器启动
		tx1838_type=1;				//置状态为1
	}
	else if(tx1838_type==1)			//状态1,等待Start信号或Repeat信号
	{
		tx1838_time=timer0_get();	//获取上一次中断到此次中断的时间
		timer0_set(0);				//定时计数器清0
		//如果计时为13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)
		if(tx1838_time>12442-500 && tx1838_time<12442+500)
		{
			tx1838_type=2;			//置状态为2
		}
		//如果计时为11.25ms,则接收到了repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)
		else if(tx1838_time>10368-500 && tx1838_time<10368+500)
		{
			tx1838_repeat_flag=1;	//置收到连发帧标志位为1
			timer0_run(0);		//定时器停止
			tx1838_type=0;		//置状态为0
		}
		else					//接收出错
		{
			tx1838_type=1;			//置状态为1
		}
	}
	else if(tx1838_type==2)		//状态2,接收数据
	{
		tx1838_time=timer0_get();	//获取上一次中断到此次中断的时间
		timer0_set(0);	//定时计数器清0
		//如果计时为1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)
		if(tx1838_time>1032-500 && tx1838_time<1032+500)
		{
			tx1838_data[tx1838_cnt/8]&=~(0x01<<(tx1838_cnt%8));	//数据对应位清0
			tx1838_cnt++;			//数据位置指针自增
		}
		//如果计时为2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)
		else if(tx1838_time>2074-500 && tx1838_time<2074+500)
		{
			tx1838_data[tx1838_cnt/8]|=(0x01<<(tx1838_cnt%8));	//数据对应位置1
			tx1838_cnt++;			//数据位置指针自增
		}
		else					//接收出错
		{
			tx1838_cnt=0;			//数据位置指针清0
			tx1838_type=1;			//置状态为1
		}
		if(tx1838_cnt>=32)		//如果接收到了32位数据
		{
			tx1838_cnt=0;			//数据位置指针清0
			if((tx1838_data[0]==~tx1838_data[1]) && (tx1838_data[2]==~tx1838_data[3]))	//数据验证
			{
				//地址		:tx1838_data[0]
				//地址反码	:tx1838_data[1]
				//数据		:tx1838_data[2]
				//数据反码	:tx1838_data[3]
				
				tx1838_value = tx1838_data[2];
				P1 = tx1838_value;
				tx1838_flag=1;	//红外遥控获取收到数据帧标志位
			}
			timer0_run(0);		//定时器停止
			tx1838_type=0;			//置状态为0
		}
	}
}


void hx1838_transform(unsigned char cmd)
{
	/*
	#define TX1838_CH0			0x45
#define TX1838_CH1			0x46
#define TX1838_CH2			0x47
#define TX1838_VOL1			0x44
#define TX1838_VOL2			0x40
#define TX1838_VOL3			0x43
#define TX1838_EQ1			0x07
#define TX1838_EQ2			0x15
#define TX1838_EQ3			0x09
#define TX1838_0			0x16
#define TX1838_100			0x19
#define TX1838_200			0x0D
#define TX1838_1			0x0C
#define TX1838_2			0x18
#define TX1838_3			0x5E
#define TX1838_4			0x08
#define TX1838_5			0x1C
#define TX1838_6			0x5A
#define TX1838_7			0x42
#define TX1838_8			0x52
#define TX1838_9			0x4A
	*/
	switch(cmd)
	{
		case TX1838_CH0:
			printf("Receice cmd : TX1838 receice is TX1838_CH0 !\r\n");
			break;
		case TX1838_CH1:
			printf("Receice cmd : TX1838 receice is TX1838_CH1 !\r\n");
			break;
		case TX1838_CH2:
			printf("Receice cmd : TX1838 receice is TX1838_CH2 !\r\n");
			break;
		case TX1838_VOL1:
			printf("Receice cmd : TX1838 receice is TX1838_VOL1 !\r\n");
			break;
		case TX1838_VOL2:
			printf("Receice cmd : TX1838 receice is TX1838_VOL2 !\r\n");
			break;
		case TX1838_VOL3:
			printf("Receice cmd : TX1838 receice is TX1838_VOL3 !\r\n");
			break;
		case TX1838_EQ1:
			printf("Receice cmd : TX1838 receice is TX1838_EQ1 !\r\n");
			break;
		case TX1838_EQ2:
			printf("Receice cmd : TX1838 receice is TX1838_EQ2 !\r\n");
			break;
		case TX1838_EQ3:
			printf("Receice cmd : TX1838 receice is TX1838_EQ3 !\r\n");
			break;
		case TX1838_0:
			printf("Receice cmd : TX1838 receice is TX1838_0 !\r\n");
			break;
		case TX1838_100:
			printf("Receice cmd : TX1838 receice is TX1838_100 !\r\n");
			break;
		case TX1838_200:
			printf("Receice cmd : TX1838 receice is TX1838_200 !\r\n");
			break;
		case TX1838_1:
			printf("Receice cmd : TX1838 receice is TX1838_1 !\r\n");
			break;
		case TX1838_2:
			printf("Receice cmd : TX1838 receice is TX1838_2 !\r\n");
			break;
		case TX1838_3:
			printf("Receice cmd : TX1838 receice is TX1838_3 !\r\n");
			break;
		case TX1838_4:
			printf("Receice cmd : TX1838 receice is TX1838_4 !\r\n");
			break;
		case TX1838_5:
			printf("Receice cmd : TX1838 receice is TX1838_5 !\r\n");
			break;
		case TX1838_6:
			printf("Receice cmd : TX1838 receice is TX1838_6 !\r\n");
			break;
		case TX1838_7:
			printf("Receice cmd : TX1838 receice is TX1838_7 !\r\n");
			break;
		case TX1838_8:
			printf("Receice cmd : TX1838 receice is TX1838_8 !\r\n");
			break;
		case TX1838_9:
			printf("Receice cmd : TX1838 receice is TX1838_9 !\r\n");
			break;
		default:
			printf("Receice cmd : TX1838 receice err!\r\n");
			break;
	}
}

//c51_tx1838.h文件

#ifndef __C51_TX1838_H__
#define __C51_TX1838_H__


#define  NEC 	P32 //红外线接收头  


#define TX1838_CH0			0x45
#define TX1838_CH1			0x46
#define TX1838_CH2			0x47
#define TX1838_VOL1			0x44
#define TX1838_VOL2			0x40
#define TX1838_VOL3			0x43
#define TX1838_EQ1			0x07
#define TX1838_EQ2			0x15
#define TX1838_EQ3			0x09
#define TX1838_0			0x16
#define TX1838_100			0x19
#define TX1838_200			0x0D
#define TX1838_1			0x0C
#define TX1838_2			0x18
#define TX1838_3			0x5E
#define TX1838_4			0x08
#define TX1838_5			0x1C
#define TX1838_6			0x5A
#define TX1838_7			0x42
#define TX1838_8			0x52
#define TX1838_9			0x4A



extern unsigned char tx1838_cnt;
extern unsigned char tx1838_type;
extern unsigned char tx1838_flag;
extern unsigned char tx1838_repeat_flag;
extern unsigned char tx1838_value;
extern unsigned char tx1838_data[4];
extern unsigned int tx1838_time;


//extern void sys_tx1838_test(void);
extern void sys_nec_test(void);
extern void hx1838_transform(unsigned char cmd);


#endif

3.2 定时器程序

定时器主要是配合解码时时间长短判断接收数据的0和1。

//c51_timer.c文件

#include "includes.h"


void sys_timer_init(void)
{
	sys_timer0_init();
	sys_timer1_init();
	sys_timer2_init();
	sys_wdog_init();
	clr_wdg();
}


/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void sys_timer0_init(void)
{
	TMOD &= 0xF0;
	TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     
	TH0=0x00;	      //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
	TL0=0x00;
	//EA=1;            //总中断打开 等最后一个中断打开
	//ET0=1;           //定时器中断打开
	TF0=0;           //定时器标志清零
	TR0=0;           //定时器开关打开
}

/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void sys_timer1_init(void)
{
	TMOD |= 0x20;	  //使用模式2,	     
	TH1=0x05;	      //给定初值,这里使用定时器最大值从5开始计数一直到255溢出
	TL1=0x00;
	//EA=1;            //总中断打开
	//ET1=1;           //定时器中断打开
	
	//TR1=1;           //定时器开关打开
}


/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void sys_timer2_init(void)
{
	RCAP2H = 0/256;//
	RCAP2L = 0/256;
	//ET2=1;                     //打开定时器中断
	//EA=1;                      //打开总中断
  
	//TR2=1;                     //打开定时器开关
}

/**
  * @brief  定时器0设置计数器值
  * @param  Value,要设置的计数器值,范围:0~65535
  * @retval 无
  */
void timer0_set(unsigned int Value)
{
	TH0=Value/256;
	TL0=Value%256;
}
 
/**
  * @brief  定时器0获取计数器值
  * @param  无
  * @retval 计数器值,范围:0~65535
  */
unsigned int timer0_get(void)
{
	return ((TH0<<8)|TL0);
}

/**
  * @brief  定时器0启动停止控制
  * @param  Flag 启动停止标志,1为启动,0为停止
  * @retval 无
  */
void timer0_run(unsigned char Flag)
{
	TR0=Flag;
}



void sys_wdog_init(void)
{ 
	//WDT_CONTR = 0x35;
}

void clr_wdg(void)
{
	//WDT_CONTR = 0x35;
}


/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
	TH0=0x00;		  //重新赋值
	TL0=0x00;

	//sys_led_test1(); //流水灯操作
}


/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3
{

	//sys_led_test1(); //流水灯操作
	
}	




/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer2_isr(void) interrupt 5//定时器2中断
{
    TF2=0;
    //sys_led_test1(); //流水灯操作
}

//c51_timer.h文件

#ifndef __C51_TIMER_H__
#define __C51_TIMER_H__






extern void timer0_set(unsigned int Value);
extern unsigned int timer0_get(void);
extern void timer0_run(unsigned char Flag);

extern void sys_timer_init(void);
extern void sys_timer0_init(void);
extern void Timer0_isr(void);
extern void sys_timer1_init(void);
extern void Timer1_isr(void);
extern void sys_timer2_init(void);
extern void Timer2_isr(void);

extern void sys_wdog_init(void);
extern void clr_wdg(void);

#endif

3.3 数码管显示程序

实现数码管显示遥控器的发送码。

//c51_ledtube.c文件

#include "includes.h"

// 显示段码值01234567,可对应原理图查看显示不同图形对应的引脚高点电平配置状态
unsigned char const EL[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,\
		                  	 0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F



///********************************************************
//函数名称:sys_ledtube_on1
//函数功能:点亮一个数码管全为亮起来
//入口参数:
//出口参数:
//修    改:
//内    容:
//********************************************************/
//void sys_ledtube_on1(void)
//{
//	//根据原理图,将P0口全部输出高电平,P2选择0号数码管
//	P0=0xFF;//取显示数据,段码
//	P2=0;  	//取位码
//}

///********************************************************
//函数名称:sys_ledtube_on2
//函数功能:显示一组数据
//入口参数:
//出口参数:
//修    改:
//内    容:
//********************************************************/
//static unsigned char ledtube_cnt = 0;
//void sys_ledtube_on2(void)
//{
//	ledtube_cnt++;
//	if(ledtube_cnt>7)
//	{
//		ledtube_cnt = 0;
//	}
//	P0 = 0x00;				//防止切换数码管瞬间有虚影出现
//	P2 = 0x00;
//	P0 = EL[ledtube_cnt];	//取显示数据,段码
//	P2 = ledtube_cnt;  		//取位码
//	
//	//根据人眼适应虚影缓冲时间为50ms左右
//	//我们调整delay在500以下可以看到明显的看起来是一串数据一起显示
//	delay(100); 			
//}


/********************************************************
函数名称:sys_keynum_ledon
函数功能:显示按键数值
入口参数:按键数值
出口参数:
修    改:
内    容:
********************************************************/
void sys_keynum_ledon(unsigned char num,unsigned char pn)
{
	//根据原理图,将P0口全部输出高电平,P2选择0号数码管
	P0 = 0x00;		//防止切换数码管瞬间有虚影出现
	P2 = pn;  		//取位码
	P0 = EL[num];	//取显示数据,段码
}

//c51_ledtube.h文件

#ifndef __C51_LEDTUBE_H__
#define __C51_LEDTUBE_H__


extern unsigned char const EL[];

//extern void sys_ledtube_on1(void);
//extern void sys_ledtube_on2(void);

extern void sys_keynum_ledon(unsigned char num,unsigned char pn);


#endif

3.4 外部中断程序

实现在有数据过来时,下降沿触发解码程序。

//c51_exit.c文件

#include "includes.h"




void sys_exit_init(void)
{
	IT0=1;         //边沿触发
	EX0=1;         //外部中断0开
	IE0=0;		   //中断标志清零
	//PX0 = 1;		 //中断优先级不配置
	EA = 1;
	
	//EX1=1;         //外部中断1开
	//IT1=0;         //电平触发
	//IT1=1;         //边沿触发,IT1=0表示电平触发
}


/*------------------------------------------------
                 外部中断程序
------------------------------------------------*/
void Exit0_isr(void) interrupt 0
{
	IE0=0;		   //中断标志清零
	sys_nec_test();
}


/*------------------------------------------------
                 外部中断程序
------------------------------------------------*/
void Exit1_isr(void) interrupt 2
{
	//在此处可以添加去抖动程序,防止按键抖动造成错误
	//P1=~P1;
}

//c51_exit.h文件



#ifndef __C51_EXIT_H__
#define __C51_EXIT_H__

extern void sys_exit_init(void);
extern void Exit0_isr(void);
extern void Exit1_isr(void);



#endif

3.5 串口打印程序

实现printf打印不同的字符串。

//c51_uart.c文件

#include "includes.h"



/*-----------------------------------------------
  名称:串口通信
  内容:连接好串口或者usb转串口至电脑,下载该程序,打开电源
        打开串口调试程序,将波特率设置为9600,无奇偶校验
        晶振11.0592MHz,发送和接收使用的格式相同,如都使用
        字符型格式,在发送框输入 hello,I Love MCU ,在接
        收框中同样可以看到相同字符,说明设置和通信正确
------------------------------------------------*/
                    


/******************************************************************/
void sys_uart_init(void)
{


	SCON  = 0x50;		        /* SCON: 模式 1, 8-bit UART, 使能接收         */
	TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */
	TH1   = 0xFD;               /* TH1:  reload value for 9600 baud @ 11.0592MHz   */
	TR1   = 1;                  /* TR1:  timer 1 run                          */
	EA    = 1;                  /*打开总中断*/
	//ES    = 1;                  /*打开串口中断*///当使用串口协议通讯时可以使用此型号中断

}


void Uart_SendChar(unsigned char  dat)
{
    SBUF = dat; 
    while(!TI); 
    TI = 0; 
}
 
char putchar(char c)//重定向
{
    Uart_SendChar(c);
    return c;

}

/******************************************************************/
/*                  串口中断程序                                  */
/******************************************************************/


static unsigned char uart_temp = 0;          //定义临时变量 
static unsigned char uart_cnt = 0;          //定义临时变量 


void UART_isr(void) interrupt 4 //串行中断服务程序
{
	if(RI)                        //判断是接收中断产生
	{
		RI=0;                      //标志位清零
		uart_temp=SBUF;                 //读入缓冲区的值
		if(uart_cnt==0)
		{
			if(0x02 == uart_temp)
			{
				uart_cnt = 1;
			}
			else
			{
				uart_cnt = 0;
			}
		}
		else if(uart_cnt==1)
		{
			if(0x05 == uart_temp)
			{
				uart_cnt = 2;
			}
			else
			{
				uart_cnt = 0;
			}
		}
		else if(uart_cnt==2)
		{
			uart_cnt = 0;
			//P1=uart_temp;                   //把值输出到P1口,用于观察
			SBUF=uart_temp;                 //把接收到的值再发回电脑端
		}
		else
		{
			uart_cnt = 0;
		}
	}
	if(TI)                        //如果是发送标志位,清零
	{
		TI=0;
	}
} 

//c51_uart.h文件

#ifndef __C51_UART_H__
#define __C51_UART_H__


extern void Uart_SendChar(unsigned char  dat);
extern char putchar(char c);//重定向

extern void sys_uart_init(void);
extern void UART_isr(void);


#endif

3.6 演示效果

(1)串口打印效果

在这里插入图片描述

(2)数码管显示和LED显示
数码管显示0x1C,LED显示D2D3D4灭,其他亮,所以也显示0x1C

在这里插入图片描述

4 设计总结

HX1838红外解码器结合数码管、串口和LED显示的应用场景有很多,下面是一些可能的应用场景:
(1) 远程控制器:将HX1838红外解码器与数码管、串口和LED显示结合使用,可以实现一个简单的远程控制器。用户可以使用红外遥控器发送命令,通过解码器解码后,在数码管上显示命令信息,并使用LED显示命令的状态(例如开启/关闭)。这可以用于控制家电设备、灯光等。
(2) 安防系统:将HX1838红外解码器与数码管、串口和LED显示结合使用,可以构建一个基本的安防系统。通过使用红外遥控器发送特定的指令,解码器将解码后的指令信息显示在数码管上,并相应地控制LED的状态,以指示安全状态或报警状态。
(3) 学习工具:结合数码管和LED显示,可以将HX1838红外解码器用于学习工具。例如,可以使用红外遥控器发送特定的学习指令,解码器将解码后的指令信息显示在数码管上,而LED则可以用于指示学习进度或正确与否。
(4) 玩具设计:利用HX1838红外解码器和数码管、串口和LED显示,可以设计各种互动玩具。例如,通过使用特定的红外遥控器发送不同的指令,解码器将识别并在数码管上显示相应的信息,而LED则可以用于增加互动效果或指示玩具状态。
(5) DIY项目:HX1838红外解码器与数码管、串口和LED显示的组合可以应用于各种DIY项目,例如智能家居控制、自动化系统、电子游戏等。通过自定义红外指令和相应的解码、显示和控制逻辑,可以实现各种有趣的功能和交互体验。
这些只是一些示例应用场景,实际上,HX1838红外解码器与数码管、串口和LED显示的组合可以应用于各种需要红外信号解码和相应显示控制的项目和系统中。具体的应用取决于你的创意和需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1939006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入理解Linux网络(三):TCP对象创建

深入理解Linux网络&#xff08;三&#xff09;&#xff1a;TCP对象创建 TCP对象创建inet_createsock_init_data TCP对象创建 常见的三句TCP编程&#xff1a; int main() {int sk socket(AF_INET, SOCK_STREAM, 0);connect(sk, ...)recv(sk, ...) }简单的两三⾏代码&#xff…

逆向案例二十八——某高考志愿网异步请求头参数加密,以及webpack

网址&#xff1a;aHR0cDovL3d3dy54aW5nYW9rYW90Yi5jb20vY29sbGVnZXMvc2VhcmNo 抓包分析&#xff0c;发现请求头有参数u-sign是加密的&#xff0c;载荷没有进行加密&#xff0c;直接跟栈分析。 进入第二个栈&#xff0c;打上断点&#xff0c;分析有没有加密位置。 可以看到参数…

【PyTorch】图像二分类项目-部署

【PyTorch】图像二分类项目 【PyTorch】图像二分类项目-部署 在独立于训练脚本的新脚本中部署用于推理的模型&#xff0c;需要构造一个模型类的对象&#xff0c;并将权重加载到模型中。操作流程为&#xff1a;定义模型--加载权重--在验证和测试数据集上部署模型。 import torch…

Windows11 安装Docker,安装至D盘(其他非C盘皆可)

Docker默认安装在C盘&#xff0c;这未来随着docker使用必定会导致C盘空间吃紧。 所以本文提前进行空间布局&#xff0c;将docker默认安装路径软链接到D盘。 软链接D盘 Docker默认安装路径为C:\Program Files\Docker。使用管理员权限打开命令终端 输入以下命令&#xff1a;m…

【LeetCode】day14:226 - 翻转二叉树, 101 - 对称二叉树, 104 - 二叉树的最大深度, 111 - 二叉树的最小深度

LeetCode 代码随想录跟练 Day14 226.翻转二叉树101.对称二叉树104.二叉树的最大深度111.二叉树的最小深度 226.翻转二叉树 题目描述&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 使用递归处理&#xff08;迭代以及层序同…

jdk1.8 List集合Stream流式处理

jdk1.8 List集合Stream流式处理 一、介绍(为什么需要流Stream&#xff0c;能解决什么问题&#xff1f;)1.1 什么是 Stream&#xff1f;1.2 常见的创建Stream方法1.3 常见的中间操作1.4 常见的终端操作 二、创建流Stream2.1 Collection的.stream()方法2.2 数组创建流2.3 静态工厂…

单链表的创建与遍历--C

基本结构声明 struct node{int data; //数据域struct node *next;//指针域 }; #include<stdio.h> #include<stdlib.h>struct node{//链表结点 int data;//数据域 struct node *next;//指针域 }; typedef struct node Node; int main(void){Node *head,*p,*…

【高数复盘】武忠祥高数辅导讲义+严选题错题一轮复盘

第一章 函数、极限和连续 高等数学辅导讲义 1. 复盘&#xff1a;(xsinxcosx)(x-sixcosx)&#xff0c;前者可以带入cosx1&#xff0c;而后者不能带入&#xff0c;为何&#xff1f; 2. 复盘&#xff1a; 这道题很明显an≤1&#xff0c;对于直接求极限&#xff0c;可以考虑夹逼…

华为防火墙总部与分支机构建立IPsec VPN涉及NAT穿越

一、IPsec VPN基本概念 1、隧道建立方式&#xff1a;分为手动建立和IKE自动协商&#xff0c;手动建立需要人为配置指定所有IPsec建立的所有参数信息&#xff0c;不支持为动态地址的发起方&#xff0c;实际网络中很少应用&#xff1b;IKE协议是基于密钥管理协议ISAKMP框架设计而…

linux系统设置开机启动的两种方法systemd及rc.local(手工写sh脚本,手工写service服务)

文章目录 知识点实验一、systemd&#xff08;一&#xff09;自写一个sh脚本并加入开机启动&#xff08;二&#xff09;源码安装的nginx加入开机启动 rc.local 知识点 在Linux系统中&#xff0c;有多种方法可以设置开机启动。以下是其中的一些主要方法&#xff1a; systemd 在较…

本地部署 mistralai/Mistral-Nemo-Instruct-2407

本地部署 mistralai/Mistral-Nemo-Instruct-2407 1. 创建虚拟环境2. 安装 fschat3. 安装 transformers4. 安装 flash-attn5. 安装 pytorch6. 启动 controller7. 启动 mistralai/Mistral-Nemo-Instruct-24078. 启动 api9. 访问 mistralai/Mistral-Nemo-Instruct-2407 1. 创建虚拟…

[图解]《分析模式》漫谈16-“我用的”不能变成“我的”

1 00:00:00,720 --> 00:00:02,160 今天&#xff0c;我们来说一下 2 00:00:02,170 --> 00:00:04,850 “我用的”不能变成“我的” 3 00:00:04,860 --> 00:00:11,390 《分析模式》的前言 4 00:00:12,260 --> 00:00:13,410 有这么一句话 5 00:00:14,840 --> 0…

postman接口测试实战篇

击杀小游戏接口测试 接口测试简单介绍击杀小游戏代码下载单接口测试(postman)接口关联并参数化接口测试简单介绍 首先思考两个问题:1.接口是什么?2.接口测试是什么? 1.我们总是把接口想的很复杂,其实呢,它就是一个有特定输入和输出参数的交互逻辑处理单元,它不需要知…

学并发编程前需要明确的一些基础知识

线程和进程的区别 在计算机科学中&#xff0c;线程和进程是两个非常重要的概念。虽然它们常常被一起提到&#xff0c;但它们实际上有很大的不同。作为一个开发者&#xff0c;我在日常工作中经常需要区分这两者&#xff0c;以便更好地进行资源管理和优化。 进程与线程的基本定…

如何解决微服务下引起的 分布式事务问题

一、什么是分布式事务&#xff1f; 虽然叫分布式事务&#xff0c;但不是一定是分布式部署的服务之间才会产生分布式事务。不是在同一个服务或同一个数据库架构下&#xff0c;产生的事务&#xff0c;也就是分布式事务。 跨数据源的分布式事务 跨服务的分布式事务 二、解决方…

华为机试HJ60查找组成一个偶数最接近的两个素数

华为机试HJ60查找组成一个偶数最接近的两个素数 题目&#xff1a; 想法&#xff1a; 构建一个判断是否为素数的函数&#xff0c;再构建一个函数输出构成输入数值相差最小的两个素数。为了保证两个素数相差最小&#xff0c;从输入数值的二分之一处开始判断&#xff0c;遍历得到…

用Python写一个视频采集脚本,对某网站进行批量采集

最近某牙上又出现一批高质量视频&#xff0c;听说删的很快&#xff0c;还好我会Python&#xff0c;赶紧采集下来保存&#xff01; 准备工作 环境使用 Python 3.10 解释器 Pycharm 编辑器 模块使用 requests >>> 数据请求模块 re <正则表达式模块> os <文…

HW行动在即,邮件系统该怎么防守?

1. 什么是HW行动&#xff1f; HW行动是一项由公安部牵头&#xff0c;旨在评估企事业单位网络安全防护能力的活动&#xff0c;是国家应对网络安全问题所做的重要布局之一。 具体实践中&#xff0c;公安部组织攻防红、蓝两队&#xff08;红队为攻击队&#xff0c;主要由“国家队…

【漏洞复现】Netgear WN604 downloadFile.php 信息泄露漏洞(CVE-2024-6646)

0x01 产品简介 NETGEAR WN604是一款由NETGEAR&#xff08;网件&#xff09;公司生产的无线接入器&#xff08;或无线路由器&#xff09;提供Wi-Fi保护协议&#xff08;WPA2-PSK, WPA-PSK&#xff09;&#xff0c;以及有线等效加密&#xff08;WEP&#xff09;64位、128位和152…

面向初学者和专家的 40 大机器学习问答(2024 年更新)

面向初学者和专家的 40 大机器学习问答(2024 年更新) 一、介绍 机器学习是人工智能的重要组成部分,目前是数据科学中最受欢迎的技能之一。如果你是一名数据科学家,你需要擅长 python、SQL 和机器学习——没有两种方法。作为 DataFest 2017 的一部分,我们组织了各种技能测…