[讨论] 430单片机按键控制数码管显示问题

pengbiao1210   2015-8-19 17:50 楼主
功能呢就类似于倒计数秒表,四个独立按键控制四位数码管显示;s1控制数码管显示可调,s2=1、2、3、4时,加减键操作分别为个十百千位, 现在的问题是,当我按下加减键时,比如s2=1时,个位跟十百千位一直常亮,闪烁程序不会。当我不按下按键时,我没法确定我操作对象是哪一位数码管,所以求怎样添加闪烁程序。单片机P4口连接两个74hc753,一片控制段信号,控制位信号;P6.3 P6.4控制74HC753的选通,P1.4-P1.7四个独立按键s1.s2.s3.s4

附上程序:




#include



#define uchar unsigned char

#define ulong unsigned long



ulong n=180;

uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,

               0x7f,0x6f};

#define DCTR0                P6OUT &= ~BIT4          //数码管段控制位信号置低

#define DCTR1           P6OUT |=  BIT4          //数码管段控制位信号置高

#define WCTR0                P6OUT &= ~BIT3          //数码管位控制位信号置低

#define WCTR1           P6OUT |=  BIT3          //数码管位控制位信号置高

#define DATAPORT        P4OUT                   //数据口所在端口P4

#define DATASEL         P4SEL                   //数据口功能寄存器,控制功能模式

#define DATADIR         P4DIR         





#define CTRPORT                P6OUT                   //控制线所在的端口P6

#define CTRSEL          P6SEL                   //控制口功能寄存器,控制功能模式

#define CTRDIR          P6DIR                   //控制口方向寄存器





#define KEYPORT                P1OUT                   //按键所在的端口P1

#define KEYSEL          P1SEL                   //控制口功能寄存器,控制功能模式

#define KEYDIR          P1DIR                   //控制口方向寄存器

#define KEYIN           P1IN   











void delay(int z)

{

  int x,y;

  for(x=z;x>0;x--)

    for(y=10;y>0;y--);

}

void Port_Init()

{

  DATASEL  = 0x00;                      //设置IO口为普通I/O模式,此句可省

  DATADIR  = 0xFF;                      //设置IO口方向为输出

  DATAPORT = 0xFF;                      //P4口初始设置为FF

  CTRSEL  =  0x00;                      //设置IO口为普通I/O模式,此句可省

  CTRDIR |=  BIT3 + BIT4;               //设置IO口方向为输出,控制口在P63,P64

  CTRPORT =  0xFF;  //P6口初始设置为FF



  KEYSEL = 0x00;                        //设置IO口为普通I/O模式,此句可省      

  KEYDIR = 0x0F;                        //高四位输入模式,低四位输出模式,外部上拉电阻

  KEYPORT= 0xF0;   

  P2DIR=0xFF;

  P2OUT=0xFF;



}

void Clock_Init()

{

  uchar i;

  BCSCTL1&=~XT2OFF;                 //打开XT2振荡器

  BCSCTL2|=SELM1+SELS;              //MCLK为8MHZ,SMCLK为8MHZ

  do{

    IFG1&=~OFIFG;                   //清楚振荡器错误标志

    for(i=0;i<100;i++)

       _NOP();

  }

  while((IFG1&OFIFG)!=0);           //如果标志位1,则继续循环等待

  IFG1&=~OFIFG;

}

void display()

{



uchar i,j,k,m;



m=n%1000%100%10;

  k=n%1000%100/10;

j=n%1000/100;

  i=n/1000;



    DCTR1;                            //控制数码管段数据的74HC573的LE管脚置高

    WCTR1;                            //控制数码管位的74HC573的LE管脚置高

    DATAPORT=0xfe;                      //设置要显示的位,也就是哪一个数码管亮

    WCTR0;                            //锁存位数据,下面送上段数据以后,就显示出来了                          

    DATAPORT=table;              //送要显示的数据,这里是键值

    DCTR0;                            //锁存段数据,数码管亮一个时间片刻



    delay(200);

   DCTR1;                            //控制数码管段数据的74HC573的LE管脚置高

    WCTR1;

    DATAPORT=0xfd;

    WCTR0;

    DATAPORT=table[j];

    DCTR0;



      delay(200);

    DCTR1;                            //控制数码管段数据的74HC573的LE管脚置高

    WCTR1;

    DATAPORT=0xfb;

    WCTR0;

    DATAPORT=table[k];

    DCTR0;



      delay(200);

    DCTR1;                            //控制数码管段数据的74HC573的LE管脚置高

    WCTR1;

    DATAPORT=0xf7;

    WCTR0;

    DATAPORT=table[m];

    DCTR0;

     delay(200);

}





void keyscan()

