设计程序,用于本地和远程控制现场灯光的开关,并能通过串口远程读取工厂的系统运行时间。
- 设计系统初始化函数,关闭蜂鸣器和继电器等无关设备。
- 设计设备检测函数,首先检测LED指示灯,从L1~L8依次逐个点亮,再依次逐个熄灭;然后检查数码管,从左到右依次点亮数码管的所有段码,再依次从左到右熄灭。
- 系统从上电开始显示系统运行时间。从00时00分00秒开始,显示格式:
- 八个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--);
}