蓝桥杯之单片机学习(十四)——基础技能综合实训案例解析

一、训练任务

在CT107D单片机综合训练平台上,设计程序,用于本地和远程控制现场灯光的开关,并能通过串口远程读取工厂的系统运行时间。

二、训练要求

  1. 设计系统初始化函数,关闭蜂鸣器和继电器等无关设备。
  2. 设计设备检测函数,首先检测LED指示灯,从L1~L8依次逐个点亮,再依次逐个熄灭;然后检查数码管,从左到右依次点亮数码管的所有段码,再依次从左到右熄灭。
  3. 系统从上电开始显示系统运行时间,从00时00分00秒开始,显示格式:
    在这里插入图片描述
  4. 八个LED指示灯分为2组: L1-L4远程控制组,L7-L8本地控制组。远程控制组的指示灯由上位机通过串口发送命令控制开关,本地控制组的指示灯由独立按键控制开关。按键检测需做去抖动处理,松开有效,按键S5控制L7,按键S4控制L8。

三、通信规约

  • 串口工作在8位UART模式,波特率为9600BPS
  • 上位机通过串口控制下位机的L1~L4指示灯和读取系统运行时间。
  • 控制命令为一一个字节, 高4位为命令类型,低4位为执行参数。
  • 控制灯光开关命令中,低4位每1位控制一个LED灯 的开关,无返回值。
  • 读取运行时间命令中,低4位保留,各位为0,返回3个字节的时间数据,用16进制的BCD码表示,先发时,再发分,后发秒。如果系统运行的时间为12时24分16秒,收到读取时间命令字后,返回: 0x12 0x24 0x16。
  • 在这里插入图片描述

代码展示

#include <reg52.h>

typedef unsigned int uint;
typedef unsigned char uchar;

sfr AUXR = 0X8e;

sbit S5 = P3^2;
sbit S4 = P3^3;

sbit L7 = P0^6;
sbit L8 = P0^7;

uchar code SMG_duanma[18] = 
	{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
	 0x88,0x80,0xc6,0xc0,0x86,0x8e,
	 0xbf,0x7f};//分别是0-9(对应下标),A-F,“-”,“.”

uchar time_005s = 0;
uchar time_s = 0;
uchar time_m = 0;
uchar time_h = 0;
	 
void SMGDisplay();
	 
//配置HC138
void SelectHC138(uchar channel)
{
	switch(channel)
	{
		case 4:    //LED
			P2 = (P2 & 0X1F) | 0X80;
		break;
		case 5:    //蜂鸣器和继电器
			P2 = (P2 & 0X1F) | 0Xa0;
		break;
		case 6:    //位码
			P2 = (P2 & 0X1F) | 0Xc0;
		break;
		case 7:    //段码
			P2 = (P2 & 0X1F) | 0Xe0;
		break;
		case 0:    //锁住所有寄存器
			P2 = (P2 & 0X1F) | 0X00;
		break;
	}
}

//在pos位码上,显示value段码
void DisplaySMG_Bit(uchar pos, uchar value)
{
	SelectHC138(6);
	P0 = 0X01 << pos;
	SelectHC138(7);
	P0 = value;
}

void Initsys()
{
	SelectHC138(5);
	P0 = 0X00;//关闭蜂鸣器和继电器
	SelectHC138(4);
	P0 = 0XFF;//关闭LED
}

void Delay_CL_CSMG(uint t)
{
	while(t--);
	while(t--);
}
void CheckSys()
{
	//检测LED
	uchar i;
	SelectHC138(4);
	for(i = 1; i <= 8; i++)
	{
		P0 = 0XFF << i;
		Delay_CL_CSMG(60000);
		Delay_CL_CSMG(60000);
	}
	for(i = 1; i <= 8; i++)
	{
		P0 = ~(0XFF << i);
		Delay_CL_CSMG(60000);
		Delay_CL_CSMG(60000);
	}
	//检测数码管
	for(i = 0; i < 8; i++)
	{
		DisplaySMG_Bit(i, 0X00);
		Delay_CL_CSMG(60000);
		Delay_CL_CSMG(60000);
	}
	P0 = 0XFF;
}
//*********************************
//本地控制
void Delay_K(uint t)
{
	while(t--);
}

