標(biāo)題: 求助:寫了個數(shù)碼管鬧鐘程序,有幾個地方調(diào)不出來。 [打印本頁]

作者: 18380429586    時間: 2016-5-16 20:33
標(biāo)題: 求助:寫了個數(shù)碼管鬧鐘程序,有幾個地方調(diào)不出來。
8位LED數(shù)碼管可調(diào)鬧鐘。



8個LED數(shù)碼管88-88-88這樣。
采用 2個鎖存器輸出 段選,位選。
采用3個獨(dú)立按鍵:
1、SET(按一下調(diào)整秒鐘,在按一下調(diào)整分鐘,按三下調(diào)整小時,按4下完成調(diào)整。)

2、加減按鍵,按一下,就加減一個數(shù)字。先由SET選擇調(diào)試 小時 還是分鐘, 然后按加減鍵 調(diào)節(jié)數(shù)字。

問題:
1、SET鍵那里我采用的是記錄鍵值思路。

    按一下SET ,  keynumber=1,  TR0=0 暫停計時,
  按下加按鍵,  如果鍵值=1、2或者3,   秒、分鐘或者小時的計數(shù)變量加一。

但是問題就來了, 按下SET 鍵后 有的時候是  調(diào)節(jié)小時,有的時候是調(diào)節(jié)分鐘,有的時候沒變化。
下面是原理圖 和 程序。


人生日歷截圖20160516203142.png (38.58 KB, 下載次數(shù): 114)

電路原理圖

電路原理圖

作者: 18380429586    時間: 2016-5-16 20:49
#include<reg51.h>
#define uchar unsigned char
uchar code led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar code wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x040,0x80};
sbit duEN=P3^6;
sbit weiEN=P3^7;
sbit k0=P2^0;
sbit k1=P2^1;
sbit k2=P2^2;
char countsec,countmin,counthou;
uchar flag;
char key;
延時程序略過。

鍵盤掃描。
void keyboard()
{
                if(k0==0)
                                {
                                       鍵盤消抖。
                                        ys(50);
                                        if(k0==0)
                                        {
                                                松手檢測。
                                                while(!k0)
                                                {
                                                        key++;                                                       
                                                        TR0=0;
                                                        if(key==4)
                                                        {
                                                                key=0;
                                                                TR0=1;
                                                        }
                                                }
                                        }
                                }
               

                                if(k1==0)
                                {
                                        ys(50);
                                        if(k1==0)
                                        {
                                       
                                                 while(!k1);
                                                        if(key==1)
                                                        {
                                                        countsec++;
                                                        if(countsec==60)
                                                        countsec=0;
                                                        }
                                                        if(key==2)
                                                        {
                                                        countmin++;
                                                        if(countmin==60)
                                                        countmin=0;
                                                        }
                                                        if(key==3)
                                                        {
                                                        counthou++;
                                                        if(counthou==24)
                                                        counthou=0;
                                                        }
                                        }
                                }


                                if(k2==0)
                                {
                                        ys(50);
                                        if(k2==0)
                                        {
                                                while(!k2);
                                                        if(key==1)
                                                        {
                                                        countsec--;
                                                        if(countsec==-1)
                                                        countsec=59;
                                                        }
                                                        if(key==2)
                                                        {
                                                        countmin--;
                                                        if(countmin==-1)
                                                        countmin=59;
                                                        }
                                                        if(key==3)
                                                        {
                                                        counthou--;
                                                        if(counthou==-1)
                                                        counthou=23;
                                                }
                                        }
                                }

}
一共8位,有點(diǎn)長,就發(fā)一段吧,其他都是一樣的。
void ledxs()
{  
        P0=led[counthou/10];
        duEN=1;       
        duEN=0;
        P0=wei[0];       
        weiEN=1;       
        weiEN=0;
        ys(5);
以下為消隱,求教 為什么這樣可以消隱。按我理解 先給P0賦值,然后開鎖存器使能,瞬間值就付給鎖存,然后關(guān)使能。應(yīng)該不會出現(xiàn)鬼影的。事           實是不加下面幾句,仿真中時鐘亂顯示。
        P0=0xff;           
        duEN=1;                              
        duEN=0;

}

