蓝桥杯单片机CT107D_13_工厂灯光控制系统

本文档展示了如何在嵌入式系统中使用HC138译码器控制LED和数码管,并通过单片机实现定时器T0中断来计时和更新显示。同时,详细介绍了独立按键S7和S5的功能,用于控制LED状态。此外,还涵盖了串口通信的初始化和中断服务,用于接收和处理远程控制命令。
摘要由CSDN通过智能技术生成

需求:(题目来自小蜜蜂老师)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

#include<reg52.h>
sfr AUXR = 0x8e;               //设置辅助寄存器AUXR
sbit S7 = P3^0;	               //独立按键S7
sbit S5 = P3^2;				   //独立按键S5
unsigned char command;         //接收串口数据
unsigned char state = 0xff;    //LED当前状态
unsigned char hour = 0;        //时
unsigned char minute = 0;      //分
unsigned char second = 0;      //秒
unsigned char count = 0; 	   //50ms定时计数
unsigned char code SEG_code[19] = 
	{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
	 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,
	 0xbf,0x7f,0x00};	           //定义共阳数码管段码内容:0~F,—,.

/*===============================系统初始化================================*/
//端口选择
void Select_HC138(unsigned char n)     
{
	switch(n)
	{
		case 0:
			P2 = (P2 & 0x1f) | 0x00;   //不选择
			break;
		case 4:
			P2 = (P2 & 0x1f) | 0x80;   //选择LED
			break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;   //选择蜂鸣器和继电器
			break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;   //选择数码管的位置
			break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;   //选择数码管的值
			break;
	}
}

//普通延时函数
void Delay_common(unsigned int t)      
{
	while(--t);		  //--t
}

//初始化
void Init_system()	  
{
	Select_HC138(5);
	P0 = 0x00;        //关闭蜂鸣器和继电器
	Select_HC138(4);
	P0 = state;       //关闭LED
	Select_HC138(0);
}

//LED检测
void Check_LED()      
{
	unsigned char i;
	Select_HC138(4);
	for(i=1;i<=8;i++)	  //依次点亮LED
	{
		P0 = state << i;
		Delay_common(60000);
		Delay_common(60000);
		Delay_common(60000);
	}
	for(i=1;i<=8;i++)	  //依次熄灭LED
	{		
		P0 = ~(state << i);
		Delay_common(60000);
		Delay_common(60000);
		Delay_common(60000);
	}
	Select_HC138(0);
}
		 
//数码管检测
void Check_SMG()	  
{	 	
	unsigned char j;
	for(j=1;j<=8;j++)
	{
		Select_HC138(6);         
		P0 = ~(0xff << j);		 //依次点亮数码管
		Select_HC138(7);
		P0 = SEG_code[18];
		Delay_common(60000);
		Delay_common(60000);
		Delay_common(60000);
	}
	for(j=1;j<=8;j++)
	{
		Select_HC138(6);         
		P0 = 0xff << j;			 //依次熄灭数码管
		Select_HC138(7);
		P0 = SEG_code[18];
		Delay_common(60000);
		Delay_common(60000);
		Delay_common(60000);
	}
	Select_HC138(0);
}
/*=========================================================================*/


/*===============================数码管显示================================*/
//数码管显示
void Show_tube(unsigned char position,unsigned char value)
{
	Select_HC138(6);
	P0 = 0x01 << position;
	Select_HC138(7);
	P0 = value;
}

//数码管动态显示
void Dynamic_display()
{
	Show_tube(0,SEG_code[hour/10]);     //显示时的十位
	Delay_common(500);
	Show_tube(1,SEG_code[hour%10]);     //显示时的个位
	Delay_common(500);
	
	Show_tube(2,SEG_code[16]);          //显示分隔符
	Delay_common(500);
	
	Show_tube(3,SEG_code[minute/10]);   //显示分的十位 
	Delay_common(500);
	Show_tube(4,SEG_code[minute%10]);   //显示分的个位
	Delay_common(500);
	
	Show_tube(5,SEG_code[16]);			//显示分隔符
	Delay_common(500);	

	Show_tube(6,SEG_code[second/10]);   //显示秒的十位 
	Delay_common(500);
	Show_tube(7,SEG_code[second%10]);   //显示秒的个位
	Delay_common(500);
}
/*=========================================================================*/


/*================================独立按键=================================*/
//去抖动延时函数
void Delay_keys()     
{
	unsigned char m = 108,n = 145;
	while(--m)
	{
		while(--n);
	}
}

