nonez 发表于 2011-9-20 12:55:50

【已解决】STC12C5608+12864(串)+DS1302显示时钟 出现秒影响分的问题,

此问题并非程序所引起,在DS1302 IO脚上拉一个10k电阻后恢复正常。
与此问题类似的时分秒显示问号 同样可以解决

=============================
在12864上显示年月日时分秒,出现了如下问题
秒读数跳变时,分的读数会变成和秒相同的数一起跳变,跳变间隙中分读数偶尔恢复正常.
我把分读数输出到屏的语句中的寄存器改成日期或者小时的寄存器就没有那种跳变.
本人新手调了一天了 还是这样子.求各位指点.
源程序:

#include <REG52.H>
#define uint unsigned int
#define uchar unsigned char
/*12864液晶定义***********************************/
sbit SID = P3^3;       //串行数据
sbit SCLK = P3^4;      //串行同步时钟
/*DS1302定义**************************************/
sbit DS1302_IO =P1^0;
sbit DS1302_CLK=P3^7;
sbit DS1302_RST=P1^1;
/*按键及NTC热敏电阻定义***************************/
sbit key1=P1^6;
sbit key2=P1^7;
sbit key3=P3^0;
sbit key4=P3^1;
/*累加器各位定义************************************/
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
/*全局变量及数组定义*******************************/
uchar code table[]="电子钟";
uchar yy,mo,dd,xq,hh,min,ss,d,num;//定义时间映射全局变量(专用寄存器)
/*函数声明****************************************/
void delayms(uint z);
void SendByte(uchar Dbyte);
uchar ReceiveByte(void);
void Lcd_WriteCmd(uchar Cbyte );
void Lcd_WriteData(uchar Dbyte );
void Lcd_Init(void);
void lcd_display();
void Init_1302(void);
void DS1302InputByte(uchar d);
uchar DS1302OutputByte(void);
void Write1302(uchar ucAddr, uchar ucDa);
uchar Read1302(uchar ucAddr);
void Lcd_w_min(void);
void Lcd_w_hh(void);
void Lcd_w_ss(void);
void Lcd_w_yy(void);
void Lcd_w_dd(void);
void Lcd_w_mo(void);
void Lcd_WriteString(uchar *str);
/*主函数******************************************/
void main()
{       
       Lcd_Init();
        Init_1302();
       delayms(100);



        while(1)
   {
       
       lcd_display();
       }       
}
/*延时函数****************************************/
void delayms(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
/****LCD显示函数**********************************/
void lcd_display()
{
yy=0x00;mo=0x00;dd=0x00;xq=0x00;hh=0x00;min=0x00;ss=0x00;
Lcd_WriteCmd(0x80);
num=0;
        while(table!='\0')
                {
                        Lcd_WriteData(table);
                        num++;
                        delayms(100);
                }
                  
                  
Lcd_w_yy();
Lcd_w_mo();
Lcd_w_dd();
Lcd_w_hh();
Lcd_w_min();
Lcd_w_ss();

delayms(100);
       
}
/*串行发送一个字节*******************************/
void SendByte(uchar Dbyte)
{
   uchar i;
   for(i=0;i<8;i++)
   {
         SCLK = 0;
         Dbyte=Dbyte<<1;      //左移一位
         SID = CY;            //移出的位给SID
         SCLK = 1;
         SCLK = 0;
   }
}
/*****串行接收一个字节***************************/
uchar ReceiveByte(void)
{
   uchar i,temp1,temp2;
   temp1 = 0;
   temp2 = 0;
   for(i=0;i<8;i++)
   {
         temp1=temp1<<1;
         SCLK = 0;
         SCLK = 1;            
         SCLK = 0;
         if(SID)
                  temp1++;
   }
   for(i=0;i<8;i++)
   {
         temp2=temp2<<1;
         SCLK = 0;
         SCLK = 1;
         SCLK = 0;
         if(SID)
                   temp2++;
   }
   return ((0xf0&temp1)+(0x0f&temp2));
}
/*检测LCD忙状态**************************/
void CheckBusy( void )
{
   do   SendByte(0xfc);         //11111,RW(1),RS(0),0
   while(0x80&ReceiveByte());       //BF(.7)=1 Busy
}
/*****写指令******************************************/
void Lcd_WriteCmd(uchar Cbyte )
{
   //CS = 1;
   CheckBusy();
   SendByte(0xf8);            //11111,RW(0),RS(0),0
   SendByte(0xf0&Cbyte);      //高四位
   SendByte(0xf0&Cbyte<<4);   //低四位(先执行<<)
    // CS = 0;
}
/*****写数据*******************************************/
void Lcd_WriteData(uchar Dbyte )
{
   CheckBusy();
   SendByte(0xfa);            //11111,RW(0),RS(1),0
   SendByte(0xf0&Dbyte);      //高四位
   SendByte(0xf0&Dbyte<<4);   //低四位(先执行<<)

}
/***LCD12864初始化*************************************/
void Lcd_Init(void)

{
    Lcd_WriteCmd(0x30);      //选择基本指令集
delayms(1);
   Lcd_WriteCmd(0x0c);          //开显示(无游标、不反白)
delayms(1);
    Lcd_WriteCmd(0x01);          //清除显示,并且设定地址指针为00H
delayms(20);
}

/*向LCD中填写 年 数据****************************************/
void Lcd_w_yy(void)
{
                yy = Read1302(0x8d);
                Lcd_WriteCmd(0x90);
                Lcd_WriteString("20");
                Lcd_WriteCmd(0x91);
                Lcd_WriteData((yy/16)+0x30);       
                Lcd_WriteData(yy%16+0x30);
                Lcd_WriteCmd(0x92);
                Lcd_WriteString("年");   
   
}
/***向LCD中填写 月 数据**************************************************************************/

void Lcd_w_mo(void)
{
                mo = Read1302(0x89);
                Lcd_WriteCmd(0x93);
                        if(mo/16 != 0){Lcd_WriteData((mo/16)+0x30);}        //十位消隐
                        else{Lcd_WriteData(0x20);}//同上                       
                Lcd_WriteData(mo%16+0x30);
                Lcd_WriteCmd(0x94);
                Lcd_WriteString("月");
}       

/*向LCD中填写 日 数据******************************************************/
void Lcd_w_dd(void){
                dd = Read1302(0x87);
                Lcd_WriteCmd(0x95);
                        if(dd/16 != 0){Lcd_WriteData((dd/16)+0x30);}        //十位消隐
                        else{Lcd_WriteData(0x20);}//同上       
                Lcd_WriteData(dd%16+0x30);
                Lcd_WriteCmd(0x96);
                Lcd_WriteString("日");
                               
}
/***向LCD中填写 小时 数据**************************************************************************/

             void Lcd_w_hh(void)
       {
                hh = Read1302(0x85);
                                delayms(100);
                Lcd_WriteCmd(0x88);
                Lcd_WriteData((hh/16)+0x30);
                Lcd_WriteData(hh%16+0x30);
                               
        }
/***向LCD中填写 分钟 数据********************************************************/
void Lcd_w_min(void)
{
if(Read1302(0x83) != min)
         {               
                min = Read1302(0x83);
               
              }
       
    min = Read1302(0x83);
        Lcd_WriteCmd(0x89);       
        Lcd_WriteData(0x3a);          //":"
        Lcd_WriteData((min/16)+0x30);
        Lcd_WriteData(min%16+0x30);
               
}
/*向LCD中填写 秒 数据*************************************************************/
void Lcd_w_ss(void)
{                Lcd_w_min();
                Lcd_WriteData(0x3a);       //"."
                ss = Read1302(0x81);        //更新数据
                Lcd_WriteCmd(0x8b);                //秒值在LCM上的写入位置
                Lcd_WriteData((ss/16)+0x30);        //写十位               
                Lcd_WriteData(ss%16+0x30);        //写个位
                Lcd_w_min();
               
       

}       

/***向LCD发送一个字符串,长度64字符之内。********************************************/
//应用:LCM_WriteString("您好!");
void Lcd_WriteString(uchar *str)
{
                while(*str != '\0')
       {
                        Lcd_WriteData(*str++);
      }
                *str = 0;
}

/***设置1302的初始时间**************************************************************************/

void Init_1302(void)//
{
      Write1302(0x8e,0x00);//允许写操作
        Write1302(0x8c,0x11);//年
        Write1302(0x8a,0x02);//星期
        Write1302(0x88,0x09);//月
        Write1302(0x86,0x20);//日
        Write1302(0x84,0x07);//小时
        Write1302(0x82,0x25);//分钟
        Write1302(0x80,0x59);//秒       
        Write1302(0x8e,0x80);//禁止写操作
   }

void DS1302InputByte(uchar d)         //实时时钟写入一字节(内部函数)
{
    uchar i;
    ACC = d;
    for(i=8; i>0; i--)
    {
      DS1302_IO = ACC0;                 //相当于汇编中的 RRC
      DS1302_CLK = 1;
      DS1302_CLK = 0;
      ACC = ACC >> 1;
    }
}

uchar DS1302OutputByte(void)         //实时时钟读取一字节(内部函数)
{
    uchar i;
    for(i=8; i>0; i--)
    {
      ACC = ACC >>1;                                 //相当于汇编中的 RRC
      ACC7 = DS1302_IO;
      DS1302_CLK = 1;
      DS1302_CLK = 0;
    }
    return(ACC);
}

void Write1302(uchar ucAddr, uchar ucDa)        //ucAddr: DS1302地址, ucData: 要写的数据
{
    DS1302_RST = 0;
    DS1302_CLK = 0;
    DS1302_RST = 1;
    DS1302InputByte(ucAddr);               // 地址,命令
    DS1302InputByte(ucDa);               // 写1Byte数据
    DS1302_CLK = 1;
    DS1302_RST = 0;
}

uchar Read1302(uchar ucAddr)        //读取DS1302某地址的数据
{
    uchar ucData;
    DS1302_RST = 0;
    DS1302_CLK = 0;
    DS1302_RST = 1;
    DS1302InputByte(ucAddr|0x01);      // 地址,命令
    ucData = DS1302OutputByte();         // 读1Byte数据
    DS1302_CLK = 1;
    DS1302_RST = 0;
    return(ucData);
}

nonez 发表于 2011-9-20 20:55:26

麻烦知道的指点一下 谢谢!!
页: [1]
查看完整版本: 【已解决】STC12C5608+12864(串)+DS1302显示时钟 出现秒影响分的问题,