主程序: T0初始化,最后不斷掃描鍵盤和顯示,等待中斷發(fā)生,從而刷新顯示。

void main()
{
        TMOD=0X01;
        TH0=(65536-45872)/256;
        TL0=(65536-45872)%256;
        EA=1;
        ET0=1;
        TR0=1;
        while(1)
        {
               
        keyboard();                       
        ledxs();

        }                                          
}


中斷子程序:秒計數(shù)。

void timer0() interrupt 1 using 0
{
        flag++;       
        if(flag==20)
                {
                        flag=0;
                        countsec++;}
        if(countsec==60)
        {
                countsec=0;
                countmin++;        }
        if(countmin==60)
        {
                countmin=0;
                counthou++;        }
        if(counthou==24)
        {
                counthou=0;
        }
        TH0=(65536-45872)/256;
        TL0=(65536-45872)%256;
}



作者: 18380429586    時間: 2016-5-16 20:55
oh, fvck。 整理排版的時候發(fā)現(xiàn),我SET鍵(K0) 的松手檢測寫錯了。 寫成下面這個:
                                                while(!k0)
                                                {
                                                        key++;                                                        
                                                        TR0=0;
                                                        if(key==4)
                                                        {
                                                                key=0;
                                                                TR0=1;
                                                        }
                                                } MD 怪不得  按了這個鍵是調(diào)整小時還是分鐘,是無規(guī)律的,等待松手的時候不知道KEY加了多少次。
修改之后 。仿真沒有問題了。
                                               while(!k0);
                                                        key++;                                                        
                                                        TR0=0;
                                                        if(key==4)
                                                        {
                                                                key=0;
                                                                TR0=1;
                                                        }
                                                

作者: 18380429586    時間: 2016-5-16 21:14
還有幾個問題。

我采用的是共陽極數(shù)碼管, 使用鎖存器作為驅(qū)動。1、位選 是不是  為1的時候  允許該位顯示?
如果采用9012 PNP三極管作為驅(qū)動,是不是  某個位控制I0口輸出為0的時候允許該位點(diǎn)亮。
看網(wǎng)上程序的時候 沒注意每個人的驅(qū)動方法不一樣,只發(fā)現(xiàn)同樣共陽怎么位選不一樣, 把我搞暈了,所以請教一下大家,給我個準(zhǔn)確答復(fù)。
2、數(shù)碼管 消隱,共陽極數(shù)碼管段選  是低電平有效。消隱就是關(guān)閉所有發(fā)光管,就是P0=0xff?
關(guān)于消隱程序 我最開始用的 郭天祥的, 如下:
         duEN=1;               
        P0=led[counthou/10];       
        duEN=0;
        P0=0Xff;       
        weiEN=1;       
        P0=wei[0];
        weiEN=0;
        ys(5);
居然 沒法顯示, 然后 從網(wǎng)上學(xué)了 這種:
        P0=led[counthou/10];
        duEN=1;       
        duEN=0;
        P0=wei[0];       
        weiEN=1;       
        weiEN=0;
        ys(5);
        P0=0xff;
        duEN=1;
        duEN=0;

消隱這個 我知道就是關(guān)掉P0,以免動態(tài)顯示要輸出下一位時,把上一位的段選給輸過去.  我感覺我理解的很糙,還請大家?guī)臀沂崂硪幌隆?br /> 然后還有一個單片機(jī) 跑程序的流程就是   逐行掃描運(yùn)行,好像還默認(rèn)的從頭到尾不斷循環(huán)。這個理解是不是對的?這個也請大家?guī)臀沂崂硪幌隆?br />
還有一個問題。
我想做成    按下SET鍵后,調(diào)整秒鐘/分鐘/時鐘的時候, 秒/分/時的那2位會閃爍,這個怎么做?我完全沒有思路。



作者: ahshmj    時間: 2016-5-16 22:33
本帖最后由 ahshmj 于 2016-5-16 22:35 編輯

不是“鍵值”,是按鍵次數(shù)。設(shè)一個計數(shù)器,每按一次加1 。根據(jù)這個計數(shù)值,確定調(diào)整的項目。當(dāng)然循環(huán)完后轉(zhuǎn)回0或1,

