51單片機(jī)實(shí)現(xiàn)的秒表

功能描述

  1. 使用6段數(shù)碼管顯示時(shí)間 分鐘-秒-100毫秒 (十分鐘以內(nèi)毡惜,0.1秒一位)
  2. 記錄8組數(shù)據(jù) 使用LED燈代表那組數(shù)據(jù)
  3. 使用三個(gè)按鍵 K1開始/暫停 K2重置 K3計(jì)次/記錄(說明:運(yùn)行狀態(tài)下,不能重置柑晒,k3增加一條記錄點(diǎn)亮一個(gè)LED,暫停狀態(tài)下,可重置,k3從第一條記錄查看并點(diǎn)亮相應(yīng)LED燈)

實(shí)現(xiàn)分析

  1. 定時(shí)器 產(chǎn)生固定周期中斷(16 13 8位定時(shí)器)
  2. 數(shù)碼管動態(tài)刷新(軟延時(shí)、定時(shí)器)
  3. 按鍵消抖(軟延時(shí)礼仗、定時(shí)器)
  4. 記錄 使用數(shù)組或字符串?使用LED表示那組數(shù)據(jù)
  5. 按鍵功能定義和狀態(tài)(開始狀態(tài)計(jì)次苞七、重置失效藐守,暫停狀態(tài)重置、記錄激活)

最終實(shí)現(xiàn)

  1. 16位定時(shí)器蹂风,定時(shí)2ms(由于單片機(jī)晶振為11.0592MHz所以有0.01%誤差 中斷相應(yīng)也會導(dǎo)致誤差)
  2. 6位數(shù)碼管 分-秒-0.1s卢厂,最大10分鐘
  3. 按鍵消抖使用定時(shí)器 10ms
  4. 8組記錄 對應(yīng)8個(gè)LED燈

相關(guān)說明

P1對應(yīng)8個(gè)LED燈
六位共陰數(shù)碼管 由P0連接兩個(gè)鎖存器 控制位選和段選
效果如下圖


946af505-2a92-49c7-a2ee-97d403e05523.jpg
#include <reg51.h>
unsigned char code leddata[]= {  0x3F,  0x06,  0x5B,  0x4F, //0 1 2 3
                                 0x66,  0x6D,  0x7D,  0x07,  //4 5 6 7
                                 0x7F,  0x6F,  0x77,  0x7C,  //8 9 A b
                                 0x39,  0x5E,  0x79,  0x71,  //c d E F
                                 0x76,  0x38,  0x37,  0x3E,  //H L n u
                                 0x73,  0x5C,  0x40,  0x00,  //P o - 清屏
                              }; 
#define digitData P0          //數(shù)碼管數(shù)據(jù)
#define startBtn    0       //按鍵值
#define resetBtn    1
#define counterBtn  2
sbit DX = P2^6;//段選
sbit WX = P2^7;//位選
sbit kaiShi = P3^4;//開始、暫停按鍵
sbit chongZhi = P3^5;//重置按鍵
sbit jiCi = P3^6;//計(jì)次惠啄、記錄查看按鍵
unsigned int recode[8] = {0};//記錄數(shù)據(jù)
unsigned char recodeNum = 0;//記錄數(shù)據(jù)值位置
unsigned char showRe = 0; //查看哪項(xiàng)記錄值
unsigned int times = 0; //當(dāng)前計(jì)時(shí)時(shí)間
unsigned int saveTimes = 0;//暫停查看記錄時(shí)保存時(shí)間數(shù)據(jù)
unsigned char counter = 0;//定時(shí)器次數(shù)慎恒,構(gòu)成100ms
unsigned char shuanXi = 0,sXW = 1;//刷新數(shù)碼管
unsigned char runState = 0;//0表示停止任内,1表示運(yùn)行
unsigned char keyTemp[3]= {0}; //按鍵按下狀態(tài)持續(xù)時(shí)間

//六位數(shù)碼管顯示 dat:顯示內(nèi)容下標(biāo) wei:哪一個(gè)數(shù)碼管
void display(unsigned char dat,unsigned char wei)//wei 1-6
{
    digitData = 0xff; //關(guān)掉顯示 消除重影
    WX = 1;
    WX = 0;
    //如果不先關(guān)閉顯示,不論先段選還位選(位選前關(guān)閉都不行)融柬,而且必須先送段選死嗦,再送位選,
    //先位選則當(dāng)前位置會顯示上次殘留段選數(shù)據(jù) 導(dǎo)致重影
    digitData = leddata[dat];//段選
    DX = 1;
    DX = 0; 
    digitData = ~(1<<(wei-1));//位選
    WX = 1;
    WX = 0;
}
//判斷當(dāng)前按鍵
unsigned char scanKey()
{
    P3 = 0x70;//k1 k2 k3給高

    if(kaiShi==0)//開始鍵按下
    {
        if(keyTemp[0] == 0) keyTemp[0]=1 ;//按鍵按下 開始記延時(shí)
    }
    else
    {
        keyTemp[0] = 0; //有抖動重新延時(shí)
    }

    if(chongZhi==0)
    {
        if(keyTemp[1] == 0) keyTemp[1]=1 ;
    }
    else
    {
        keyTemp[1] = 0;
    }

    if(jiCi==0)
    {
        if(keyTemp[2] == 0) keyTemp[2]=1 ;
    }
    else
    {
        keyTemp[2] = 0;
    }
    if(keyTemp[0]>5) return startBtn;  //5次 5*2ms 超過10ms 消抖
    if(keyTemp[1]>5) return resetBtn;
    if(keyTemp[2]>5) return counterBtn;
    return 0xFF; //沒有按鍵
}
void Timer0Init(void)       //2毫秒@11.0592MHz
{
    //AUXR &= 0x7F;     //定時(shí)器時(shí)鐘12T模式
    TMOD &= 0xF0;       //設(shè)置定時(shí)器模式
    TMOD |= 0x01;       //設(shè)置定時(shí)器模式
    TL0 = 0xCF;     //設(shè)置定時(shí)初值
    TH0 = 0xF8;     //設(shè)置定時(shí)初值
    TF0 = 0;        //清除TF0標(biāo)志
    TR0 = 1;        //定時(shí)器0開始計(jì)時(shí)
    ET0 = 1;         //運(yùn)行定時(shí)器0中斷
    EA = 1;         //開全局中斷
}

