找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2755|回复: 4
打印 上一主题 下一主题
收起左侧

矩阵键盘输入数字,数码管实现倒计时,单片机初学者,不知道这个哪里错了

[复制链接]
跳转到指定楼层
楼主
ID:882907 发表于 2021-2-4 21:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <REGX52.H>

unsigned char NixieTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

unsigned char KeyNumber=0,sec;

void Delay(unsigned int xms)
{
  unsigned char i,j;
  while(xms)
  {
        i = 2;
        j = 239;
        do
        {
           while (--j);
        }while (--i);
        xms--;
  }
}

void Nixie(unsigned char Location,Number)
{
        switch(Location)
        {
                case 1:P2_4=1;P2_3=1;P2_2=1;break;
                case 2:P2_4=1;P2_3=1;P2_2=0;break;
                case 3:P2_4=1;P2_3=0;P2_2=1;break;
                case 4:P2_4=1;P2_3=0;P2_2=0;break;
                case 5:P2_4=0;P2_3=1;P2_2=1;break;
                case 6:P2_4=0;P2_3=1;P2_2=0;break;
                case 7:P2_4=0;P2_3=0;P2_2=1;break;
                case 8:P2_4=0;P2_3=0;P2_2=0;break;
        }
        P0=NixieTable[Number];
        Delay(1);
        P0=0x00;
}

unsigned char MatrixKey()
{
       

        P1=0xFF;
        P1_3=0;
        if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
        if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
        if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
        if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}

        P1=0xFF;
        P1_2=0;
        if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
        if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
        if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
        if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}

        P1=0xFF;
        P1_1=0;
        if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
        if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
        if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
        if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}

        P1=0xFF;
        P1_0=0;
        if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
        if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
        if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
        if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}

        return KeyNumber;
}

void Timer0Init(void)                //1毫秒@12.000MHz
{
        TMOD &= 0xF0;                //设置定时器模式
        TMOD |= 0x01;                //设置定时器模式
        TL0 = 0x18;                //设置定时初值
        TH0 = 0xFC;                //设置定时初值
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
        ET0=1;
        EA=1;
        PT0=0;                    
}

void main()
{
       
        Timer0Init();
        while(1)
        {       
                if(P3_0==0)
                {
                Delay(20);
                while(P3_0==0);
                Delay(20);
                sec=MatrixKey();
                }
                Nixie(1,sec);
        }
}