當(dāng)需要調(diào)的項目需要閃爍時,可以用另一個定時器中斷方法,一般取0.3~0.5秒中斷一次,每次中斷變換一次,在輸出正常的段碼和全滅之間變換即可。

我做的是設(shè)一個標(biāo)志,中斷一次標(biāo)志轉(zhuǎn)換一次,調(diào)顯示程序時,根據(jù)標(biāo)志輸出亮、滅。
作者: zl2168    時間: 2016-5-17 07:45
本帖最后由 zl2168 于 2016-5-17 08:58 編輯

模擬電子鐘(由80C51定時器產(chǎn)生秒時基)已在本壇“51單片機(jī)”專欄2016.5.11上傳,可參閱。






K0、K1K2具有時鐘校正功能,其控制過程為:


按下K0(帶鎖),進(jìn)入時鐘修正;首先,時數(shù)據(jù)(包括時十位、時個位)快速閃爍(亮暗各131ms);


按一次K1(不帶鎖),被修正數(shù)據(jù)(快速閃爍)按時、分、秒(同時包括十位、個位)次序右移(循環(huán)往復(fù));


按一次K2(不帶鎖),被修正數(shù)據(jù)整體加1(最大值不超過時鐘規(guī)定值,超過復(fù)0);時鐘修正期間,計時繼續(xù)運(yùn)行;


釋放K0,退出時鐘修正。




作者: 18380429586    時間: 2016-5-17 19:55
zl2168 發(fā)表于 2016-5-17 07:45
模擬電子鐘(由80C51定時器產(chǎn)生秒時基)已在本壇“51單片機(jī)”專欄2016.5.11上傳,可參閱。

謝謝,我去看看。
作者: 18380429586    時間: 2016-5-17 20:51
zl2168 發(fā)表于 2016-5-17 07:45
模擬電子鐘(由80C51定時器產(chǎn)生秒時基)已在本壇“51單片機(jī)”專欄2016.5.11上傳,可參閱。

好的,我去看看,謝謝了。
作者: 18380429586    時間: 2016-5-17 21:01
ahshmj 發(fā)表于 2016-5-16 22:33
不是“鍵值”,是按鍵次數(shù)。設(shè)一個計數(shù)器,每按一次加1 。根據(jù)這個計數(shù)值,確定調(diào)整的項目。當(dāng)然循環(huán)完后轉(zhuǎn) ...

我試了一下,不知道是不是我沒弄好。 結(jié)果是8位全部都在閃爍,就是動態(tài)掃描  顯示延時 設(shè)太長的那種現(xiàn)象。我沒用 2個定時器,因為我還不知道怎么設(shè)中斷優(yōu)先。待會學(xué)習(xí)下。然后在試一下。
作者: zl2168    時間: 2016-5-19 18:38
本帖最后由 zl2168 于 2016-5-19 18:42 編輯

模擬電子鐘(由80C51定時器產(chǎn)生秒時基)已在本壇“51單片機(jī)”專欄2016.5.11上傳,可參閱。









