请教一下动态数码管,最后一位显示特别亮是什么问题?

2020-02-01 16:25发布

也就是w6那一位,程序如下:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define key_state_0        0 //初始
#define key_state_1        1 //按下
#define key_state_2        2 //释放
uchar code table[]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,
0x79,0x71
};
sbit DS=P2^2;
sbit duan=P2^6;
sbit wei=P2^7;
#define WRITE_SECOND 0x80
#define WRITE_MINUTE 0x82
#define WRITE_HOUR 0x84
#define READ_SECOND 0x81
#define READ_MINUTE 0x83
#define READ_HOUR 0x85
#define WRITE_PROTECT 0x8E
sbit ACC_7=ACC^7;//位寻址寄存器定义
sbit SCLK=P3^2; // DS1302时钟信号         6脚
sbit DIO=P2^4;  // DS1302数据信号         7脚
sbit CE=P3^3;   // DS1302片选            5脚
sbit key_1=P3^4;
sbit key_2=P3^5;
sbit key_3=P3^6;
sbit key_4=P3^7;
sbit fm=P2^3;
uchar miao,fen,shi,fun,s2a,lshi,lfen,kai,flag,flag1;
uint temp;
void smgxs(uchar, uchar, uchar);
void delay(uchar z);
void Write1302 ( uchar addr,dat );
uchar Read1302 (uchar addr );
void Initial( );
void xsxz( );
void naozhong( );
void read_key( );
void delay1(uint count)      //延时函数
{
  uint i;
  while(count)
  {
    i=200;
    while(i>0)
    i--;
    count--;
  }
}
void dsreset(void)       //复位初始化函数
{
  uint i;
  DS=0;
  i=103;
  while(i>0)i--;
  DS=1;
  i=4;
  while(i>0)i--;
}

bit tmpreadbit(void)       //读一位数据函数
{
   uint i;
   bit dat;
   DS=0;i++;          //i++ 起延时作用
   DS=1;i++;i++;
   dat=DS;
   i=8;while(i>0)i--;
   return (dat);
}

uchar tmpread(void)   //读一个字节函数
{
  uchar i,j,dat;
  dat=0;
  for(i=1;i<=8;i++)
  {
    j=tmpreadbit();
    dat=(j<<7)|(dat>>1);   //读出的数据最低位在最前面,这样刚好一个字节在DAT里
  }
  return(dat);
}

void tmpwritebyte(uchar dat)   //写一个字节函数
{
  uint i;
  uchar j;
  bit testb;
  for(j=1;j<=8;j++)
  {
    testb=dat&0x01;
    dat=dat>>1;
    if(testb)     //写1
    {
      DS=0;
      i++;i++;
      DS=1;
      i=8;while(i>0)i--;
    }
    else
    {
      DS=0;       //写0
      i=8;while(i>0)i--;
      DS=1;
      i++;i++;
    }

  }
}

void tmpchange(void)  //获取温度并转换
{
  dsreset();
  delay1(1);
  tmpwritebyte(0xcc);  //写跳过读rom指令
  tmpwritebyte(0x44);  //写温度转换指令
}