void LocalCheck()
{
	SelectHC138(4);
	if(S4 == 0)
	{
		Delay_K(100);
		if(S4 == 0)
		{
			L8 = 0;
		}
		while(S4 == 0)
		{
			SMGDisplay();
		}
		L8 = 1;
	}
	if(S5 == 0)
	{
		Delay_K(100);
		if(S5 == 0)
		{
			L7 = 0;
		}
		while(S5 == 0)
		{
			SMGDisplay();
		}
		L7 = 1;
	}
}
//*********************************

//*********************************
//定时器
void InitTimer0()
{
	TMOD = 0X01;
	TH0 = (65535 - 50000) / 256;
	TL0 = (65535 - 50000) % 256;
	
	ET0 = 1;
	EA = 1;
	TR0 = 1;
}

void ServiceTimer0() interrupt 1
{
	TH0 = (65535 - 50000) / 256;
	TL0 = (65535 - 50000) % 256;
	time_005s++;
	if(time_005s == 20)
	{
		time_005s = 0;
		time_s++;
		if(time_s == 60)
		{
			time_s = 0;
			time_m++;
		}
		if(time_m == 60)
		{
			time_m = 0;
			time_h++;
		}
		if(time_h == 99)
		{
			time_h = 0;
		}
	}
}
//*********************************

//数码管显示
void Delay_SMG(uint t)
{
	while(t--);
}

void SMGDisplay()
{
	DisplaySMG_Bit(0, SMG_duanma[time_h / 10]);
	Delay_SMG(500);
	DisplaySMG_Bit(1, SMG_duanma[time_h % 10]);
	Delay_SMG(500);
	DisplaySMG_Bit(2, SMG_duanma[16]);
	Delay_SMG(500);
	
	DisplaySMG_Bit(3, SMG_duanma[time_m / 10]);
	Delay_SMG(500);
	DisplaySMG_Bit(4, SMG_duanma[time_m % 10]);
	Delay_SMG(500);
	DisplaySMG_Bit(5, SMG_duanma[16]);
	Delay_SMG(500);

	DisplaySMG_Bit(6, SMG_duanma[time_s / 10]);
	Delay_SMG(500);
	DisplaySMG_Bit(7, SMG_duanma[time_s % 10]);
	Delay_SMG(500);
	P0 = 0XFF;
}
//************************************
//串口通信
uchar command = 0;

void InitUart()
{
	TMOD = 0X20;
	TH1 = 0XFD;
	TL1 = 0XFD;
	TR1 = 1;
	
	SCON = 0X50; //模式1
	AUXR = 0X00;
	
	ES = 1;
	EA = 1;
}

void ServiceUart() interrupt 4
{
	if(RI == 1)
	{
		command = SBUF;
		RI = 0;
	}
}

void SendByteUart(uchar dat)
{
	SBUF = dat;
	while(TI == 0);
	TI = 0;
}


void UartWorking()
{
	if(command != 0)
	{
		SelectHC138(4);
		switch(command & 0XF0)
		{
			 case 0xA0:
				 P0 = (P0 | 0X0F) & (~command | 0XF0); //保留高4位,反转低四位
				 command = 0X00;
			 break;
			 case 0xB0:
				 SendByteUart((time_h / 10 << 4) | (time_h % 10));
			   SendByteUart((time_m / 10 << 4) | (time_m % 10));
			   SendByteUart((time_s / 10 << 4) | (time_s % 10));
				 command = 0X00;
			 break;
		}
	}
}
//************************************
void main()
{
	Initsys();
	CheckSys();
	InitTimer0();
	InitUart();
	InitUart();
	while(1)
	{
		LocalCheck();
		SMGDisplay();
		UartWorking();
	}
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周末不下雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值