搜索
bottom↓
回复: 12

動態掃描 數碼管閃動

[复制链接]

出0入0汤圆

发表于 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[bai];        //顯示百位的數字
        delayms1(10);
        P0=0x00;           //消隱
        P2=0xfb;       //十位顯示打開
        P0=dsp[shi];
        delayms1(10);
        P0=0x00;
        P2=0xf7;       //個位顯示打開
        P0=dsp[ge];
        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--;
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2012-9-10 12:49:38 | 显示全部楼层
呵呵,
while(!k21);
你觉得这时候你按住按键cpu在干嘛呢?
就在while这空转了,不会执行别的代码

出0入0汤圆

 楼主| 发表于 2012-9-10 13:15:51 | 显示全部楼层
想檢測按鍵是否已經釋放  怕數字亂閃

出0入0汤圆

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

出0入0汤圆

 楼主| 发表于 2012-9-10 13:45:26 | 显示全部楼层
謝謝你   趕緊去找找這文章  

出0入0汤圆

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

出0入0汤圆

 楼主| 发表于 2012-9-10 16:34:32 | 显示全部楼层
文章找到了  在慢慢看  吸收中

出0入0汤圆

发表于 2012-9-11 19:46:27 | 显示全部楼层
锦瑟华年 发表于 2012-9-10 13:28
嗯,我知道,但是這種寫法只適合測試用,不適合工程用,一般而言,這種按鍵可以使用‘狀態機’實現,本壇有 ...

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

出0入0汤圆

发表于 2012-9-11 23:36:47 | 显示全部楼层
做个记号

出0入0汤圆

发表于 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;
动作;
}

出0入0汤圆

 楼主| 发表于 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[bai];          //顯示百位的數字

        }
        if(loop==1)
        {
                P2=0xfb;       //十位顯示打開
                P0=dsp[shi];
        }
        if(loop==2)
        {
                P2=0xf7;       //個位顯示打開
                P0=dsp[ge];
        }
}
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;
        }
       
}

出0入0汤圆

发表于 2012-9-18 10:38:13 | 显示全部楼层
马老师 著述 的状态 机 很 不错的

出0入0汤圆

 楼主| 发表于 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[3]; //任務延時變量定義
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]==0)                                    //led閃動  
                        {
                                task0();
                                task_delay[0]=time_per_sec/2;        //500ms頻率閃動
                        }
                if(task_delay[1]==0)                                        //數碼管掃描
                {
                        task1();
                        task_delay[1]=time_per_sec/200;                //5ms頻率掃描
                }
                if(task_delay[2]==0)                                        //按鍵掃描
                {
                        task2();
                        task_delay[2]=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[bai];          //顯示百位的數字

        }
        if(scan_led==1)
        {
                P2=0xfb;       //十位顯示打開
                P0=dsp[shi];
        }
        if(scan_led==2)
        {
                P2=0xf7;       //個位顯示打開
                P0=dsp[ge];
        }
}
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;
        }                       
}
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 22:10

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表