stc89c52和LCD1602实现的秒表

功能描述

  1. 使用1602显示时间 分钟-秒-10毫秒 (256分钟以内,0.01秒精度,达到最大时间蜂鸣器警告)
  2. 记录20组数据
  3. 使用三个按键 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;
}
//写数据到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++;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容