找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 2684|回復(fù): 12
收起左側(cè)

51單片機(jī)秒表程序問(wèn)題,無(wú)論k2在何時(shí)按都會(huì)清零

[復(fù)制鏈接]
ID:562692 發(fā)表于 2019-6-18 11:37 | 顯示全部樓層 |閱讀模式
做了一個(gè)秒表,硬件是pz的開(kāi)發(fā)板。效果是開(kāi)機(jī)后,按下k1后開(kāi)始計(jì)時(shí),在四位共陰管上顯示xx.yy。其中xx是分,yy是秒。
k1是啟動(dòng)/暫停鍵,k2是歸零鍵,目的是短按k1實(shí)現(xiàn)定時(shí)器啟動(dòng)與關(guān)閉,在暫停模式下再按k2才可歸零。
按鍵掃描程序如下圖,問(wèn)題是無(wú)論k2在何時(shí)按都會(huì)清零
void keyscan()
{        u8 keymod=0;
        if(k1==0)
        {
                delay(1000);
                if(k1==0)
                {
                        TR0=!TR0;
                        keymod=!keymod;               
                }
                while(!k1);
        }
        if(keymod==0)
        {
                if(k2==0)
                {
                        delay(1000);
                        if(k2==0)
                        {
                                sec=0,min=0,hour=0;               
                        }
                        while(!k2);
                }
        }
}
對(duì)此不是很理解,單片機(jī)才學(xué)了二十天左右,要是有愚蠢錯(cuò)誤別打。 clock.zip (20 KB, 下載次數(shù): 12)




回復(fù)

使用道具 舉報(bào)

ID:552614 發(fā)表于 2019-6-18 15:36 | 顯示全部樓層
你的keymod初始化就已經(jīng)等于零了啊,直接進(jìn)入if(keymod==o)里面的語(yǔ)句了
回復(fù)

使用道具 舉報(bào)

ID:332444 發(fā)表于 2019-6-18 16:41 | 顯示全部樓層
那就應(yīng)該判斷暫停模式狀態(tài)后才使K2有效,邏輯問(wèn)題
回復(fù)

使用道具 舉報(bào)

