功能描述
- 使用1602顯示時間 分鐘-秒-10毫秒 (256分鐘以內(nèi),0.01秒精度楞抡,達到最大時間蜂鳴器警告)
- 記錄20組數(shù)據(jù)
- 使用三個按鍵 K1開始/暫停 K2重置/計次 K3前一條記錄 K4后一條記錄(說明:運行時 K2添加一條記錄)
效果如下圖
Paste_Image.png
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;
}
//寫數(shù)據(jù)到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);
}
秒表實現(xiàn)主程序
#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狀態(tài)發(fā)生變化則處理按鍵功能
{
keyValue = keyTemp;
switch(keyValue)
{
case startOrPuaseBtn: //啟動或暫停
TR0 = !TR0;
if(TR0)
{
disStr1602(0, 0, "start");
}
else
{
disStr1602(0, 0, "stop ");
}
break;
case resetOrCounterBtn:
if(TR0)//運行狀態(tài) 增加記錄
{
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 //暫停狀態(tài) 重置
{
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)//達到了秒表最大值 不能再繼續(xù) 打開蜂鳴器提醒 并暫停秒表 等待重置
{
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++;
}
}