void Timer0_Routine() interrupt 1
{       
        static unsigned int T0Count;
        TL0 = 0x18;                //设置定时初值
        TH0 = 0xFC;                //设置定时初值
        T0Count++;
        if(T0Count>=1000)
        {
                T0Count=0;
                sec--;
        }
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:332444 发表于 2021-2-5 09:35 | 只看该作者
矩阵代码写的太多了,看得乱就不想看了,可参https://blog.csdn.net/xianfajushi/article/details/80884859  写得简洁些
回复

使用道具 举报

板凳
ID:213173 发表于 2021-2-5 14:38 | 只看该作者
  1. #include <REGX52.H>

  2. unsigned char NixieTable[]={
  3.                 0x3f,0x06,0x5b,0x4f,
  4.                 0x66,0x6d,0x7d,0x07,
  5.                 0x7f,0x6f,0x77,0x7c,
  6.                 0x39,0x5e,0x79,0x71,0x3d};

  7. unsigned char KeyValue=0;
  8. bit flag=0;

  9. void Delay(unsigned int xms)
  10. {
  11.   unsigned char i,j;
  12.   while(xms)
  13.   {
  14.         i = 2;
  15.         j = 239;
  16.         do
  17.         {
  18.            while (--j);
  19.         }while (--i);
  20.         xms--;
  21.   }
  22. }

  23. void Nixie(unsigned char Number)
  24. {
  25.         static unsigned char i;
  26.         unsigned char a[2];

  27.         if(Number>9)
  28.                 a[0]=NixieTable[Number/10];
  29.         else a[0]=0x00;
  30.         a[1]=NixieTable[Number%10];
  31.         P0=0x00;
  32.         P2&=0xe3;
  33.         P2|=~((0x00+i)<<2);
  34.         P0=a[i];
  35.         i=++i%2;
  36.         Delay(1);
  37. }

  38. void MatrixKey()
  39. {
  40.         static unsigned char count=0;
  41.         static bit sign=0;
  42.         P1=0xf0;                                        //赋值P1 1111 0000
  43.         if(P1!=0xf0)                                //检测有按键按下
  44.         {
  45.                 if(++count>=10 && sign==0)
  46.                 {                       
  47.                         sign=1;                        //按键自锁标志置1
  48.                         switch(P1)
  49.                         {
  50.                                 case(0Xe0):KeyValue = 0;break;
  51.                                 case(0Xd0):KeyValue = 1;break;
  52.                                 case(0Xb0):KeyValue = 2;break;
  53.                                 case(0X70):KeyValue = 3;break;
  54.                         }
  55.                         P1=0x0f;                        //赋值P1 0000 1111
  56.                         switch(P1)
  57.                         {
  58.                                 case(0X0e):KeyValue+= 1;break;
  59.                                 case(0X0d):KeyValue+= 5;break;
  60.                                 case(0X0b):KeyValue+= 9;break;
  61.                                 case(0X07):KeyValue+=13;break;
  62.                         }
  63.                 }
  64.         }
  65.         else                                                //键抬起
  66.         {
  67.                 sign=0;                                //按键自锁标志清0
  68.                 count=0;                                //消抖计数清0
  69.         }
  70. }

  71. void Timer0Init(void)                //1毫秒@12.000MHz
  72. {
  73.         TMOD= 0x01;                //设置定时器模式
  74.         TL0 = 0x18;                //设置定时初值
  75.         TH0 = 0xFC;                //设置定时初值
  76.         TR0 = 1;                //定时器0开始计时
  77.         ET0 = 1;
  78.         EA  = 1;         
  79. }

  80. void main()
  81. {        
  82.         Timer0Init();
  83.         while(1)
  84.         {        
  85.                 if(flag==0)
  86.                         MatrixKey();
  87.                 if(P3_0==0)
  88.                         flag=1;
  89.                 Nixie(KeyValue);
  90.         }
  91. }

  92. void Timer0_Routine() interrupt 1
  93. {        
  94.         static unsigned int T0Count;
  95.         TL0 = 0x18;                //设置定时初值
  96.         TH0 = 0xFC;                //设置定时初值
  97.         if(KeyValue>0&&flag==1)
  98.         {
  99.                 T0Count++;
  100.                 if(T0Count>=1000)
  101.                 {
  102.                         T0Count=0;
  103.                         KeyValue--;
  104.                         if(KeyValue==0)
  105.                         {
  106.                                 flag=0;
  107.                         }
  108.                 }
  109.         }
  110. }
复制代码
回复

使用道具 举报

地板
ID:883031 发表于 2021-2-5 15:38 | 只看该作者
if(P3_0==0)
                {
                Delay(20);
                while(P3_0==0);
                Delay(20);
                sec=MatrixKey();
                }
红色部分,如果是抖动,可能会误动作。
另外,你的键值扫描,如果没有按键按下,返回的是什么值?可能会是上次的值。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

5#
ID:883031 发表于 2021-2-5 15:49 | 只看该作者
unsigned char idata DrvKey;                        //驱动线值
unsigned char idata ScnKey;                        //扫描线值
unsigned char KeyValue;
/*******************************************************************************
*   函数原型:bit KeyScan(void);
*   功    能:键盘扫描子程序,判断是否有键按下。
*******************************************************************************/
bit KeyScan(void)
{
        DRVKEY &= 0xf0;
        HX = 0;
        ScnKey = ~SCNKEY;      // ^ 0xff列线值取反,以便判断
        ScnKey &= 0x1e;       

        if (ScnKey != 0)                //列线值不全为0,则有键按下
        {
                return TRUE;
        }
        else                    //否则,无键按下
        {
                return FALSE;
        }       
}

/*******************************************************************************
*   函数原型:void Delay(unsigned char i);
*   功    能:延时子程序,用于去抖。
*******************************************************************************/
void Delay(unsigned char i)
{
        int j = 0;
        int k = 0;
        k = i * i;
        while (j < k)
        {
                j++;
        }
}
/*******************************************************************************
*   函数原型:bit AvoidWobble(void);
*   功    能:去抖子程序,用于消除抖动,判断是否真有键按下。
*******************************************************************************/
bit AvoidWobble(void)
{
        Delay(5);                //延时再读
        if (KeyScan())                        //仍有键按下,返回1
        {
                return TRUE;
        }
        else                    //无键按下则为抖动
        {
                return FALSE;
        }
}
/*******************************************************************************
*   函数原型:unsigned char GetKey(void);
*   功    能:键盘子程序。最大8*8键盘。
*******************************************************************************/
unsigned char GetKey(void)
{
        unsigned char i;
        unsigned char j;
        unsigned char Key_Value = 0;
        unsigned char temp = 0x01;
        HX = 1;
       
    if (KeyScan())              //有键按下取其值
    {
            if (AvoidWobble())                //确实有键按下,取其值
            {
                           for (i = 0;i < DRV_NUM;i++)   //行线移位送0
                    {
                            DRVKEY = (temp << i) ^ 0x0f;

                            for (j =1;j < SCN_NUM + 1;j++)   //列线移位扫描
                            {
                                ScnKey = SCNKEY;         //读列线值
                                    ScnKey >>= j;            
                                    ScnKey &= 0x01;
                                    if (ScnKey == 0)         //判断第j位是否为0
                                    {
                                            Key_Value += (j - 1);        //计算健值
                                              while(KeyScan())       //等待按键松开
                        {
                            ;
                        }
                                            return Key_Value;
                                    }
                            }
                            Key_Value += SCN_NUM;          //第i行无按键按下,键值加列线值,扫描第i+1行
                    }
                   return 255;
            }
    }
    else
    {
        return 255;
    }
}

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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