//独立按键
void Press_keys()
{
	if(S7 == 0)			 //按下S7,点亮L8
	{
		Delay_keys();	 //去抖动
		if(S7 == 0)
		{
			Select_HC138(4);
			state = (state & 0x7f) | (~state & 0x80);  //将最高位取反:将最高位置0、保留state低7位,然后取state取反后的最高位、其他位置0,最后组合
			P0 = state;	             //将当前状态赋值给P0
			Select_HC138(0);
			while(S7 == 0)
			{
				Dynamic_display();   //保证数码管动态显示
			}
		}
	}

	else if(S5 == 0)     //按下S5,点亮L7
	{
		Delay_keys();	 //去抖动
		if(S5 == 0)
		{
			Select_HC138(4);
			state = (state & 0xbf) | (~state & 0x40);  //将第7位取反:将第7位置0、保留state其他位,然后取state取反后的第7位、其他位置0,最后组合
			P0 = state;				 //将当前状态赋值给P0
			Select_HC138(0);
			while(S5 == 0)
			{
				Dynamic_display();	 //保证数码管动态显示
			}
		}
	}
}
/*=========================================================================*/


/*================================定时器T0=================================*/
//定时器timer0中断初始化
void Init_timer0()
{
	TMOD = 0x21;                   //注意:同时给定时器0和定时器1赋值
	TH0 = (65535 - 50000) / 256;   //定时50ms
	TL0 = (65535 - 50000) % 256; 

	EA =1;     //打开总中断
	ET0 = 1;   //打开定时器0的中断
	TR0 = 1;   //启动定时器0
}

//定时器0中断服务函数
void Service_timer0() interrupt 1
{
	TH0 = (65535 - 50000) / 256;   //重新赋值
	TL0 = (65535 - 50000) % 256;  
	count++;                       //定时满50ms加1

	if(count == 20)
	{
		count = 0; 
		second++;				   //定时满1s加1
	}
	if(second == 60)
	{
		second = 0;
		minute++;				   //定时满1min加1
	}
	if(minute == 60)
	{
		minute = 0;
		hour++;					   //定时满1h加1
	}
}
/*=========================================================================*/


/*================================串口通信=================================*/
//发送字节
void Send_byte(unsigned char dat)
{
	SBUF = dat;		  //注意:串口自动转换输出16进制数
	while(TI == 0);   //等待发送
	TI = 0;           //清0
}

//发送字符串
//void Send_string(unsigned char *str)
//{
//	while(*str != '\0')
//	{
//		Send_byte(*str++);
//	}
//}

//串口中断初始化
void Init_uart() 
{
	SCON = 0x50;	//8位异步uart并允许接收
	AUXR = 0x00;	//将AUXR置0
	TMOD = 0x21;    //注意:同时给定时器0和定时器1赋值
	TH1 = 0xfd;
	TL1 = 0xfd;

	EA = 1;         //打开总中断
	ES = 1;         //打开串口中断
	TR1 = 1;		//启动定时器1
}

//串口中断服务函数
void Service_uart() interrupt 4
{
	if(RI == 1)     
	{
		RI = 0;           //清0
		command = SBUF;	  //接收数据
	}
}
/*=========================================================================*/


/*================================命令处理=================================*/
//对串口接收的命令进行相应处理
void Command_process()
{
	if(command)
	{
		switch(command & 0xf0)	      //取command的高4位,低4位清0
		{
			case 0xa0:				  //远程灯光控制
				Select_HC138(4);
				state = (state & 0xf0) | (~command & 0x0f);     //保留state高4位,取~command的低4位,然后组合
				P0 = state;			  //将当前状态赋值给P0
				Select_HC138(0);
				break;

			case 0xb0:				  //读取系统运行时间
				Send_byte((hour/10 << 4) | (hour%10));       //发送时
				//Send_string("-");							 //分隔符
				Send_byte((minute/10 << 4) | (minute%10));   //发送分
				//Send_string("-");							 //分隔符
				Send_byte((second/10 << 4) | (second%10));   //发送秒
				//Send_string("\r\n");                       //换行 
				break;
		}
		command = 0;
	}
}
/*=========================================================================*/


/*=================================主函数==================================*/
void main()
{
	Init_system();           //初始化
	Check_LED();	         //LED检测
	Check_SMG();	         //数码管检测
	Init_uart();	         //串口初始化
	Init_timer0();	         //定时器0初始化
	while(1)
	{
		Dynamic_display();   //数码管动态显示
		Press_keys();		 //独立按键
		Command_process();   //命令处理
	}
}
/*=========================================================================*/	

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值