【蓝桥杯08】——工厂灯光控制系统

设计程序,用于本地和远程控制现场灯光的开关,并能通过串口远程读取工厂的系统运行时间。

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

void Init();  //系统初始化,关闭无关设备
void InTimer(); //定时器初始化
void Init_Uart();//串口初始化

void LED_Test();//LED灯测试
void SMG_Test();//数码管测试

void show(unsigned int w,unsigned int n); //数码管显示指定数据
void Time_show();//时间显示
void SendByte(unsigned char dat); //单字节发送数据
void execute();  //数据解析函数

void selectHC(unsigned int n); //寄存器选择
void delay_ms(int n); //延时函数
void scanKeys(); //按键扫描

unsigned char table[]={
    
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};//0xbf为数码管显示 ——
unsigned char which[]={
    
    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

sbit S5 = P3^2;  //控制L7
sbit S4 = P3^3;  //控制L8

unsigned char hour=0;  //时
unsigned char min=0;   //分钟
unsigned char sec=0;   //秒
unsigned char count=0; //毫秒
unsigned char command=0;       //存放串口数据
unsigned char stat_LED=0xff;   //stat_LED作为暂时储存P0的值


void main()
{
    
    
	Init();
	LED_Test();
	SMG_Test();
	InTimer();
	Init_Uart();
	while(1)
	{
    
    
		execute();
		Time_show();
		scanKeys();
  }
}

/*===================LED灯检测函数=====================
功能:测试LED灯
=======================================================*/
void LED_Test()
{
    
    
	 unsigned char i = 0;
   selectHC(4);
   for(i = 0 ; i < 8 ; i++)
   {
    
    
    P0 = 0xFE << i;
	  delay_ms(2000); 
   }
	 delay_ms(2000);
   for(i = 0 ; i < 8 ; i++)
   {
    
    
    P0 = ~(0x7F >> i);
	  delay_ms(2000);
   }
}


/*===================数码管检测函数====================
功能:测试数码管
=======================================================*/
void SMG_Test()
{
    
    
	 unsigned char i = 0;
   selectHC(7);
   P0 = 0x00;
   for(i = 0 ; i < 8 ; i++)
   {
    
    
    selectHC(6);
	  P0 = ~(0xFE << i);
	  delay_ms(2000);
   }
   for(i = 0 ; i < 8 ; i++)
   {
    
    
    selectHC(6);
	  P0 = 0x7F >> i;
	  delay_ms(2000);
   }
   selectHC(0);
}

/*==================系统初始化函数======================
功能:关闭无关设备
=======================================================*/
void Init()
{
    
    
	selectHC(5);
	P0=0x00;
	selectHC(4);
  P0 = stat_LED;
  selectHC(0);
}

/*==================寄存器选择函数======================
功能:选择指定的功能寄存器
=======================================================*/
void selectHC(unsigned int n)
{
    
    
	switch(n)
	{
    
    
		case 4: P2=(P2&0x1f)|0x80; break; //LED灯
		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; //锁存数据,退出前一锁存器,防止改变数据。
		default: break;
	}
}
/*==================数码管显示函数======================
功能:第w位数码管显示数字n
=======================================================*/
void show(unsigned int w,unsigned int n)
{
    
    
	selectHC(6);
	P0=which[w-1];
	selectHC(7);
	P0=table[n];
	delay_ms(5);
	P0=0xff;
	P2&=0x1f;
}

/*===================时间显示函数======================
功能:显示时间
=======================================================*/
void Time_show()
{
    
    
	unsigned char i;
	for(i=0;i<8;i++)
		{
    
    
			switch(i)
			{
    
    
				case 7:show(8,sec%10);delay_ms(5);break;
				case 6:show(7,sec/10);delay_ms(5);break;
				case 5:show(6,10);delay_ms(5);break;
				case 4:show(5,min%10);delay_ms(5);break;
				case 3:show(4,min/10);delay_ms(5);break;
				case 2:show(3,10);delay_ms(5);break;
				case 1:show(2,hour%10);delay_ms(5);break;
				case 0:show(1,hour/10);delay_ms(5);break;
		  }
		}
}
//***********************************************************************************************************
/*=================定时器T0初始化函数===================
功能:初始化定时器T0
=======================================================*/
void InTimer()
{
    
    
	TMOD=0X21;    //定时器0十六位计数模式
  TH0=(65536-50000)/256;    //50ms计时 
	TL0=(65536-50000)%256;
	ET0=1;
	EA=1;            
	TR0=1;
}
/*================定时器T0中断服务函数===================
功能:时间计时
=======================================================*/
void seviceTimer() interrupt 1
{
    
    
	 TH0=(65536-50000)/256;    
	 TL0=(65536-50000)%256;
	 count++;
	 if(count==20)  //说明到了20*50ms=1S,
	 {
    
    
		 count=0;
		 sec++;   //秒加1
		 if(sec==60)
		 {
    
    
			 sec=0;
			 min++;    //分加1
			 if(min==60)
			 {
    
    
				 min=0;
				 hour++;
				 if(hour==24)
				 {
    
    
					 sec=0;
					 min=0;
					 hour=0;
			   }
		   }
	   }
   }
}
//***********************************************************************************************************
/*=================串口初始化函数======================
功能:串口初始化
=======================================================*/
void Init_Uart()
{
    
    
	 TMOD=0X21;  //定时器1工作模式为自动重装
	 TH1=0XFD;   //设置波特率为9600,  11.0592M或12M的12分频
	 TL1=0XFD;
	 
	 TR1=1;      //启动定时器1
	 AUXR=0X00;  //bit7=1:定时器1不分频,0则12分频
	           
   SCON = 0x50;      //串口参数为模式1和允许接收
   ES=1;             //使能串口中断
   EA=1;             //使能总中断
}

/*=================串口服务函数======================
功能:串口服务
=======================================================*/
void ServiceUart() interrupt 4
{
    
        
	 if(RI==1)  //接收到一个完整的字节  如果RI==1就说明接收到一个完整的数据
	 {
    
    
		 command=SBUF;  //接收到的数据放在 command 里面
	 	 RI=0;          //人工清零  清除接收完成标志
   }
}
/*===============串口发送单字节函数====================
功能:发送单字节数据
=======================================================*/
void SendByte(unsigned char dat)
{
    
    
   SBUF=dat;     //将数据放进SBUF缓冲器
	 while(TI==0); //等待发送数据完成
	 TI=0;         //清除发送完成标志 
}
/*===============上位机命令解析执行函数=================
功能:接收上位机的数据并保持在command变量中
=======================================================*/
void execute()
{
    
    
   if(command != 0x00)
   {
    
    
      switch (command & 0xF0)
	  {
    
    
	     case 0xA0 :
		 selectHC(4);
		 stat_LED = (stat_LED | 0x0F) & (~command | 0xF0);
		 P0 = stat_LED;
		 selectHC(0);
		 command = 0x00;//清零
		 break;

		 case 0xB0 :
		 SendByte(((hour / 10) << 4 ) |(hour % 10));//发送时
		 SendByte(((min / 10) << 4 ) |(min % 10));//发送分
		 SendByte(((sec / 10) << 4 ) |(sec % 10));//发送秒
		 command = 0x00;//清零
		 break;
	  }
   }
}
/*=================独立按键扫描函数====================
功能:扫描S5和S4按键并执行现场灯光控制。
=======================================================*/
void scanKeys()
{
    
    
   if(S5 == 0)
   {
    
    
			delay_ms(5);	//按键消抖
			if(S5 == 0)
			{
    
    
				while(S5 == 0)
				{
    
    
					delay_ms(5);
				}
				selectHC(4);
				stat_LED = (stat_LED | 0x40) & (~stat_LED | 0xBf);//控制L7亮灭
				P0 = stat_LED;
				selectHC(0);
			}	
   }
   if(S4 == 0)
   {
    
    
      delay_ms(5);  //按键消抖
			if(S4 == 0)
			{
    
    
				while(S4 == 0)
				{
    
    
					delay_ms(5);
				}
				selectHC(4);
				stat_LED = (stat_LED | 0x80) & (~stat_LED | 0x7f);//控制L8亮灭
				P0 = stat_LED;
				selectHC(0);
	    }
   }
}

/*=====================延时函数========================
功能:扫描S5和S4按键并执行现场灯光控制。
=======================================================*/
void delay_ms(int n)
{
    
    
	int i,j;
	for(i=n;i>0;i--)
	for(j=110;j>0;j--);
}

猜你喜欢

转载自blog.csdn.net/z3447643805/article/details/113818354
今日推荐