/****************************************************************** * 操作描述:
* 1.按Switch键可以启动或停止秒表走表,首次按会清零记录次数
* 2.秒表走表期间,按RecorRead按键可以记录当前时间(不影响秒表走表)
* 3.按Reset键,表值清零,按RecordRead键可以回读此前记录的对应次数与时间 * 4.按TimeMove进入秒表时间设置模式,连按可以移动光标到对应位(限秒以上), * 只在该模式下按TimeUp键才可以累加数值,该模式下按Switch可以开始计时, * 按Reset可以退出,计时到设定值后声光提示
* 时间:2016-04-19
********************************************************************/ /****************************************************************** * 硬件描述:
* 主芯片:stc89c51
* 显示器件:lcd1602
* 时间:2016-04-19
********************************************************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define DelayNOP() {_nop_();_nop_();_nop_();_nop_();}
#define timer0_DISABLE() TR0 = 0 //关闭定时器0
#define timer0_ENABLE() TR0 = 1 //开启定时器0
bit LCD_Busy_Check();
void LCD_Initialize();
void LCD_Set_POS(uchar);
void LCD_Write_Command(uchar);
void LCD_Write_Data(uchar);
void Display_String(uchar*str,uchar LineNo);
void LCD1602_Display();
sbit Key_Switch = P1^0;//秒表启动与停止按键
sbit Key_Reset = P1^1;//秒表复位清零按键
sbit Key_RecordRead = P1^2;//记录时间与回读
sbit Key_TimeMove = P1^3;//时间设置光标移动
sbit Key_TimeUp = P1^4;//时间设置增加
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit BEEP_LED = P2^7;
bit KeySwitch = 0;
bit TimeSetMode = 0;
bit TimeMode = 0;
uchar KeyRecord = 0;
//uchar KeyTimeNum =0;
uint KeyTimeSet = 0;
uint onems = 0;
const uchar code msg1[10][16] ={
"Record Mum 0",
"Record Mum 1",
"Record Mum 2",
"Record Mum 3",
"Record Mum 4",
"Record Mum 5",
"Record Mum 6",
"Record Mum 7",
"Record Mum 8",
"Record Mum 9",
};
const uchar code msg2[16] = {"TimerMode" };
uchar Time_Buffer[] = {0,0,0,0};
uchar TimeSet_Buffer[] = {0,0,0,0,};
uchar LCD_Display_Buffer[] = {"00:00:00:00"}; //该数组有7个元素4个00+3个‘:’ /* | | | |
| | | |1hour__
| | |1min__
| |1s__
|10ms__
数组排列与显示顺序相反
*/
uchar Time_Read[10][4]={
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
};
/*毫秒延时函数*/
void DelayMS(uint ms)
{
uchar t;
while(ms--)
{
for (t=0;t
}
}
/*定时器中断服务程序1ms进入一次*/
void Time0() interrupt 1 using 0
{
TH0 = (65536- 1000) / 256;
TL0 = (65536- 1000) % 256;
onems++;
/*10ms累加一次*/
if(onems == 10)
{
Time_Buffer[0]++;
onems = 0;
}
/*100*10ms = 1s*/
if(Time_Buffer[0]==100)
{
Time_Buffer[0]=0;
Time_Buffer[1]++;
}
/*1s * 60 = 1min*/
if(Time_Buffer[1]==60)
{
Time_Buffer[1]=0;
Time_Buffer[2]++;
}
/*1min * 60 = 1hour*/
if(Time_Buffer[2]==60)
{
Time_Buffer[2]=0;
Time_Buffer[3]++;
}
/*hour = 100时,时钟归零*/
if(Time_Buffer[3]==100)
{
Time_Buffer[3]=0;
}
/*当定时限制模式开启*/
if(TimeMode == 1)
{
if(Time_Buffer[1]==TimeSet_Buffer[1])
{
if(Time_Buffer[2]==TimeSet_Buffer[2])
{
if(Time_Buffer[3]==TimeSet_Buffer[3])
{
/*所有值相同,到达设定时间,定时器停止工作,声光提示*/ TimeMode = 0;
BEEP_LED = 0;
timer0_DISABLE();
}
}
}
}
}
/*设置光标的移动位置*/
void TimeSet()
switch(KeyTimeSet)
{
/*秒个位*/
case 1:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2+5);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
/*秒十位*/
case 2:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2+4);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
/*分个位*/
case 3:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2+2);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
/*分十位*/
case 4:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2+1);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
/*时个位*/
case 5:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2-1);
DelayMS(5);
DelayMS(1); break;
/*时十位*/
case 6:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2-2);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
default:break;
}
}
/*根据光标位置(TimeSet变量值),及TimeUP键的触发,改变对应的值*/ void TimeChange()
{
uchar i;
switch(KeyTimeSet)
{
/*second设置*/
case 1:
TimeSet_Buffer[1] = TimeSet_Buffer[1] + 1;//个位数+1 if(TimeSet_Buffer[1] % 10 == 0 )
TimeSet_Buffer[1] = TimeSet_Buffer[1] % 10;//个位数清零,保留十位数 break;
case 2:
TimeSet_Buffer[1] = TimeSet_Buffer[1] + 10;//十位数+1
if(TimeSet_Buffer[1] / 10 > 5)
TimeSet_Buffer[1] = TimeSet_Buffer[1] % 10;//十位数清零,保留个位数 break;
/*min设置*/
case 3:
TimeSet_Buffer[2] = TimeSet_Buffer[2] + 1;
if(TimeSet_Buffer[2] % 10 == 0 )
TimeSet_Buffer[2] = TimeSet_Buffer[2] % 10; break;
case 4:
TimeSet_Buffer[2] = TimeSet_Buffer[2] + 10;
if(TimeSet_Buffer[2] / 10 > 5)
TimeSet_Buffer[2] = TimeSet_Buffer[2] % 10; break;
/*hour设置*/
case 5:
TimeSet_Buffer[3] = TimeSet_Buffer[3] + 1;
if(TimeSet_Buffer[3] % 10 == 0 )
TimeSet_Buffer[3] = TimeSet_Buffer[3] % 10; break;
case 6:
TimeSet_Buffer[3] = TimeSet_Buffer[3] + 10;
if(TimeSet_Buffer[3] / 10 > 9)
TimeSet_Buffer[3] = TimeSet_Buffer[3] % 10; break;
default: break;
}
for(i=0;i
{
Time_Buffer[i] = TimeSet_Buffer[i];
}
}
void main()
{
uchar i,KeyReset;
uchar times;
IE =0x82;
TMOD = 0x01;
TH0 = (65536- 1000) / 256;
TL0 = (65536- 1000) % 256;
LCD_Initialize();
Display_String(msg1[0],0x00);
while(1)
{
/*开关键*/
if( Key_Switch == 0 )
{
DelayMS(10);
KeySwitch = ~KeySwitch;
KeyReset = 0;
if(TimeSetMode==1)
{
KeyTimeSet = 0;
TimeSetMode= 0;
TimeMode = 1;
for(i=0;i
{
Time_Buffer[i] = 0;
DelayMS(1);
}
}
if(KeySwitch == 0 )
{
timer0_DISABLE();
}
else
{
timer0_ENABLE();
}
while (Key_Switch == 0);
}
/*复位键*/
else if(Key_Reset == 0)
{
DelayMS(10);
timer0_DISABLE();
times = KeyRecord;
KeyReset = 1;
KeyRecord = 0;
KeySwitch = 0;
TimeSetMode= 0;
KeyTimeSet = 0;
BEEP_LED = 1;
for(i=0;i
{
Time_Buffer[i] = 0;
}
Display_String(msg1[times],0);
while (Key_Reset == 0);
}
/*记录及回读键*/
else if(Key_RecordRead == 0)
{
if(KeySwitch == 1)
{ for(i=0;i
{
Time_Read[KeyRecord][i] = Time_Buffer[i]; }
KeyRecord++;
if(KeyRecord == 10)
{
KeyRecord = 0;
}
}
else if(KeySwitch == 0)
{
DelayMS(10);
if(KeyReset == 1)
{
for(i=0;i
{
Time_Buffer[i] = Time_Read[KeyRecord][i]; }
KeyRecord++;
if(KeyRecord > times)
{
KeyRecord = 0;
}
if(KeyRecord == 10)
{
KeyRecord = 0;
}
}
}
Display_String(msg1[KeyRecord],0);
while (Key_RecordRead == 0);
}
/*光标移动键*/
else if(Key_TimeMove == 0)
{
DelayMS(10);
TimeSetMode = 1; //
KeyTimeSet++;
if(KeyTimeSet > 6)
{
KeyTimeSet = 1;
}
Display_String(msg2,0);
while (Key_TimeMove == 0);
}
/*时间值设定键*/
else if(Key_TimeUp == 0)
{
DelayMS(10);
if(TimeSetMode == 1)
{
TimeChange();
}
while (Key_TimeUp == 0);
}
TimeSet();
LCD1602_Display();
}
}
/*lcd1602显示当前时间函数*/
void LCD1602_Display()
{
uchar i;
LCD_Set_POS(0x40);
for(i=3;i != 0xff;i--)
{
LCD_Display_Buffer[2*i+1] = Time_Buffer[i] / 10 + '0';
LCD_Display_Buffer[2*i ] = Time_Buffer[i] % 10 + '0';
LCD_Write_Data( LCD_Display_Buffer[2*i+1] );
LCD_Write_Data( LCD_Display_Buffer[2*i ] );
if(i>0)
{
LCD_Write_Data(':');
}
}
}
/*LCD1602初始化*/
void LCD_Initialize()
{
DelayMS(5);
LCD_Write_Command(0x38); DelayMS(5);
LCD_Write_Command(0x0c); DelayMS(5);
LCD_Write_Command(0x06); DelayMS(5);
LCD_Write_Command(0x01); DelayMS(5);
}
/*LCD1602显示位置*/
void LCD_Set_POS(uchar Position) {
LCD_Write_Command(Position | 0x80); }
/*LCD1602显示字符串*/
void Display_String(uchar*str,uchar LineNo) {
uchar k;
LCD_Set_POS(LineNo);
for (k=0;k
{
LCD_Write_Data (str[k]);
}
}
/*LCD1602忙状态检测*/
bit LCD_Busy_Check()
{
bit Result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
DelayNOP();
Result = (bit)(P0&0x80);
LCD_EN = 0;
return Result;
}
/*LCD1602写命令*/
void LCD_Write_Command(uchar cmd) {
while (LCD_Busy_Check());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
DelayNOP();
LCD_EN = 1;
DelayNOP();
LCD_EN = 0;
}
/*LCD1602写数据*/
void LCD_Write_Data(uchar str)
{ while (LCD_Busy_Check()) ;
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = str;
DelayNOP();
LCD_EN = 1;
DelayNOP();
LCD_EN = 0;
}
硬件图:
/****************************************************************** * 操作描述:
* 1.按Switch键可以启动或停止秒表走表,首次按会清零记录次数
* 2.秒表走表期间,按RecorRead按键可以记录当前时间(不影响秒表走表)
* 3.按Reset键,表值清零,按RecordRead键可以回读此前记录的对应次数与时间 * 4.按TimeMove进入秒表时间设置模式,连按可以移动光标到对应位(限秒以上), * 只在该模式下按TimeUp键才可以累加数值,该模式下按Switch可以开始计时, * 按Reset可以退出,计时到设定值后声光提示
* 时间:2016-04-19
********************************************************************/ /****************************************************************** * 硬件描述:
* 主芯片:stc89c51
* 显示器件:lcd1602
* 时间:2016-04-19
********************************************************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define DelayNOP() {_nop_();_nop_();_nop_();_nop_();}
#define timer0_DISABLE() TR0 = 0 //关闭定时器0
#define timer0_ENABLE() TR0 = 1 //开启定时器0
bit LCD_Busy_Check();
void LCD_Initialize();
void LCD_Set_POS(uchar);
void LCD_Write_Command(uchar);
void LCD_Write_Data(uchar);
void Display_String(uchar*str,uchar LineNo);
void LCD1602_Display();
sbit Key_Switch = P1^0;//秒表启动与停止按键
sbit Key_Reset = P1^1;//秒表复位清零按键
sbit Key_RecordRead = P1^2;//记录时间与回读
sbit Key_TimeMove = P1^3;//时间设置光标移动
sbit Key_TimeUp = P1^4;//时间设置增加
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit BEEP_LED = P2^7;
bit KeySwitch = 0;
bit TimeSetMode = 0;
bit TimeMode = 0;
uchar KeyRecord = 0;
//uchar KeyTimeNum =0;
uint KeyTimeSet = 0;
uint onems = 0;
const uchar code msg1[10][16] ={
"Record Mum 0",
"Record Mum 1",
"Record Mum 2",
"Record Mum 3",
"Record Mum 4",
"Record Mum 5",
"Record Mum 6",
"Record Mum 7",
"Record Mum 8",
"Record Mum 9",
};
const uchar code msg2[16] = {"TimerMode" };
uchar Time_Buffer[] = {0,0,0,0};
uchar TimeSet_Buffer[] = {0,0,0,0,};
uchar LCD_Display_Buffer[] = {"00:00:00:00"}; //该数组有7个元素4个00+3个‘:’ /* | | | |
| | | |1hour__
| | |1min__
| |1s__
|10ms__
数组排列与显示顺序相反
*/
uchar Time_Read[10][4]={
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
};
/*毫秒延时函数*/
void DelayMS(uint ms)
{
uchar t;
while(ms--)
{
for (t=0;t
}
}
/*定时器中断服务程序1ms进入一次*/
void Time0() interrupt 1 using 0
{
TH0 = (65536- 1000) / 256;
TL0 = (65536- 1000) % 256;
onems++;
/*10ms累加一次*/
if(onems == 10)
{
Time_Buffer[0]++;
onems = 0;
}
/*100*10ms = 1s*/
if(Time_Buffer[0]==100)
{
Time_Buffer[0]=0;
Time_Buffer[1]++;
}
/*1s * 60 = 1min*/
if(Time_Buffer[1]==60)
{
Time_Buffer[1]=0;
Time_Buffer[2]++;
}
/*1min * 60 = 1hour*/
if(Time_Buffer[2]==60)
{
Time_Buffer[2]=0;
Time_Buffer[3]++;
}
/*hour = 100时,时钟归零*/
if(Time_Buffer[3]==100)
{
Time_Buffer[3]=0;
}
/*当定时限制模式开启*/
if(TimeMode == 1)
{
if(Time_Buffer[1]==TimeSet_Buffer[1])
{
if(Time_Buffer[2]==TimeSet_Buffer[2])
{
if(Time_Buffer[3]==TimeSet_Buffer[3])
{
/*所有值相同,到达设定时间,定时器停止工作,声光提示*/ TimeMode = 0;
BEEP_LED = 0;
timer0_DISABLE();
}
}
}
}
}
/*设置光标的移动位置*/
void TimeSet()
switch(KeyTimeSet)
{
/*秒个位*/
case 1:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2+5);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
/*秒十位*/
case 2:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2+4);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
/*分个位*/
case 3:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2+2);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
/*分十位*/
case 4:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2+1);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
/*时个位*/
case 5:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2-1);
DelayMS(5);
DelayMS(1); break;
/*时十位*/
case 6:
LCD_Write_Command(0x0e);
LCD_Write_Command(0xc2-2);
DelayMS(5);
LCD_Write_Command(0x0c);
DelayMS(1);
break;
default:break;
}
}
/*根据光标位置(TimeSet变量值),及TimeUP键的触发,改变对应的值*/ void TimeChange()
{
uchar i;
switch(KeyTimeSet)
{
/*second设置*/
case 1:
TimeSet_Buffer[1] = TimeSet_Buffer[1] + 1;//个位数+1 if(TimeSet_Buffer[1] % 10 == 0 )
TimeSet_Buffer[1] = TimeSet_Buffer[1] % 10;//个位数清零,保留十位数 break;
case 2:
TimeSet_Buffer[1] = TimeSet_Buffer[1] + 10;//十位数+1
if(TimeSet_Buffer[1] / 10 > 5)
TimeSet_Buffer[1] = TimeSet_Buffer[1] % 10;//十位数清零,保留个位数 break;
/*min设置*/
case 3:
TimeSet_Buffer[2] = TimeSet_Buffer[2] + 1;
if(TimeSet_Buffer[2] % 10 == 0 )
TimeSet_Buffer[2] = TimeSet_Buffer[2] % 10; break;
case 4:
TimeSet_Buffer[2] = TimeSet_Buffer[2] + 10;
if(TimeSet_Buffer[2] / 10 > 5)
TimeSet_Buffer[2] = TimeSet_Buffer[2] % 10; break;
/*hour设置*/
case 5:
TimeSet_Buffer[3] = TimeSet_Buffer[3] + 1;
if(TimeSet_Buffer[3] % 10 == 0 )
TimeSet_Buffer[3] = TimeSet_Buffer[3] % 10; break;
case 6:
TimeSet_Buffer[3] = TimeSet_Buffer[3] + 10;
if(TimeSet_Buffer[3] / 10 > 9)
TimeSet_Buffer[3] = TimeSet_Buffer[3] % 10; break;
default: break;
}
for(i=0;i
{
Time_Buffer[i] = TimeSet_Buffer[i];
}
}
void main()
{
uchar i,KeyReset;
uchar times;
IE =0x82;
TMOD = 0x01;
TH0 = (65536- 1000) / 256;
TL0 = (65536- 1000) % 256;
LCD_Initialize();
Display_String(msg1[0],0x00);
while(1)
{
/*开关键*/
if( Key_Switch == 0 )
{
DelayMS(10);
KeySwitch = ~KeySwitch;
KeyReset = 0;
if(TimeSetMode==1)
{
KeyTimeSet = 0;
TimeSetMode= 0;
TimeMode = 1;
for(i=0;i
{
Time_Buffer[i] = 0;
DelayMS(1);
}
}
if(KeySwitch == 0 )
{
timer0_DISABLE();
}
else
{
timer0_ENABLE();
}
while (Key_Switch == 0);
}
/*复位键*/
else if(Key_Reset == 0)
{
DelayMS(10);
timer0_DISABLE();
times = KeyRecord;
KeyReset = 1;
KeyRecord = 0;
KeySwitch = 0;
TimeSetMode= 0;
KeyTimeSet = 0;
BEEP_LED = 1;
for(i=0;i
{
Time_Buffer[i] = 0;
}
Display_String(msg1[times],0);
while (Key_Reset == 0);
}
/*记录及回读键*/
else if(Key_RecordRead == 0)
{
if(KeySwitch == 1)
{ for(i=0;i
{
Time_Read[KeyRecord][i] = Time_Buffer[i]; }
KeyRecord++;
if(KeyRecord == 10)
{
KeyRecord = 0;
}
}
else if(KeySwitch == 0)
{
DelayMS(10);
if(KeyReset == 1)
{
for(i=0;i
{
Time_Buffer[i] = Time_Read[KeyRecord][i]; }
KeyRecord++;
if(KeyRecord > times)
{
KeyRecord = 0;
}
if(KeyRecord == 10)
{
KeyRecord = 0;
}
}
}
Display_String(msg1[KeyRecord],0);
while (Key_RecordRead == 0);
}
/*光标移动键*/
else if(Key_TimeMove == 0)
{
DelayMS(10);
TimeSetMode = 1; //
KeyTimeSet++;
if(KeyTimeSet > 6)
{
KeyTimeSet = 1;
}
Display_String(msg2,0);
while (Key_TimeMove == 0);
}
/*时间值设定键*/
else if(Key_TimeUp == 0)
{
DelayMS(10);
if(TimeSetMode == 1)
{
TimeChange();
}
while (Key_TimeUp == 0);
}
TimeSet();
LCD1602_Display();
}
}
/*lcd1602显示当前时间函数*/
void LCD1602_Display()
{
uchar i;
LCD_Set_POS(0x40);
for(i=3;i != 0xff;i--)
{
LCD_Display_Buffer[2*i+1] = Time_Buffer[i] / 10 + '0';
LCD_Display_Buffer[2*i ] = Time_Buffer[i] % 10 + '0';
LCD_Write_Data( LCD_Display_Buffer[2*i+1] );
LCD_Write_Data( LCD_Display_Buffer[2*i ] );
if(i>0)
{
LCD_Write_Data(':');
}
}
}
/*LCD1602初始化*/
void LCD_Initialize()
{
DelayMS(5);
LCD_Write_Command(0x38); DelayMS(5);
LCD_Write_Command(0x0c); DelayMS(5);
LCD_Write_Command(0x06); DelayMS(5);
LCD_Write_Command(0x01); DelayMS(5);
}
/*LCD1602显示位置*/
void LCD_Set_POS(uchar Position) {
LCD_Write_Command(Position | 0x80); }
/*LCD1602显示字符串*/
void Display_String(uchar*str,uchar LineNo) {
uchar k;
LCD_Set_POS(LineNo);
for (k=0;k
{
LCD_Write_Data (str[k]);
}
}
/*LCD1602忙状态检测*/
bit LCD_Busy_Check()
{
bit Result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
DelayNOP();
Result = (bit)(P0&0x80);
LCD_EN = 0;
return Result;
}
/*LCD1602写命令*/
void LCD_Write_Command(uchar cmd) {
while (LCD_Busy_Check());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
DelayNOP();
LCD_EN = 1;
DelayNOP();
LCD_EN = 0;
}
/*LCD1602写数据*/
void LCD_Write_Data(uchar str)
{ while (LCD_Busy_Check()) ;
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = str;
DelayNOP();
LCD_EN = 1;
DelayNOP();
LCD_EN = 0;
}
硬件图: