choi 发表于 2012-9-10 12:47:28

動態掃描 數碼管閃動

用數碼管做了個學習板原意是按按鍵k20 數字加一按按鍵k21數字減一   但發現按鍵長按的時候數碼管沒有顯示
只有鬆開按鍵數碼管才顯示正確的數字快速按動按鍵數碼管顯示的數字在閃動請各位幫忙看看程序那裏出錯了
謝謝





#include<reg52.h>
#include<intrins.h>
unsigned char code dsp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67};        //0,1,2,3,4,5,6,7,8,9
sbit led=P3^7;
sbit beep=P3^4;
sbit k20=P2^7;
sbit k21=P2^6;
unsigned int num;
void delayms(unsigned int time);           //長延時
void delayms1(unsigned char tt);           //短延時
void beep1();                                                   //開啓蜂鳴器
void display(unsigned int number);           //顯示數字
void scankey();                                                   //鍵盤掃描
main()
{
        while(1)
        {
                scankey();
                display(num);
        }
}
void delayms(unsigned int time)
{
        unsigned int n;
        unsigned int m;
    while(time>0)
        {
                for(n=0;n<300;n++)
                {
                        for(m=0;m<300;m++);
                }
                time--;
        }
}

void beep1()
{
        beep=0;
        delayms(2);
        beep=1;
}
void display(unsigned int number)
{
        unsigned char bai,shi,ge;
        bai=number/100;                   //分離數字
        shi=number%100/10;
        ge=number%10;
        P2=0xfe;          //百位顯示打開
        P0=dsp;        //顯示百位的數字
        delayms1(10);
        P0=0x00;           //消隱
        P2=0xfb;       //十位顯示打開
        P0=dsp;
        delayms1(10);
        P0=0x00;
        P2=0xf7;       //個位顯示打開
        P0=dsp;
        delayms1(10);
        P0=0x00;
}
void scankey()
{
        if (k20==0)                                //數字加
        {
                delayms(1);
                if(k20==0)
                {
                        num++;
                        if(num==1000)
                        {
                                num=0;
                        }
                        while(!k20);
                        beep1();
                }
        }
        if(k21==0)                //數字減
        {
                delayms(1);
                if(k21==0)
                {
                  if(num==0)
                        {
                                num=1000;
                        }
                        num--;
                        while(!k21);
                        beep1();
                }
        }
}
void delayms1(unsigned char tt)
{
        unsigned char n=200;
        while(tt>0)
        {
                while(n>0)
                {
                        n--;
                }
                tt--;
        }
}

锦瑟华年 发表于 2012-9-10 12:49:38

呵呵,
while(!k21);
你觉得这时候你按住按键cpu在干嘛呢?{:lol:}
就在while这空转了,不会执行别的代码

choi 发表于 2012-9-10 13:15:51

想檢測按鍵是否已經釋放怕數字亂閃

锦瑟华年 发表于 2012-9-10 13:28:19

嗯,我知道,但是這種寫法只適合測試用,不適合工程用,一般而言,這種按鍵可以使用‘狀態機’實現,本壇有個帖子《从单片机初学者到单片机工程师》裏面詳細介紹了這種寫法,樓主有時間的話可以去好好看看,如果有不懂的咱們可以交流一下

choi 发表于 2012-9-10 13:45:26

謝謝你   趕緊去找找這文章

锦瑟华年 发表于 2012-9-10 14:02:24

嗯,這篇文章在網上有全文的pdf下載的,能很好地提高初學者的眼界(其實我也是初學者啦:) ),要完全吸收理解還是要花些功夫的,樓主加油
PS1:那篇文章裡的按鍵功能很全面,如果不需要那麼多功能(比如你現在的程序),是可以很輕鬆地修改成簡化版的
PS2:作者當時應該是武漢職業技術學院的學生,現在畢業了,吃水不忘挖井人,呵呵

choi 发表于 2012-9-10 16:34:32

文章找到了在慢慢看吸收中

beijinggood2008 发表于 2012-9-11 19:46:27

锦瑟华年 发表于 2012-9-10 13:28 static/image/common/back.gif
嗯,我知道,但是這種寫法只適合測試用,不適合工程用,一般而言,這種按鍵可以使用‘狀態機’實現,本壇有 ...

那个文章我也看了 受益匪浅!现在正在用那个方法~

tonyone 发表于 2012-9-11 23:36:47

做个记号

876192514 发表于 2012-9-12 19:22:49

本帖最后由 876192514 于 2012-9-12 19:25 编辑

1 用定时器扫描数码管
2按键做2个标志 一个用来记录按键 一个程序做判断用 用完后清除
比如
if(KEY==0)
{
if(标志1==0)
{标志1=1;
标志2=1;
}
}
else
{标志1=0;}

if(标志2==1)
{标志2=0;
动作;
}

