远程灯光控制系统

一、任务要求

在CT107D单片机上,设计程序:用于本地和远程控制现场灯光的开关,并能通过串口远程读取工厂的系统运行时间。
1.设计系统初始化函数,关闭蜂鸣器和继电器等无关设备;
2.设计设备检测函数,首先检测LED指示灯,从L1~L8依次逐个点亮,再依次逐个熄灭;然后检测数码管,从左到右依次点亮数码管的所有段码,再依次从左到右熄灭。
3.系统从上电开始显示系统运行时间,从00时00分00秒开始,显示格式:00-00-00;
4.八个LED指示灯分为两组:L1——L4为远程控制组,L7——L8为本地控制组。远程控制组的指示灯由上位机通过串口发送命令控制开关,本地控制组的指示灯由独立按键控制开关。按键检测需做去抖动处理,松开有效,按键S5控制S7,按键S4控制L8.
串口方面
1.串口工作在8位UART模式,波特率为9600BPS;
2.上位机通过串口控制下位机的L1——L4指示灯和读取系统运行时间;
3.控制命令为一个字节,高四位为命令类型,低四位为执行参数;
4.控制灯光开关命令中,低四位每一位控制一个LED指示灯的开关,无返回值;
5.读取运行时间命令中,低四位保留,返回3个字节的时间数据,用16进制的BCD码表示,先发时,再发分,后发秒。如果系统运行时间为12时24分16秒,收到读取时间命令后,返回 0x12 0x24 0x16。

二、实验结果

上位机通过串口控制下位机的L1——L4指示灯和读取系统运行时间:
在这里插入图片描述
串口发送a0,单片机LED0指示灯亮:
在这里插入图片描述
在这里插入图片描述

三、参考代码

#include <STC15F2K60S2.H>


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