開機(jī)顯示000秒,隨后開始計時運(yùn)行,2組發(fā)光二極管秒閃爍(亮暗各500ms。同時要求K0、K1K2具有時鐘校正功能,其控制過程為:按下K0(帶鎖),進(jìn)入時鐘修正;首先,時數(shù)據(jù)(包括時十位、時個位)快速閃爍(亮暗各131ms);按一次K1(不帶鎖),被修正數(shù)據(jù)(快速閃爍)按時、分、秒(同時包括十位、個位)次序右移(循環(huán)往復(fù));按一次K2(不帶鎖),被修正數(shù)據(jù)整體加1(最大值不超過時鐘規(guī)定值,超過復(fù)0);時鐘修正期間,計時繼續(xù)運(yùn)行;釋放K0,退出時鐘修正。


實例94 模擬電子鐘(由80C51定時器產(chǎn)生秒時基).rar (43.05 KB, 下載次數(shù): 10)



作者: zl2168    時間: 2016-5-19 21:13
試試上述模擬電子鐘Proteus仿真演示,包你滿意。
作者: 18380429586    時間: 2016-5-21 10:24
zl2168 發(fā)表于 2016-5-19 21:13
試試上述模擬電子鐘Proteus仿真演示,包你滿意。

恩! 我看了下,確實給力。謝謝了,讓我知道有 74595這種 驅(qū)動。
作者: zl2168    時間: 2016-5-21 10:25
本帖最后由 zl2168 于 2016-5-21 10:26 編輯

模擬電子鐘程序如下:














t0t1.jpg (108.49 KB, 下載次數(shù): 89)

t0t1.jpg

作者: zl2168    時間: 2016-5-21 10:29
上述電路和程序引自張志良編著《單片機(jī)實驗實訓(xùn)100例》 ISBN 978-7-5124-1603-1,北航社出版、《80C51單片機(jī)實用教程》ISBN 978-7-04-044532-9,高教社出版。歡迎咨詢,zzlls@126.com
作者: 18380429586    時間: 2016-5-21 10:31
zl2168 發(fā)表于 2016-5-19 21:13
試試上述模擬電子鐘Proteus仿真演示,包你滿意。

前輩,請教一下,uchar 是無符號的吧。 可是在時鐘里  按鍵調(diào)時間的時候,用到一句 :  如果減計數(shù)按鍵被按下,秒計數(shù)減一,如果秒計數(shù)=-1,秒計數(shù)=59。
我的秒計數(shù)變量是 uchar型的, uchar不是無符號嗎?為什么程序 可以編譯成功,仿真也可以用呢?

                                                       if(k1==0)
                                                       {
                                                            countsec--;
                                                            if(countsec==-1)
                                                            countsec=59;
                                                        }
作者: zl2168    時間: 2016-5-21 10:39
為什么要秒計數(shù)減一?時鐘都是加一的。你看我的程序,加到60,復(fù)0.
作者: zl2168    時間: 2016-5-21 10:42
啊哦!你可能是到計時秒表。介紹你一本書,張志良編著《單片機(jī)實驗實訓(xùn)100例》 ISBN 978-7-5124-1603-1,北航社出版,里面有99.9秒表和能預(yù)設(shè)初值的倒計時秒表實例。
作者: zl2168    時間: 2016-5-21 10:55
啊哦!我知道你問的問題了。-1是補(bǔ)碼,255,仍屬于uchar。
作者: zl2168    時間: 2016-5-21 10:57
0-1=255
作者: 慌張    時間: 2016-5-21 14:41
還是用lcd1602寫比較實用點(diǎn)
作者: zl2168    時間: 2016-5-21 15:27
這是一個題目。有LED顯示,也有LCD顯示。本題是LED顯示。
作者: zl2168    時間: 2016-5-21 15:30
還有秒基準(zhǔn)取自于外時鐘芯片,還是取自于內(nèi)振蕩時鐘。本題是內(nèi)振蕩時鐘,分頻后產(chǎn)生秒基準(zhǔn)。
作者: zl2168    時間: 2016-5-21 15:32
介紹你一本書,張志良編著《單片機(jī)實驗實訓(xùn)100例》 ISBN 978-7-5124-1603-1,北航社出版,里面有4種1302的電路、程序和仿真案例
作者: zl2168    時間: 2016-5-21 15:37
上述4種1302的電路、程序和仿真案例已上傳至本壇“51單片機(jī)”專欄
作者: zl2168    時間: 2016-5-21 15:38
2016-5-3 本人上傳的“開機(jī)顯示PC機(jī)時間的時鐘1302”(1602顯示)
作者: zl2168    時間: 2016-5-21 15:38
2016-5-4 本人上傳的“具有校正功能的時鐘1302”(1602顯示)
作者: zl2168    時間: 2016-5-21 15:38
2016-5-5 本人上傳的“開機(jī)顯示PC機(jī)時分秒的時鐘1302”(LED數(shù)碼管顯示)
作者: zl2168    時間: 2016-5-21 15:39
2016-5-6 本人上傳的“具有校正功能的時鐘1302(LED數(shù)碼管顯示)”
作者: zl2168    時間: 2016-5-21 19:49
Proteus仿真試了沒有?試后滿意再謝。
作者: 18380429586    時間: 2016-5-23 11:19
zl2168 發(fā)表于 2016-5-21 19:49
Proteus仿真試了沒有?試后滿意再謝。

試過了!效果很好,謝謝了。




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1