功能描述
- 使用1602显示时间 分钟-秒-10毫秒 (256分钟以内,0.01秒精度,达到最大时间蜂鸣器警告)
- 记录20组数据
- 使用三个按键 K1开始/暂停 K2重置/计次 K3前一条记录 K4后一条记录(说明:运行时 K2添加一条记录)
效果如下图
1602操作程序
#include <reg51.h>
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P2^5;
sbit BUSY = P0^7;
#define DATA P0
//读忙信号
void wait(void)
{
P0 = 0xFF;
do
{
RS = 0;
RW = 1;
EN = 0;
EN = 1;
}
while (BUSY == 1);
EN = 0;
}
//写命令到1602
void writeCMD(unsigned char cmd)
{
wait();
DATA = cmd;
EN = 1;
RS = 0;
RW = 0;
EN = 0;
}
//写数据到1602
void writeData(unsigned char dat)
{
wait();
DATA = dat;
EN = 1;
RS = 1;
RW = 0;
EN = 0;
}
//1602初始化
void init1602()
{
writeCMD(0x38);
writeCMD(0x08);
writeCMD(0x01);
writeCMD(0x06);
writeCMD(0x0C);
writeCMD(0x80);
}
秒表实现主程序
#include <reg51.h>
#include "1602.h"
#include <stdio.h>
#define noBtn 0
#define startOrPuaseBtn 1
#define resetOrCounterBtn 2
#define previousBtn 3
#define nextBtn 4
#define RE_NUM 20
#define FM_OFF 1
#define FM_ON 0
typedef struct{
unsigned char minute;
unsigned char second;
unsigned char msec;
}time;
sbit K1 = P3^4;//开始、暂停按键
sbit K2 = P3^5;//重置、计次按键
sbit K3 = P3^6;//查看上一条记录按键
sbit K4 = P3^7;//查看下一条记录按键
sbit FM = P2^3;//蜂鸣器 0 开 1 关
unsigned char msec = 0;
//bit runState = 0;
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 18;
j = 235;
do
{
while (--j);
} while (--i);
}
//按键检测
unsigned char scanKey()
{
P3 = 0xF0;
if(P3!=0xF0)//有按键 延时10ms消抖
{
Delay10ms();
}
else
{
return noBtn;
}
if(K1==0) return startOrPuaseBtn;
if(K2==0) return resetOrCounterBtn;
if(K3==0) return previousBtn;
if(K4==0) return nextBtn;
return noBtn;
}
void Timer0Init(void) //50毫秒@11.0592MHz
{
//AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0xDC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 0; //定时器0开始计时 //开始时暂停的
ET0 = 1; //定时器0中断开启
EA = 1; //打开全局中断
}
//在1602的row行column列显示dat
//row 0 - 1
//column 0 - 15
void dis1602(unsigned char row, unsigned char column, char dat)//
{
writeCMD(0x80+row*0x40+column);
writeData(dat);
}
//在1602的row行column列显示字符串str
void disStr1602(unsigned char row, unsigned char column, char *str)//
{
writeCMD(0x80+row*0x40+column);
while(*str)
{
writeData(*str++);
}
}
void main()
{
unsigned char msecTemp = 0, keyValue = noBtn, keyTemp = noBtn;
unsigned char recordTotal = 0, currentRecord = 0;
unsigned char minute = 0, second = 0;
char str[16] = "";
time idata record[RE_NUM] = {0}; //记录存放
init1602();
Timer0Init();
disStr1602(0,0, "stop 000:00:00");//初始化显示
disStr1602(1,0, "00/00 000:00:00");
//dis1602(0,10,':');
//dis1602(0,13,':');
while(1)
{
keyTemp = scanKey(); //当前key值
if(keyValue!=keyTemp) //key状态发生变化则处理按键功能
{
keyValue = keyTemp;
switch(keyValue)
{
case startOrPuaseBtn: //启动或暂停
TR0 = !TR0;
if(TR0)
{
disStr1602(0, 0, "start");
}
else
{
disStr1602(0, 0, "stop ");
}
break;
case resetOrCounterBtn:
if(TR0)//运行状态 增加记录
{
if(recordTotal < RE_NUM)
{
record[recordTotal].minute = minute;
record[recordTotal].second = second;
record[recordTotal].msec = msec;
recordTotal++;
currentRecord = recordTotal;
}
sprintf(str,"%02d/%02d %03d:%02d:%02d",
(int)currentRecord,(int)recordTotal,
(int)record[recordTotal-1].minute,
(int)record[recordTotal-1].second,
(int)record[recordTotal-1].msec);
disStr1602(1, 0, str);//显示 记录
}
else //暂停状态 重置
{
FM = FM_OFF;
minute = 0;
second = 0;
msec = 0;
recordTotal = 0;
currentRecord = 0;
disStr1602(0,0, "stop 000:00:00");//重置显示
disStr1602(1,0, "00/00 000:00:00");//重置显示
}
break;
case previousBtn: //前一条记录
if(currentRecord > 1)
{
currentRecord--;
sprintf(str,"%02d/%02d %03d:%02d:%02d",
(int)currentRecord,(int)recordTotal,
(int)record[currentRecord-1].minute,
(int)record[currentRecord-1].second,
(int)record[currentRecord-1].msec);
disStr1602(1, 0, str);//显示 记录
}
break;
case nextBtn: //查看后一条记录
if(currentRecord < recordTotal)
{
currentRecord++;
sprintf(str,"%02d/%02d %03d:%02d:%02d",
(int)currentRecord,(int)recordTotal,
(int)record[currentRecord-1].minute,
(int)record[currentRecord-1].second,
(int)record[currentRecord-1].msec);
disStr1602(1, 0, str);//显示 记录
}
break;
}
}
if(msecTemp!=msec)//每变一次10ms刷新
{
msecTemp = msec;
if(msec>99)
{
if(++second>59)
{
minute++;
second = 0;
dis1602(0, 7,'0'+minute/100);
dis1602(0, 8,'0'+minute/10%10);
dis1602(0, 9,'0'+minute%10);
if(minute==0xFF)//达到了秒表最大值 不能再继续 打开蜂鸣器提醒 并暂停秒表 等待重置
{
TR0 = 0;
FM = FM_ON;
}
}
else
{
dis1602(0,11,'0'+second/10);
dis1602(0,12,'0'+second%10);
}
msec = 0;
}
dis1602(0,14,'0'+msec/10);
dis1602(0,15,'0'+msec%10);
}
}
}
void T0_50ms() interrupt 1
{
TL0 = 0x00; //设置定时初值
TH0 = 0xDC; //设置定时初值
//if(runState)
{
msec++;
}
}