uint tmp()               //读取寄存器中存储的温度数据
{
  float tt;
  uchar a,b;
  dsreset();
  delay1(1);
  tmpwritebyte(0xcc);
  tmpwritebyte(0xbe);
  a=tmpread();           //读低8位
  b=tmpread();           //读高8位
  temp=b;
  temp<<=8;             //字节合并
  temp=temp|a;
  tt=temp*0.0625;       //温度在寄存器中挝?2位,分辨率为0.0625
  temp=tt;       //乘10表示小数点后面只取一位
  return temp;
}
void main( )
{
  TMOD=0x01;//定时器工作方式2(8位自动重装)
  TH0=0xD8;//装初值
  TL0=0xF0;//装初值
  EA=1;//开总中断
  ET0=1;//开定时器0中断
  TR0=1;//启动定时器0
  fun=0;
  s2a=0;
  flag=0;
  flag=1;
  Initial();//时钟初始化
  while(1)
{
  //miao=Read1302(READ_SECOND);//读取秒
           
  fen=Read1302(READ_MINUTE);//读取分
           
  shi=Read1302(READ_HOUR);//读取时
           
  xsxz( );
  if(flag==1)
  naozhong( );
  tmpchange(); //获取温度并转换
}
}
void smgxs(uchar shi, uchar fen, uchar miao)//
{
     uchar w1,w2,w3,w4,w5,w6;      
           w1=shi/10;
           w2=shi%10;
           w3=fen/10;
           w4=fen%10;
           w5=miao/10;
           w6=miao%10;

           duan=1;//打开段选
           P0=table[w1];//段数据
           duan=0;//关闭段选
           P0=0xff;//消隐
           wei=1;//打开位选
           P0=0xfe;//位数据
           wei=0;//关闭位选
           delay(5);//延时

           duan=1;
           P0=table[w2];
           duan=0;
           P0=0xff;
           wei=1;
           P0=0xfd;
           wei=0;
           delay(5);
         
           duan=1;
           P0=table[w3];
           duan=0;
           P0=0xff;
           wei=1;
           P0=0xfb;
           wei=0;
           delay(5);

           duan=1;
           P0=table[w4];
           duan=0;
           P0=0xff;
           wei=1;
           P0=0xf7;
           wei=0;
           delay(5);

           duan=1;
           P0=table[w5];
           duan=0;
           P0=0xff;
           wei=1;
           P0=0xef;
           wei=0;
           delay(5);

           duan=1;
           P0=table[w6];
           duan=0;
           P0=0xff;
           wei=1;
           P0=0xdf;
           wei=0;
           delay(5);
           
}
void delay(uchar z)//延时子程序ms
{
   uchar x,y;
    for (x=z;x>0;x--)
        for(y=110;y>0;y--);   
}
void Write1302 ( uchar addr,dat ) //地址、数据发送子程序   
{
       uchar i,temp;
       CE=0;                         //CE引脚为低,数据传送中止
       SCLK=0;                    //清零时钟总线
       CE=1;                       //CE引脚为高,逻辑控制有效//发送地址
       for ( i=8; i>0; i-- ) //循环8次移位
       {     
              SCLK=0;
              temp=addr;
              DIO=(bit)(temp&0x01);//每次传输低字节
              addr>>= 1;//右移一位
              SCLK=1;//发送数据
       }
      
       for ( i=8; i>0; i-- )
       {     
              SCLK=0;
              temp=dat;
              DIO=(bit)(temp&0x01);         
              dat>>=1;                  
              SCLK=1;
       }
              CE=0;         
}
uchar Read1302 (uchar addr )//数据读取子程序
{
       uchar i,temp,dat1,dat2;            
       CE=1;
       for ( i=8; i>0; i-- ) //发送地址                      //循环8次移位
       {     
              SCLK=0;
              temp=addr;
              DIO=(bit)(temp&0x01);//每次传输低字节
              addr>>=1;//右移一位
              SCLK=1; //读取数据
       }
      
       for ( i=8;i>0;i--)
       {
              ACC_7=DIO;
              SCLK=1;//注意时序
              ACC>>=1;
              SCLK=0;
       }     
       CE=0;
       dat1=ACC;
       dat2=dat1/16;         //数据进制转换
       dat1=dat1%16;        //十六进制转十进制
       dat1=dat1+dat2*10;
       return (dat1);
}
void Initial( )//初始化DS1302   
{  
       Write1302(WRITE_PROTECT,0X00);          //禁止写保护
       Write1302(WRITE_SECOND,0x30);          //秒位初始化
       Write1302(WRITE_MINUTE,0x59);         //分钟初始化
       Write1302(WRITE_HOUR,0x23);          //小时初始化
       Write1302(WRITE_PROTECT,0x80);      //允许写保护
}

void xsxz()//显示选择
{
   if (fun==0)
   smgxs(shi,fen,tmp());
   if (fun==1)
   smgxs(shi,fen,00);
   if (fun==2)
   smgxs(lshi,lfen,flag);
}
void naozhong ( )
{
   if((shi==lshi)&&(fen==lfen)&&(flag1==1))
   fm=0;
}  
void read_key( )
{
  uchar aa,bb,cc,dd;
  static char key_state=0;
  switch (key_state)
{
  case key_state_0:  // 按键初始态
  if (!key_1||!key_2||!key_3||!key_4)
  key_state=key_state_1;// 键被按下,状态转换到键确认态
  break;
  case key_state_1: // 按键确认态
  if(!key_1||!key_2||!key_3||!key_4)
{
    if(!key_1)//功能键.0:时钟运行1:时钟调整2:闹钟调整
{
    fun++;
    if(fun==3)
    fun=0;
          }
    if(!key_2)//时分切换键.0:分钟调整1:小时调整2:闹钟开关设置
    {
     s2a++;
     if(s2a==3)
     s2a=0;
}
    if(!key_3)//向上调整键
{
    if((fun==1)&&(s2a==0))//时钟分加
    {
     fen++;
     if(fen==60)
     fen=0;
                 }
     if((fun==1)&&(s2a==1))//时钟时加
     {
      shi++;
      if(shi==24)
      shi=0;
             }
      if((fun==2)&&(s2a==0))//闹钟分加
       {
        lfen++;
        if(lfen==60)
        lfen=0;
                }
        if((fun==2)&&(s2a==1))//闹钟时加
         {
          lshi++;
          if(lshi==24)
          lshi=0;
                   }
          if((fun==2)&&(s2a==2))//闹钟开关
           {
             flag=!flag;
             flag1=1;
                           }
                                      }
    if(!key_4)//向下调整键
    {
      if((fun==1)&&(s2a==0))//时钟分减
    {
      if(fen==0)
      fen=60;
      fen--;
                  }
     if((fun==1)&&(s2a==1))//时钟时减
     {
       if(shi==0)
       shi=24;
       shi--;
                    }
      if((fun==2)&&(s2a==0))//闹钟分减
       {
        if(lfen==0)
        lfen=60;
        lfen--;
                  }
        if((fun==2)&&(s2a==1))//闹钟时减
         {
          if(lshi==0)
          lshi=24;
          lshi--;
                     }
          if(fun==0)
           {
              flag1=0;
              fm=1;
                         }
                                    }
     Write1302(WRITE_PROTECT,0X00);//关写保护
     aa=fen/10;//进制转换
     bb=fen%10;
     aa<<=4;
     fen=aa+bb;
     Write1302(WRITE_MINUTE,fen);//写入分数据
     cc=shi/10;
     dd=shi%10;
     cc<<=4;
     shi=cc+dd;     
     Write1302(WRITE_HOUR,shi);//写入时数据
     Write1302(WRITE_PROTECT,0x80);//开写保护            
     key_state=key_state_2;// 状态转换到键释放态 ;       
}
  else
  key_state=key_state_0;// 按键已抬起,转换到按键初始态
  break;
  case key_state_2:
  if(key_1&&key_2&&key_3&&key_4)
  key_state=key_state_0;//按键已释放,转换到按键初始态
  break;   
}     
}
void timer0() interrupt 1//定时器0中断程序
{
    TH0=0xD8;//装初值
    TL0=0xF0;//装初值
    read_key();
                  }
                    
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
10条回答
kentzhtao_top
1楼-- · 2020-02-01 17:26
我之前也遇到过这种情况,原因是最后一个数码管没有关闭位选(最后一个数码管要关闭)
破破破东风
2楼-- · 2020-02-01 19:01
个人愚见 最后一位写进数码管后,后面的程序执行也需要时间 相当于最后一位的延时,即最后一位的延时比其他位长
eaglelpx
3楼-- · 2020-02-02 00:30
感觉你这个动态显示很有问题,用switch  case吧
byrin219
4楼-- · 2020-02-02 02:27
 精彩回答 2  元偷偷看……
wsy2012
5楼-- · 2020-02-02 03:45
点亮时间不同
czdavid
6楼-- · 2020-02-02 06:37
为啥不把显示放中断,Switch   case  定时刷新呢?这样每个数码管的刷新频率就一样了。

一周热门 更多>