CT107D:15、基础技能综合实训案例解析

工厂灯光控制系统--功能需求

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

1、设计系统初始化函数,关闭蜂鸣器和继电器等无关设备。

2、设计设备检测函数,首先检测LED指示.灯,从L1~L8依次逐个点亮,再依次逐个熄灭;然后检查数码管,从左到右依次点亮数码管的所有段码,再依次从左到右熄灭。

3、系统从上电开始显示系统运行时间,从00时00分00秒开始,显示格式:

12-00-02
12时间隔0分间隔2秒

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。
1高4位低4位例如:命令0xA6点亮L2和L3,关闭L1和L4
AL4L3L2L1
控制灯光命令字0:关灯        1:开灯
2高4位低4位例如:命令0xB0返回数据0x12 0x24 0x16
B0000
读取时间命令字保留,均为0

 

 

 

#include "reg52.h"

sfr AUXR=0x8e;
sbit HC138_A=P2^5;
sbit HC138_B=P2^6;
sbit HC138_C=P2^7;
sbit S5=P3^2;
sbit S4=P3^3;

//存储min,s,ms的值
unsigned char min=0;
unsigned char s=0;
unsigned char ms_50=0;
unsigned char hour=0;

unsigned char state_led=0xff;
unsigned char command=0;


unsigned char code duanma[18]=
{0xc0,//0
0xf9,//1
0xa4,//2
0xb0,//3
0x99,//4
0x92,//5
0x82,//6
0xf8,//7
0x80,//8
0x90,//9
0x88,//A
0x80,//B
0xc6,//C
0xc0,//D
0x86,//E
0x8e,//F
0xbf,//-
0x7f//.
};

void delay(unsigned int t)
{
	while(t--);
	while(t--);
}

//选通led
void led()
{
	HC138_A=0;
	HC138_B=0;
	HC138_C=1;		
}


//选通com端
void com()
{
	HC138_A=0;
	HC138_B=1;
	HC138_C=1;	
}
//选通数码管
void shu()
{
	HC138_A=1;
	HC138_B=1;
	HC138_C=1;	
}
//取消选通
void cancel()
{
	HC138_A=0;
	HC138_B=0;
	HC138_C=0;
}
//********************初始化系统*******************
void init_system()
{
	HC138_A=1;
	HC138_B=0;
	HC138_C=1;
	P0=0x00;//蜂鸣器、继电器
	HC138_A=0;
	HC138_B=0;
	HC138_C=1;
	P0=state_led;
	cancel();
}
//*******************检测led***************
void check_led()
{
	char i;
	led();
	for(i=0;i<9;i++)//逐个点亮led灯
	{
		state_led=0xfe<<i;
		P0=state_led;
		delay(60000);
	}
	for(i=0;i<9;i++)//逐个熄灭led灯
	{
		state_led=~(0xfe<<i);
		P0=state_led;
		delay(60000);
	}
	cancel();
}
//*****************检测数码管*************
void check_smg()
{
	char i;
	shu();
	P0=0X00;
	for(i=0;i<9;i++)//逐个点亮数码管
	{
		com();
		P0=~(0xfe<<i);
		delay(60000);
	}
	for(i=0;i<9;i++)//逐个熄灭数码管
	{
		com();
		P0=0xfe<<i;
		delay(60000);
	}
}
//*************初始化定时器T0******************
void init_timer0()
{
	TMOD=0X21;//T0和T1的工作模式同时赋值
	TH0=(65535-50000)/256;//计数初值为50ms
	TL0=(65535-50000)%256;
	ET0=1;//使能定时器T0
	EA=1;//使能总中断
	TR0=1;//启动定时器
}

//******************定时器T0中断服务函数**************
void service_timer0() interrupt 1
{
	//重装初值
	TH0=(65535-50000)/256;
	TL0=(65535-50000)%256;
 
	ms_50++;
	if(ms_50==20)//达到1s
	{
		s++;
		ms_50=0;
		if(s==60)//达到1min
		{
			min++;
			s=0;
		}
		if(min==60)//达到1h
		{
			min=0;
			hour++;
		}
	}
}

//*****************串口初始化******************
void init_uart()
{
	TMOD=0x21;//T0和T1的工作模式同时赋值
	TH1=0XFD;//设置波特率9600波特率的参数
	TL1=0XFD;
	TR1=1;//启动定时器T1
	
	SCON=0X50;//8位UART模式,运行接收
	AUXR=0X00;//辅助寄存器设置

	ES=1;//使能串口中断
	EA=1;//使能总中断
}

//*************串口中断服务函数***************
void service_uart() interrupt 4
{
	if(RI==1)
	{
		command=SBUF;//将接收到的数据保存到command变量
		RI=0;//将接收完成标志RI清0
	}
}

//**************串口发送单字节函数*********************
void send_byte(unsigned char dat)
{
	 SBUF=dat;
	 while(TI==0);
	 TI=0;
}

//*************解析命令***************
void execute_command()
{
	if(command!=0x00)//接收到一个上位机命令
	{
		 switch(command&0xf0)//将命令类型
		 {
		 	 case 0xa0://远程灯光控制命令
			 led();
			 state_led=(state_led|0x0f)&(~command|0xf0);
			 P0=state_led;
			 cancel();
			 command=0x00;
			 break;

			 case 0xb0://读取现场系统运行时间命令
			 send_byte((hour/10<<4)|(hour%10));
			 send_byte((min/10<<4)|(min%10));
			 send_byte((s/10<<4)|(s%10));
			 command=0x00;
			 break;
		 }
	}
}
//*******************系统时间显示****************
void display_bit(unsigned char value,unsigned char pos)//位显示
{
	P0=0XFF;//消隐
	com();
	P0=0x01<<pos;//左移多少位就第几个数码管亮
	shu();
	P0=value;
}

void delay_shumaguan(unsigned int t)
{
	while(t--);
}
//动态显示
void display()
{
	//s
	display_bit(duanma[s%10],7);
	delay_shumaguan(500);
	display_bit(duanma[s/10],6);
	delay_shumaguan(500);
 
	display_bit(duanma[16],5);
	delay_shumaguan(500);
	//min
	display_bit(duanma[min%10],4);
	delay_shumaguan(500);
	display_bit(duanma[min/10],3);
	delay_shumaguan(500);
 
	display_bit(duanma[16],2);
	delay_shumaguan(500);
 
	//hour
	display_bit(duanma[hour%10],1);
	delay_shumaguan(500);
	display_bit(duanma[hour/10],0);
	delay_shumaguan(500);
}

//******************独立按键的处理*************
void scan_key()
{
	if(S5==0)//发现按键S5的信号
	{
		display();//去抖动处理
		if(S5==0)//确认按键S5的信号
		{
			while(S5==0)//等待按键S5松开(此时系统时间需要在运行状态)
			{
				display();
			}
			led();
			state_led=(state_led|0x40)&(~state_led|0xbf);
			P0=state_led;//执行现场灯光控制
			cancel();
		}
	}

	if(S4==0)//发现按键S4的信号
	{
		display();//去抖动处理
		if(S4==0)
		{
			while(S4==0)
			{
				display();
			}
			led();
			state_led=(state_led|0x80)&(~state_led|0x7f);
			P0=state_led;//执行现场灯光控制
			cancel();
		}
	}
}
//整个工厂灯光控制系统的主函数
void main()
{
	init_system();
	check_led();
	check_smg();
	init_timer0();
	init_uart();

	while(1)
	{
		execute_command();
		display();
		scan_key();	
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值