工厂灯光控制系统--功能需求
题目:在CT107D单片机综合训练平台上,设计程序,用于本地和远程控制现场灯光的开关,并能通过串口远程读取工厂的系统运行时间。
1、设计系统初始化函数,关闭蜂鸣器和继电器等无关设备。
2、设计设备检测函数,首先检测LED指示.灯,从L1~L8依次逐个点亮,再依次逐个熄灭;然后检查数码管,从左到右依次点亮数码管的所有段码,再依次从左到右熄灭。
3、系统从上电开始显示系统运行时间,从00时00分00秒开始,显示格式:
1 | 2 | - | 0 | 0 | - | 0 | 2 |
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 | |||
A | L4 | L3 | L2 | L1 | ||
控制灯光命令字 | 0:关灯 1:开灯 | |||||
2 | 高4位 | 低4位 | 例如:命令0xB0返回数据0x12 0x24 0x16 | |||
B | 0 | 0 | 0 | 0 | ||
读取时间命令字 | 保留,均为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();
}
}