ID:565305 發(fā)表于 2019-6-18 17:50 | 顯示全部樓層
你這個(gè)函數(shù)是被別的函數(shù)調(diào)用吧, keymod 是一個(gè)局部變量,進(jìn)一次函數(shù)就會(huì)初始化一次
void keyscan()
{        u8 keymod=0;

解決方法,要么這個(gè)變量設(shè)定為全局變量,要么透過(guò)入口參數(shù)傳入
=======================
另外不得不說(shuō)一下,這種到處寫(xiě) while(!xxxxx) 真心要不得,阻塞主程序流程不說(shuō),還不方便做并行操作

=======================
//  請(qǐng)確保 main 函數(shù)的 while 循環(huán)和 delay_1ms 均存在并且不會(huì)超時(shí)。并且?guī)挛娜齻(gè)全局變量
int  keymod=0;
int  k1_count=0, k2_count=0;
void main()
{
    while(1)   
    {
        scan_key();
        other_event_func();
        delay_1ms(); ....
     }
}

void scan_key()
{
    // 判斷:兩個(gè)按鍵必須有連續(xù) 10ms 處于按住(去抖)狀態(tài)才能當(dāng)做“有效按下”
    // 由于只需要判斷按下瞬間,所以下文 100 的常量只是讓其不溢出且大于 10ms 即可
    if(k1==0){ if(k1_count<100) k1_count++; } else k1_count=0;
    if(k2==0){ if(k2_count<100) k2_count++; } else k2_count=0;

    // 有按住的時(shí)序計(jì)數(shù)器了,那么計(jì)數(shù)器等于 10 的瞬間就是“按下瞬間”,而不是“按住瞬間”
    if(k1_count==10)
    {
        TR0=!TR0; keymod=!keymode;  // 進(jìn)入狀態(tài)切換
    }
    // k2 按下瞬間,只要 keymod==0 (暫停態(tài)),就做歸零
    if(k2_count==10 && keymod==0)
    {
        sec=0;min=0;hour=0;  
    }
}


回復(fù)

使用道具 舉報(bào)

ID:562692 發(fā)表于 2019-6-18 20:54 | 顯示全部樓層
egypt 發(fā)表于 2019-6-18 17:50
你這個(gè)函數(shù)是被別的函數(shù)調(diào)用吧, keymod 是一個(gè)局部變量,進(jìn)一次函數(shù)就會(huì)初始化一次
void keyscan()
{    ...

謝謝指點(diǎn),發(fā)現(xiàn)只要把keymod設(shè)置成全局變量,然后用
if((k2==0)&&(keymod==0))
替換那兩句就可以了
回復(fù)

使用道具 舉報(bào)

ID:562692 發(fā)表于 2019-6-18 21:03 | 顯示全部樓層
egypt 發(fā)表于 2019-6-18 17:50
你這個(gè)函數(shù)是被別的函數(shù)調(diào)用吧, keymod 是一個(gè)局部變量,進(jìn)一次函數(shù)就會(huì)初始化一次
void keyscan()
{    ...

我是按照教程上學(xué)的while(!xxxx),學(xué)習(xí)教程是買(mǎi)開(kāi)發(fā)板送的,原來(lái)不好啊。不知道您有什么好的教程推薦?
回復(fù)

使用道具 舉報(bào)

ID:517466 發(fā)表于 2019-6-18 23:22 | 顯示全部樓層
你的程序中有錯(cuò)誤。定時(shí)器TR沒(méi)有設(shè)成1,導(dǎo)致定時(shí)器不工作,沒(méi)法計(jì)時(shí)。程序修改如下:
/*采用普中科技ES-V2.0開(kāi)發(fā)板作為實(shí)驗(yàn)硬件*/
#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;

sbit LSA=P2^0;
sbit LSB=P2^1;
sbit LSC=P2^2;
sbit LSD=P2^3;
sbit k1=P3^1;  
sbit k2=P3^0;

u8 sec,min,hour;

u8 code  shuzu[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                                  0x7f,0x6f,0x77};        //共陽(yáng)數(shù)碼管碼表,code表示保存到flash空間,節(jié)省rom       
u8 code table[]={   // 共陰數(shù)碼管,筆段=0時(shí),筆段點(diǎn)亮。0-0xC0
    0xc0,0xf9,0xa4,0xb0,0x99,
        0x92,0x82,0xf8,0x80,0x90,0xff, 0xbf};
void delay(u16 i)
{
        while(i--);       
}
void Timer0Init()
{
        TMOD|=0X01;//選擇為定時(shí)器0模式,工作方式1,僅用TR0打開(kāi)啟動(dòng)。
        TH0=0X3c;        //給定時(shí)器賦初值,定時(shí)50ms
        TL0=0Xb0;       
        ET0=1;//打開(kāi)定時(shí)器0中斷允許
        EA=1;//打開(kāi)總中斷
        TR0=1;//關(guān)閉定時(shí)器                       
}
void keyscan()
{        u8 keymod=0;
        if(k1==0)
        {
                delay(1000);
                if(k1==0)
                {
                        TR0=!TR0;
                        keymod=!keymod;               
                }
                while(!k1);
        }
        if(keymod==0)
        {
                if(k2==0)
                {
                        delay(1000);
                        if(k2==0)
                        {
                                sec=0,min=0,hour=0;               
                        }
                        while(!k2);
                }
        }
}

void DigDisplay(u8 min,u8 sec)
{
        u8 i;
        for(i=0;i<4;i++)
        {
                switch(i)         //位選,選擇點(diǎn)亮的數(shù)碼管,
                {
                  // 共陰用
                        case(0):
                                LSA=0;LSB=1;LSC=1;LSD=1;P0=shuzu[min/10]; break;//顯示第0位
                        case(1):
                                LSA=1;LSB=0;LSC=1;LSD=1;P0=shuzu[min%10];break;//顯示第1位
                        case(2):
                                LSA=1;LSB=1;LSC=0;LSD=1;P0=shuzu[sec/10];break;//顯示第2位
                        case(3):
                                LSA=1;LSB=1;LSC=1;LSD=0;P0=shuzu[sec%10]; break;//顯示第3位                               
                }
    delay(100); //間隔一段時(shí)間掃描       
                // 共陰用
                P0=0x00;//消隱筆段
        }
}
void main()
{       
        Timer0Init();
        while(1)
        {       
                P1=sec;
                DigDisplay(min,sec);
                keyscan();
                       
        }               
}


void Timer0() interrupt 1
{
        static u16 i;
        TH0=0X3c;        //給定時(shí)器賦初值,定時(shí)50ms
        TL0=0Xb0;
        i++;
        if(i==20)
        {
                i=0;
                sec++;
                if(sec==60)
                {
                        sec=0;
                        min++;
                        if(min==60)
                        {
                                min=0;
                                hour++;
                                if(hour==99)
                                {
                                        hour=0;

                                }
                        }
                }       
        }       
}               
回復(fù)

使用道具 舉報(bào)

ID:517466 發(fā)表于 2019-6-18 23:25 | 顯示全部樓層
附上proteus的仿真文件

test.zip

15.92 KB, 下載次數(shù): 10

回復(fù)

使用道具 舉報(bào)

ID:207421 發(fā)表于 2019-6-19 01:08 | 顯示全部樓層
其實(shí)把 u8 keymod=0; 變?yōu)槿肿兞,改?u8 keymod=1; 就好了。
當(dāng)按K1, TR0 =1; keymod=0;
此時(shí) K2有效
回復(fù)

使用道具 舉報(bào)

ID:565305 發(fā)表于 2019-6-19 08:46 | 顯示全部樓層
帶多個(gè)鎖死 while 的程序,真正測(cè)試的時(shí)候,會(huì)發(fā)現(xiàn)有按鍵不響應(yīng)的 BUG

你試著按住 k1 后不松手,再按 k2 ,試個(gè)兩三次就知道了

或者按住 k2 不松手,再按 k1 看看功能正常不
回復(fù)

使用道具 舉報(bào)

ID:566603 發(fā)表于 2019-6-19 11:36 | 顯示全部樓層
將下面的if(keymod==0)改為if(keymod!=0)試試,keymod應(yīng)該是在key1按下后取反,表示key1已經(jīng)按下,那么下面的判斷就不能是keymod==0,因?yàn)閗eymod的初始化情況就是0,當(dāng)然按下key2會(huì)清零.-----建議僅供參考
回復(fù)

使用道具 舉報(bào)

ID:160500 發(fā)表于 2019-6-19 16:39 | 顯示全部樓層
建議你先畫(huà)一個(gè)流程圖,理清其中的邏輯關(guān)系,根據(jù)流程圖再編程實(shí)現(xiàn)所需要的功能
回復(fù)

使用道具 舉報(bào)

ID:564631 發(fā)表于 2019-6-19 17:49 | 顯示全部樓層
void keyscan()
{        u8 keymod=0;
        if(k1==0)
        {
                delay(1000);
                if(k1==0)
                {
                        TR0=!TR0;
                        keymod=!keymod;               
                }
                while(!k1);
        }
        if(keymod==1)
        {
                if(k2==0)
                {
                        delay(1000);
                        if(k2==0)
                        {
                                sec=0,min=0,hour=0;               
                        }
                        while(!k2);
                }
        }
}
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表