choi 发表于 2012-9-18 09:50:23

按10樓的方法更改了數碼管的掃描方式改善了按鍵被按下時led閃的問題   但又出現了個新情況就是
數碼管的亮度不一緻有些會亮些有些會暗點   我改了掃描時間不能改善   請問亮度不一緻是什麽原因
造成的      附件是更改后的程序   還有我取消了消隱的語句好像沒出問題不明?



#include<reg52.h>
#include<intrins.h>
unsigned char code dsp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67};        //0,1,2,3,4,5,6,7,8,9
sbit led=P3^7;
sbit beep=P3^4;
sbit k20=P2^7;
sbit k21=P2^6;
sbit k22=P2^5;
unsigned int num;
unsigned char loop;
void delayms(unsigned int time);           //長延時
void delayms1(unsigned char tt);           //短延時
void beep1();                                                   //開啓蜂鳴器
void display(unsigned int number);           //顯示數字
void scankey();                                                   //鍵盤掃描
main()
{
        TMOD=0x01;
        TH0=(65536-5505)/256;
        TL0=(65536-5505)%256;
        EA=1;
        ET0=1;
        TR0=1;
        while(1)
        {
                scankey();
        }
}
void delayms(unsigned int time)
{
        unsigned int n;
        unsigned int m;
    while(time>0)
        {
                for(n=0;n<300;n++)
                {
                        for(m=0;m<300;m++);
                }
                time--;
        }
}

void beep1()
{
        beep=0;
        delayms(2);
        beep=1;
}
void display(unsigned int number)
{
        unsigned char bai,shi,ge;
        bai=number/100;                   //分離數字
        shi=number%100/10;
        ge=number%10;
        if(loop==0)
        {
                P2=0xfe;         //百位顯示打開
                P0=dsp;          //顯示百位的數字

        }
        if(loop==1)
        {
                P2=0xfb;       //十位顯示打開
                P0=dsp;
        }
        if(loop==2)
        {
                P2=0xf7;       //個位顯示打開
                P0=dsp;
        }
}
void scankey()
{
        if (k20==0)                                //數字加
        {
                delayms(1);
                if(k20==0)
                {
                        num++;
                        if(num==1000)
                        {
                                num=0;
                        }
                        while(!k20);
                        beep1();
                }
        }
        if(k21==0)                //數字減
        {
                delayms(1);
                if(k21==0)
                {
                  if(num==0)
                        {
                                num=1000;
                        }
                        num--;
                        while(!k21);
                        beep1();
                }
        }
        if(k22==0)
        {
                delayms(1);
                if(k22==0)
                {
                        num=0;
                }
                while(!k22);
                beep1();
        }
}
void delayms1(unsigned char tt)
{
        unsigned char n=200;
        while(tt>0)
        {
                while(n>0)
                {
                        n--;
                }
                tt--;
        }
}
void t0_time() interrupt 1
{
        TH0=(65536-5505)/256;
        TL0=(65536-5505)%256;
        display(num);
        loop++;
        if(loop>3)
        {
                loop=0;
        }
       
}

halloocc 发表于 2012-9-18 10:38:13

马老师 著述 的状态 机 很 不错的 {:victory:}{:lol:}

choi 发表于 2012-9-28 10:18:52

本帖最后由 choi 于 2012-9-28 10:21 编辑

匆匆將 《从单片机初学者到单片机工程师》這文章看完了受益匪浅!
修改了文章中的程序寫了以下的程序發現還是弄不懂如何將一個io腳單獨定時就像程序中的蜂鳴器響閙我想將io腳定時500ms翻轉就不是很成功請問應如何修改
完整程序如下

   /*要實現的效果
        1、led作流水效果閃動
        2、數碼管顯示0-9數字
        3、3個按鍵數字加數字減數字清零
數碼管刷新頻率=40Hz   按鍵刷新頻率=50Hz   led閃爍頻率=2Hz
定時器=5ms
*/
#include<reg52.h>
#include<intrins.h>
#define time_per_sec 200 //定義任務時鐘頻率 200hz
#define clock 11059200   //定義時鐘晶振 單位 Hz
#define max_task 3       //定義任務數量
#define key_state 0             //按鍵初始
#define key_wobble 1   //按鍵抖動
#define key_press 2             //按鍵壓下
#define key_release 3    //按鍵釋放
unsigned char code dsp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67};        //0,1,2,3,4,5,6,7,8,9
void display(unsigned int number);
void scankey();           //鍵盤掃描
void beep();           //蜂鳴器響閙
void task0();           //led閃爍
void task1();           //數碼管
void task2();           //按鍵
void keyactive();//鍵值對應功能
sbit k20=P2^7;   //數字加
sbit k21=P2^6;   //數字減
sbit k22=P2^5;   //數字清零
sbit bp=P3^4;           //蜂鳴器響閙控制

