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

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

在这里插入图片描述

#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
    评论
数码管是一种常见的数字显示器件,可以用于显示各种数字、字母等字符。在单片机应用中,数码管通常用于显示计数器、计时器、温度、湿度等实时数据。 数码管的种类有很多,包括共阳数码管、共阴数码管、共阳共阴混合数码管等。其中,共阳数码管是最常见的一种,也是本文所涉及的数码管类型。 单片机控制数码管的原理是通过对数码管的各个管脚进行控制,使其显示相应的数字或字符。数码管的控制方式有两种,即静态显示和动态显示。 静态显示是指将要显示的数字或字符的每一位分别输出到数码管的每个管脚上,然后使其保持不变,从而实现显示效果。静态显示的缺点是需要使用大量的I/O口,且不能灵活地改变显示内容。 动态显示是指将要显示的数字或字符的每一位依次输出到数码管的每个管脚上,并在短时间内快速切换下一个数字或字符,从而形成连续的显示效果。动态显示的优点是可以使用较少的I/O口,且可以灵活地改变显示内容。 以下是一个简单的动态显示数码管的实现示例: 1. 定义数码管的引脚 ```c #define DIG_PORT P2 // 数码管位选端口 #define DIG_COM 0x00 // 数码管位选端口初始值 #define LED_PORT P0 // 数码管段选端口 ``` 2. 定义数码管显示的数字或字符 ```c unsigned char code ledChar[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f }; ``` 3. 实现数码管动态显示函数 ```c void display(unsigned char i) { unsigned char j, k; for (j = 0; j < 8; j++) { DIG_PORT = DIG_COM | (1 << j); // 选择数码管位(从左到右) for (k = 0; k < 100; k++); // 延时,视情况可调整 LED_PORT = ledChar[i]; // 显示数码管上的数字或字符 } } ``` 4. 调用数码管动态显示函数 ```c int main() { unsigned char i = 0; while (1) { display(i % 10); // 显示数字 i 的个位数 i++; } return 0; } ``` 以上就是一个简单的数码管动态显示的实现示例。需要注意的是,数码管的控制方式和具体实现方法可能因不同的硬件平台和编程语言而有所不同。因此,在具体应用中需要根据实际情况进行适当的调整和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值