美文网首页
stc89c52和LCD1602实现的秒表

stc89c52和LCD1602实现的秒表

作者: 水上清风 | 来源:发表于2015-12-15 21:33 被阅读719次

    功能描述

    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++;
        }
    }
    

    相关文章

      网友评论

          本文标题:stc89c52和LCD1602实现的秒表

          本文链接:https://www.haomeiwen.com/subject/bcwuhttx.html