unsigned char stat_led = 0xff;
unsigned char count = 0;
unsigned char t_s = 0;
unsigned char t_m = 0;
unsigned char t_h = 0;
unsigned char command = 0x00;
unsigned char code SEG[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
	
/*========时间延迟函数================
功能:精准延时50us误差0us。
参数:n--用户需求的时间。
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void m_delay(unsigned char n)	//满足用户需求的延迟时间n毫秒
{
	unsigned char i,j;
	for(i =  n; i > 0; i--)
		for(j = 110; j > 0; j--);
}
/*========时间延迟函数================
功能:延时t--个时间长度。
参数:n--用户需求的时间。
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void delay(unsigned char t)
{
	while(t--);
	while(t--);
}
/*========选择锁存器函数================
功能:选择相关设备的控制。
参数:channel--相应信道。
返回:无
设计:张智洪(2022年3月27日)
======================================*/
void select_HC573(unsigned char channel)
{
	switch(channel)
	{
		case 4:
			P2 = (P2 & 0x1f) | 0x80;  //Y4输出0,选择LED指示灯控制
		break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;	//Y5输出0,选择蜂鸣器与继电器控制
		break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;	//Y6输出0,选择数码管位选控制
		break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;	//Y7输出0,选择数码管段码控制
		break;	
		case 0:
			P2 = (P2 & 0x1f) | 0xff;	//Y所有锁存器不选择
		break;
	}
}
/*========初始化系统函数================
功能:关闭蜂鸣器与继电器等无关设备。
参数:无
返回:无
设计:张智洪(2022年3月27日)
======================================*/
void initial_system()
{
	select_HC573(5);
	P0 = 0x00;
	select_HC573(6);
	P0 = 0x00;
	select_HC573(4);
	P0 = stat_led;
	select_HC573(0);
}

/*========LED指示灯显示模块检测函数=====
功能:逐个检查LED指示灯是否正常工作。
参数:无
返回:无
设计:张智洪(2022年3月27日)
=======================================*/	
void check_LED()
{
	unsigned char i;
	select_HC573(4);
	for(i = 0; i < 9; i++)
	{
		stat_led = 0xfe << i;
		P0 = stat_led;
		m_delay(200);
	}
	for(i = 0; i < 9; i++)
	{
		stat_led = ~(0xfe << i);
		P0 = stat_led;
		m_delay(200);
	}
	select_HC573(0);
}
/*========时间显示模块检测函数=========
功能:逐个检查数码管是否正常工作。
参数:无
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void check_SEG()
{
	unsigned char i;
	select_HC573(7);
	P0 = 0x00;
	for(i = 0; i < 9; i++)
	{
		select_HC573(6);
		P0 = ~(0xfe << i);  //逐个点亮数码管
		m_delay(200);
	}
	for(i = 0; i < 9; i++)
	{
		select_HC573(6);
		P0 = 0xfe << i;		逐个关闭数码管
		m_delay(200);
	}
	select_HC573(0);
}
/*========数码管显示控制模块函数=========
功能:控制数码管输出函数。
参数:pos--控制数码管位选,val--控制数码管显示的内容。
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void out_SEG_bit(unsigned char val,unsigned char pos)
{
	P0 = 0xff;		//消隐
	select_HC573(6);
	P0 = 0x01 << pos;
	select_HC573(7);
	P0 = val;
}
/*========定时器0初始化模块函数=========
功能:初始化定时器各项参数。
参数:无
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void initial_Timer0()
{
	TMOD = 0x21;		//确保程序后面的串口开启时不会使定时器0关闭。
	TH0 = (65535 - 50000) / 256;
	TL0 = (65535 - 50000) % 256;
	TR0 = 1;
	
	ET0 = 1;
	EA = 1;
}
/*========串口初始化模块函数=========
功能:将串口初始化位模式1,波特率位9600,允许接收。
参数:无
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void initial_URAT()
{
	TMOD = 0x21;//T0和T1一起赋值!设置定时器1的工作模式并保持打开定时器0。
	TH1 = 0xfd; //    TH1和TL1:设置波特率参数9600。
	TL1 = 0xfd;
	TR1 = 1; 		//打开定时器1。
	
	
	SCON = 0x50;	// //0101 0000,选择8位的URAT工作模式,允许接收数据。
	AUXR = 0x00;
	ES = 1;//打开串口中断开关。
	EA = 1;	//打开总中断开关。
}
/*========定时器0中断服务模块函数=========
功能:利用中断1实现秒、分和时 计数。
参数:count--50ms一次,t_s--秒,t_m--分,t_h--时。
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void service_Timer0() interrupt 1
{
	TH0 = (65535 - 50000) / 256;
	TL0 = (65535 - 50000) % 256;
	count++;
	if(count == 20)
	{
		t_s++;
		count = 0;
	}
	if(t_s == 60)
	{
		t_m++;
		t_s = 0;
	}
	if(t_m == 60)
	{
		t_h++;
		t_m = 0;
	}
}
/*========数码管时间延迟函数================
功能:特定数码管延时相应时间。
参数:t--延时长度。
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void SEG_delay(unsigned char t)
{
	while(t--);
}
/*========数码管显示模块函数=========
功能:数码管按照 时:分:秒 格式输出函数。
参数:pos--控制数码管位选,val--控制数码管显示的内容。
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void SEG_action()
{
	out_SEG_bit(SEG[t_s % 10],7);
	SEG_delay(500);
	out_SEG_bit(SEG[t_s / 10],6);
	SEG_delay(500);
	out_SEG_bit(SEG[16],5);
	SEG_delay(500);
	
	out_SEG_bit(SEG[t_m % 10],4);
	SEG_delay(500);
	out_SEG_bit(SEG[t_m / 10],3);
	SEG_delay(500);
	out_SEG_bit(SEG[16],2);
	SEG_delay(500);
	
	out_SEG_bit(SEG[t_h % 10],1);
	SEG_delay(500);
	out_SEG_bit(SEG[t_h / 10],0);
	SEG_delay(500);
}
/*========定时器1中断服务模块函数=========
功能:串行接口接收的内容。
参数:command--用户命令,用于打开某个LED指示灯。
返回:无
设计:张智洪(2022年3月27日)
======================================*/	
void service_URAT() interrupt 4
{
	if(RI == 1)	//RI--串行接口接收完成中断的标志。
	{
		command = SBUF;
		RI = 0;
	}
}

/*========串口发送单字节模块函数=========
功能:串口向上位机发送一个字节。
参数:dat--要发送的内容。
返回:空
设计:张智洪(2022年3月27日)
======================================*/
void send_byte(unsigned char dat)
{
	SBUF = dat;
	while(TI == 0);		//TI--串行接口发送完成中断的标志。
	TI = 0;
}

/*========上位机命令解析执行模块函数=========
功能:接受上位机的数据并保持在command变量中。
参数:无
返回:空
设计:张智洪(2022年3月27日)
======================================*/
void execute_command()
{
	if(command != 0x00)
	{
		switch(command & 0xf0)	//取出命令类型。
		{
			case 0xa0:						//远程灯光控制命令。
				select_HC573(4);
				stat_led = (stat_led | 0x0f) & (~command | 0xf0);	保留P0高四位,改变低四位,command保留低四位。
				P0 = stat_led;
				select_HC573(0);
				command = 0x00;
			break;
			
			case 0xb0:
				send_byte((t_h / 10 << 4) | (t_h % 10));	//读取 现场 系统时间 命令。
				send_byte((t_m / 10 << 4) | (t_m % 10));
				send_byte((t_s / 10 << 4) | (t_s % 10));
				command = 0x00;
			break;
		}
	}
}
/*========独立按键控制LED指示灯模块函数=======
功能:独立按键取S4和S5部分控制LED7和LED8。
参数:无
返回:无
设计:张智洪(2022年3月27日)
=============================================*/	
void scan_button_keys()
{
	if(S4 == 0)
	{
		delay(60000);
		if(S4 == 0)
		{
			while(S4 == 0)
			{
				SEG_action();
			}
			select_HC573(4);
			stat_led = (stat_led | 0x80) & (~stat_led | 0x7f);	//此行代码意思为:第一种情况:LED7熄灭的情况下,按键S4按着不动是不会跳转亮灯状态的;
																													//第二种情况:LED7亮灯的情况下,按键S4 按着不动也不会跳转到熄灭状态。
			P0 = stat_led;
			select_HC573(0);
		}
	}
	if(S5 == 0)
	{
		delay(60000);
		if(S5 == 0)
		{
			while(S5 == 0)
			{
				SEG_action();
			}
			select_HC573(4);
			stat_led = (stat_led | 0x40) & (~stat_led | 0xbf);	//此行代码意思为:第一种情况:LED8熄灭的情况下,按键S5按着不动是不会跳转亮灯状态的;
																													//第二种情况:LED8亮灯的情况下,按键S5 按着不动也不会跳转到熄灭状态。
			P0 = stat_led;
			select_HC573(0);
		}
	}
}


void main()
{
	initial_system();
	check_LED();
	check_SEG();
	initial_Timer0();
	initial_URAT();
	while(1)
	{
		execute_command();
		SEG_action();
		scan_button_keys();
		
	}
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Born_toward

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

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

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

打赏作者

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

抵扣说明:

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

余额充值