void main()
{
    unsigned char keyValue = 0xFF,keyT = 0xFF;//按鍵值
    unsigned char weiXian[6] = {0,22,0,0,22,0};
    Timer0Init();
    while(1)
    {
        if(shuanXi)//刷新sXW位置的數(shù)碼管中
        {
            if(times>=6000) //十分鐘
            {
                times = 0;
            }
            weiXian[0] = times/600;//分鐘
            weiXian[2] = times/10%60/10;
            weiXian[3] = times/10%60%10;
            weiXian[5] = times%10;
            display(weiXian[sXW-1],sXW);
            shuanXi = 0;
        }
        keyT = scanKey();//當(dāng)前按鍵值
        if(keyT!=keyValue)//當(dāng)前按鍵值與上次按鍵值不同粒氧,則表示按鍵狀態(tài)改變越除。需要做按鍵處理
        {
            keyValue = keyT;
            //P1 = keyValue;
            switch(keyValue)//按鍵處理
            {
            case startBtn://開始暫停按下
                //if(runState) TR0 = 0; else TR0 = 1;
                //runState ? (TR0 = 0) : (TR0 = 1);
                runState = !runState;//改變狀態(tài)
                if(runState)//恢復(fù)時(shí)間
                {
                    times = saveTimes;
                }
                else//保存時(shí)間
                {
                    saveTimes = times;
                }

                break;
            case resetBtn:  //重置
                if(!runState)
                {
                    times = 0;
                    saveTimes = 0;
                    recodeNum = 0;
                    P1 = 0xFF;
                }
                break;
            case counterBtn:  //記錄或查看記錄
                if(runState)//運(yùn)行時(shí),記錄
                {
                    if(recodeNum<8)
                    {
                        recode[recodeNum++] = times;
                        P1 = (0xFF<<recodeNum);//點(diǎn)亮recodeNum個(gè)燈
                    }
                }
                else//暫停查看記錄
                {
                    P1 = (0xFF ^(1 << showRe));//點(diǎn)亮showRe位置的燈
                    times = recode[showRe++];
                    if(showRe >= recodeNum)
                    {
                        showRe = 0;//循環(huán)查看記錄
                    }
                }
                break;
            }
        }
    }

}
void T0_2ms() interrupt 1
{
    //定時(shí)器重新賦初值 放在終端服務(wù)程序最開始有利于降低定時(shí)中斷誤差
    TL0 = 0xCF;     //設(shè)置定時(shí)初值
    TH0 = 0xF8;     //設(shè)置定時(shí)初值
    if(++counter>=50 && runState)//運(yùn)行狀態(tài)下100ms 加0.1秒
    {
        times++;
        counter = 0;
    }
    shuanXi = 1;//數(shù)碼管周期刷新
    if(++sXW>6) //六位循環(huán)刷新
    {
        sXW = 1;
    }
    if(keyTemp[0]) keyTemp[0]++;//按鍵持續(xù)
    if(keyTemp[1]) keyTemp[1]++;//按鍵持續(xù)
    if(keyTemp[2]) keyTemp[2]++;//按鍵持續(xù)

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末外盯,一起剝皮案震驚了整個(gè)濱河市摘盆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饱苟,老刑警劉巖孩擂,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異箱熬,居然都是意外死亡类垦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進(jìn)店門城须,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚤认,“玉大人,你說我怎么就攤上這事糕伐±优常” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵赤炒,是天一觀的道長。 經(jīng)常有香客問我亏较,道長莺褒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任雪情,我火速辦了婚禮遵岩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘巡通。我一直安慰自己尘执,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布宴凉。 她就那樣靜靜地躺著誊锭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弥锄。 梳的紋絲不亂的頭發(fā)上丧靡,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天蟆沫,我揣著相機(jī)與錄音,去河邊找鬼温治。 笑死饭庞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的熬荆。 我是一名探鬼主播舟山,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼卤恳!你這毒婦竟也來了累盗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤纬黎,失蹤者是張志新(化名)和其女友劉穎幅骄,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體本今,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拆座,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了冠息。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挪凑。...
    茶點(diǎn)故事閱讀 39,745評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖逛艰,靈堂內(nèi)的尸體忽然破棺而出躏碳,到底是詐尸還是另有隱情,我是刑警寧澤散怖,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布菇绵,位于F島的核電站,受9級特大地震影響镇眷,放射性物質(zhì)發(fā)生泄漏咬最。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一欠动、第九天 我趴在偏房一處隱蔽的房頂上張望永乌。 院中可真熱鬧,春花似錦具伍、人聲如沸翅雏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽望几。三九已至,卻和暖如春啼肩,著一層夾襖步出監(jiān)牢的瞬間橄妆,已是汗流浹背衙伶。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留害碾,地道東北人矢劲。 一個(gè)月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像慌随,于是被迫代替她去往敵國和親芬沉。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容