unsigned char task_delay; //任務延時變量定義
unsigned char n;
unsigned scan_led;
unsigned int num;
unsigned char keytemp;       //按鍵掃描設置
unsigned char keystate;
unsigned char keylast;
unsigned char keynull;
unsigned char timecount;
unsigned char m;
unsigned char l;
void timer0_init()//定時器0初始化
{
        unsigned char i;
        for(i=0;i<max_task;i++)task_delay=0; //任務延時量清零
        TMOD=0x01;                              //定時器0工作在模式1,16bit定時器模式
        TH0=255-clock/time_per_sec/12/256;                //設為5ms定時
        TL0=255-clock/time_per_sec/12%256;
        TR0=1;
        ET0=1;
}
void timer0() interrupt 1
{
        unsigned char i;
        TH0=255-clock/time_per_sec/12/256;
        TL0=255-clock/time_per_sec/12%256;
        /*設蜂鳴器響閙時長*/
        if(l==1)
        {
                m++;
                if(m>50)
                {
                        m=0;
                        bp=1;
                }
        }

        for(i=0;i<max_task;i++)
        {
                if(task_delay)
                {
                        task_delay--;                          
                }
        }


}
void main()
{
           keynull=0xf0;                                  //沒有按鍵按下的鍵值
        keystate=key_state;                          //按鍵狀態
        timer0_init();
        EA=1;
        P1=0x7f;                                          //led閃動初值
        while(1)
        {
                if(task_delay==0)                                  //led閃動
                        {
                                task0();
                                task_delay=time_per_sec/2;        //500ms頻率閃動
                        }
                if(task_delay==0)                                        //數碼管掃描
                {
                        task1();
                        task_delay=time_per_sec/200;                //5ms頻率掃描
                }
                if(task_delay==0)                                        //按鍵掃描
                {
                        task2();
                        task_delay=time_per_sec/50;          //20ms判斷一個按鍵
                }
        }

}
void task0()          //led閃爍效果
{
        if(n==0)                                  //判斷n=0時 led左移
        {
                P1=_crol_(P1,1);
                if(P1==0x7f)                  //判斷led是否到頭了(P1^7 led點亮了)
                {
                        n=1;
                        P1=0xfe;               //重新定義P1口數值 給右移作準備
                }
        }
        if(n==1)                                        //判斷n=1 led右移
        {
          
                P1=_cror_(P1,1);
                if(P1==0xfe)
                {
                        n=0;
                }
        }

}
void task1()       //數碼管顯示掃描
{
        display(num);
        scan_led++;
        if(scan_led>3)
        {
                scan_led=0;
        }
}
void task2()          //按鍵掃描
{
        scankey();
}


void display(unsigned int number)        //數碼管顯示
{
        unsigned char bai,shi,ge;
        bai=number/100;                   //分離數字
        shi=number%100/10;
        ge=number%10;
        if(scan_led==0)
        {
                P2=0xfe;         //百位顯示打開
                P0=dsp;          //顯示百位的數字

        }
        if(scan_led==1)
        {
                P2=0xfb;       //十位顯示打開
                P0=dsp;
        }
        if(scan_led==2)
        {
                P2=0xf7;       //個位顯示打開
                P0=dsp;
        }
}
void beep()                           //蜂鳴器響閙
{
        bp=0;
        l=1;                           //打開計時
}
void scankey()                        //鍵盤掃描
{
        keytemp=P2&0xf0;        //檢測是否有鍵按下
        switch(keystate)
        {
                case key_state:
                {
                        if(keynull!=keytemp)
                        {
                                keystate=key_wobble;
                        }
                }
                break;
                case key_wobble:                           //去抖動
                {
                        keystate=key_press;       
                }
                break;
                case key_press:                                        //檢測是否有鍵按下
                {
                        if(keynull!=keytemp)
                        {
                                keylast=keytemp;                //存鍵值
                                keystate=key_release;
                        }
                }
                break;
                case key_release:                               //檢測鍵是否鬆開
                {
                        if(keytemp==keynull)
                        {
                          keyactive();
                                keystate=key_state;       
                  }
                }
                break;
        }                  
}

void keyactive()                                  //鍵值對應功能
{
        if(keylast==0x70)                          //數字加
        {
                num++;
                if(num==1000)
                {
                        num=0;
                }
                beep();       
                keylast=keynull;
        }
        if(keylast==0xb0)                          //數字減
        {
                if(num==0)
                {
                        num=1000;
                }
                num--;
                beep();       
                keylast=keynull;
        }
        if(keylast==0xd0)                           //清零
        {
                num=0;
                beep();       
                keylast=keynull;
        }                       
}
页: [1]
查看完整版本: 動態掃描 數碼管閃動