{

static uchar a,b,c,d;

static int s1num,s3num,s4num;

static char s2num=-1;





  if(P1IN==0xe0)

   {

      delay(5000);

      if(P1IN==0xe0)

      {

        while(P1IN==0xe0);



        s1num=s1num++;

     s1num=s1num%2;

        }}



       switch(s1num)

      {

           case 1:

             CCTL0 = ~CCIE;



           if(P1IN==0xd0)

         {

            delay(5000);

              if(P1IN==0xd0)



                 {

                   while(P1IN==0xd0);

                   s2num++;

                   s2num=s2num%4;

                  }

         }

         switch(s2num)

         {

         case 0:         if(P1IN==0x70)

                           {

                               delay(5000);

                               if(P1IN==0x70)

                                {

                                  while(P1IN==0x70);

                               //if((P1IN&0x80)

                                     a++;

                                     a=a%10;

                                      n=a+b*10+c*100+d*1000;

                                }

                           }

                         if(P1IN==0xb0)

                           {

                               delay(5000);

                               if(P1IN==0xb0)

                                {

                                    while(P1IN==0xb0);

                                   a--;

                                   if(a==255) a=9;



                                 n=a+b*10+c*100+d*1000;

                                }

                          }//display(n);                          //控制数码管段数据的74HC573的LE管脚置高





                       break;



         case 1:         if(P1IN==0x70)

                           {

                               delay(5000);

                               if(P1IN==0x70)

                                {

                                  while(P1IN==0x70);

                               //if((P1IN&0x80)

                                     b++;

                                     b=b%10;;

                                     n=a+b*10+c*100+d*1000;

                                }

                           }

                         if(P1IN==0xb0)

                           {

                               delay(5000);

                               if(P1IN==0xb0)

                                {

                                    while(P1IN==0xb0);

                                  b--;

                                   if(b==255) b=9;

                             n=a+b*10+c*100+d*1000;

                                }

                           }//display(n);

                        break;

         case 2:         if(P1IN==0x70)

                           {

                               delay(5000);

                               if(P1IN==0x70)

                                {

                                  while(P1IN==0x70);

                               //if((P1IN&0x80)

                                     c++;

                                     c=c%10;

                                     n=a+b*10+c*100+d*1000;

                                }

                           }

                         if(P1IN==0xb0)

                           {

                               delay(5000);

                               if(P1IN==0xb0)

                                {

                                    while(P1IN==0xb0);

                                   a--;

                                   if(a==255) a=9;

                               n=a+b*10+c*100+d*1000;

                                }

                           }//display(n);

                        ; break;

      case 3:         if(P1IN==0x70)

                           {

                               delay(5000);

                               if(P1IN==0x70)

                                {

                                  while(P1IN==0x70);

                               //if((P1IN&0x80)

                                     d++;

                                     d=d%10;

                                n=a+b*10+c*100+d*1000;

                                }

                           }

                         if(P1IN==0xb0)

                           {

                               delay(5000);

                               if(P1IN==0xb0)

                                {

                                    while(P1IN==0xb0);

                                   d--;

                                   if(d==255) d=9;

                                      n=a+b*10+c*100+d*1000;

                                }

                           }//display(n);

                 break;



       //display(n);

       // break;

         case -1: display(n); break;

         }

         break;

      case 0:  CCTL0 = CCIE;break;

      }

}









#pragma vector=TIMERA0_VECTOR

__interrupt void Timer_A0 (void)

{

n--;

}

void main(void)

{



     WDTCTL = WDTPW + WDTHOLD;                          //看门狗初始化

  Clock_Init();                         //时钟初始化

  Port_Init();      

  CCTL0 = CCIE;                 

    CCR0 = 4096;                  

    TACTL = TASSEL_1+ID_3 + MC_1;

    _EINT();

  while(1)

  {

    keyscan();

    display(n);

    if(n==0)

    {

      CCTL0 = ~CCIE;

      P2OUT=0x00;

      delay(200000);

      P2OUT=0xFF;

      n=180;

    }



}

}

回复评论 (6)

我看了下键盘扫描函数应该单独写,而您呢,却写在case语句之后了。这样的写法。。。。
点赞  2015-8-19 19:20
点赞  2015-8-20 07:43
引用: huaiqiao 发表于 2015-8-19 19:20
我看了下键盘扫描函数应该单独写,而您呢,却写在case语句之后了。这样的写法。。。。

能力 太低啊,但是加减按键之前一定要判定s2num啊,想不出来还能怎么写
点赞  2015-8-20 09:07
引用: pengbiao1210 发表于 2015-8-20 09:07
能力 太低啊,但是加减按键之前一定要判定s2num啊,想不出来还能怎么写

我个人建议啊,请把switch语句的判断和  键盘扫描函数(就是case后的语句分开)。实在不行,您可以先画个流程图出来。这样您的思路更加清晰一些的。不要怕浪费时间。
点赞  2015-8-20 09:14
引用: huaiqiao 发表于 2015-8-20 09:14
我个人建议啊,请把switch语句的判断和  键盘扫描函数(就是case后的语句分开)。实在不行,您可以先画个 ...

那怎样 让操作的那位数码管闪烁呢
点赞  2015-8-20 09:35
引用: pengbiao1210 发表于 2015-8-20 09:35
那怎样 让操作的那位数码管闪烁呢

键盘扫描的函数里,我只是举个例子。比如在扫描函数中按下key1键,获取键值1,那么数码管显示1。这个我想你与其问。还不如去画个流程图,这样你写程序的时候就不怎么茫然了。
点赞  2015-8-20 10:05
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复