打印

【求助】万年历显示时间不对

[复制链接]
2082|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sdu_yqc|  楼主 | 2011-4-29 18:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用avr单片机、1302和12864,用ICCAVR编译。代码如下,求指教。运行后只显示2000/00/00 00:00:00 Week 0,连初始化函数 都没运行,为什么啊?
#include<iom16v.h>
#include<macros.h>


#define uchar unsigned char
#define uint unsigned int

#define DB PORTB
#define EN_CLR PORTD &= ~(1 << PD7)
#define EN_SET PORTD |= (1 << PD7)
#define RW_CLR PORTD &= ~(1 << PD6)
#define RW_SET PORTD |= (1 << PD6)
#define RS_CLR PORTD &= ~(1 << PD5)
#define RS_SET PORTD |= (1 << PD5)

//下面的都是写寄存器,要变成读只需加1,即或上0x01
#define SECOND 0x80                //秒
#define MINUTE 0x82                //分鍾
#define HOUR   0x84                //小時
#define DAY           0x86                //天
#define MONTH  0x88                //月
#define WEEK   0x8a                //星期
#define YEAR   0x8c                //年
#define WRITE_PROTECT 0x8e  //写保护

#define SCLK_CLR PORTD &= ~(1 << PD0)
#define SCLK_SET PORTD |= (1 << PD0)
#define IO_CLR PORTD &= ~(1 << PD1)
#define IO_SET PORTD |= (1 << PD1)
#define RST_SET PORTD &= ~(1 << PD2)  //因为复位键是低电平有效
#define RST_CLR PORTD |= (1 << PD2)
char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year;  //秒,分,时到日,月,年位闪的计数
uchar week_value[2];
typedef struct systime
{
        unsigned char Second;
        unsigned char Minute;
        unsigned char Hour;
        unsigned char Week;
        unsigned char Day;
        unsigned char Month;
        unsigned char Year;
        unsigned char DateString[11];
        unsigned char TimeString[9];
}SYSTIME;

SYSTIME CurrentTime;   //系统日期

/*12864函数*/
void delay_ms(uint m) //延时程序ms ,频率为8MHz时
{ uint i,j;
for(i=0;i<m;i++)
for(j=0;j<1141;j++);
}

void delay_us(uint u) //延时程序us
{ uint i,j;
for(i=0;i<u;i++)
for(j=0;j<141;j++);
}

uchar check_busy(void)
{
    char r;
    DDRB = 0x00;       //端口B设为输入方式
    EN_CLR;RS_CLR;RW_SET;     //E=0(致能),RS=0(命令),RW=1(读)
    delay_us(2);       //液晶延时子程序
    EN_SET;
    delay_us(2);       //液晶延时子程序
    r = PINB & 0x80;   //读取lcd_data第八位
    EN_CLR;
    DDRB=0xff;         //端口B设为输出方式
    return r;          //读取结果返回
}

void write_com(uchar cmdcode)  //写指令
{
  while(check_busy());
  RS_CLR;       //指令
  RW_CLR;      //写
  EN_CLR;
  delay_us(2);//delay_us(1);
  EN_SET;
  DB=cmdcode;
  delay_us(2);//delay_us(1);delay_us(1);
  EN_CLR;
}

void write_data(uchar datacode)  //写数据
{
  while(check_busy());
  RS_SET;
  RW_CLR;
  EN_CLR;
  delay_us(2);//delay_us(1);
  EN_SET;
  DB=datacode;
  delay_us(2);//delay_us(1);delay_us(1);
  EN_CLR;
}

uchar read_data(void)   //读数据
{
  uchar dat;
  while(check_busy());
  RS_SET;
  RW_SET;
  EN_CLR;
  delay_us(2);
  EN_SET;
  dat=DB;
  delay_us(2);
  EN_CLR;
  return dat;
}

void Initial_LCD(void)
{     
    write_com(0x38); //8位并行口,基本指令集
    write_com(0x38);
    write_com(0x08); //令显示器off
    write_com(0x01); //清除显示器
    write_com(0x06); //令LCD每接收到1Byte数据后,AC自动加1
    write_com(0x0E); //令光标,0x0c=不显示,0x0d=显示闪动.
}

void Location_XY(uchar x,uchar y)
{
  switch(y)   //y取值0~3
  {
    case 0:
      y=0x80;break;
    case 1:
      y=0x90;break;
    case 2:
     y=0x88;break;
    case 3:
      y=0x98;break;
    default:
      y=0x80;
  }
  x=x&0x07;   //x取值0~7
  write_com(x+y);
}

void Write_String(unsigned char *asc)
{
  while((*asc) != 0)   //判断字是否结束
    {
        write_data(*asc); //向lcd写入字符串
        asc++;           //移下一个字符
    }
}

void Write_String_atXY(uchar x,uchar y,uchar string[])
{
  Location_XY(x,y);
  Write_String(string);
}


/*ds1302函数*/

void DS1302_Write(uchar D)  //向1302写入一个字节
{   
    uchar i;       
    DDRD|=0X07;       
        for(i=0;i<8;i++)
        {       
                if(D&0x01) IO_SET;
                  else  IO_CLR;//DS1302_IO=D&0x01; //取最低位
                SCLK_SET; //DS1302_SCLK=1;
                SCLK_CLR; //DS1302_SCLK=0;
                D=D>>1;                               
        }       
}

uchar DS1302_Read(void)  //向1302读取一个字节
{   
   
        uchar TempDat=0,i,t;
        DDRD&=~BIT(1);  //1302的IO口设为输入
        t=PIND;
        t&=BIT(1);
        for(i=0;i<8;i++)
        {       
                TempDat>>=1;   //移位,以便下次存放读出的数据       
               
                if(t) TempDat=TempDat|0x80;  //如果IO口为1,则把1存到TempDat的最高位
                SCLK_SET; //DS1302_SCLK=1;
                SCLK_CLR; //DS1302_SCLK=0;
                       
        }       
    return TempDat;
}

void WDS1302(uchar ucAddr, uchar ucDat)          //写1302寄存器
{   
    RST_SET; //DS1302_RST = 0;   //复位
    SCLK_CLR;  //DS1302_SCLK = 0;
    RST_CLR;//DS1302_RST = 1;   //开始读写
    DS1302_Write(ucAddr);               // 地址,命令
    DS1302_Write(ucDat);               // 写1Byte数据
    SCLK_SET; //DS1302_SCLK = 1;  //SCLK上升沿
    RST_SET; //DS1302_RST = 0;
}

uchar RDS1302(uchar ucAddr)   //读1302寄存器内容
{
    uchar ucDat;
    RST_SET; //DS1302_RST = 0;
    SCLK_CLR;  //DS1302_SCLK = 0;
    RST_CLR; //DS1302_RST = 1;
    DS1302_Write(ucAddr);               // 地址,命令
    ucDat=DS1302_Read();
        SCLK_SET; //DS1302_SCLK = 1;
    RST_SET; //DS1302_RST = 0;
        return ucDat;
}


/*void GetTime(SYSTIME *sys)
{
        uchar uiTempDat;
        uiTempDat=RDS1302(YEAR|0x01);        //读取年                  
        (*sys).Year=(uiTempDat>>4)*10+(uiTempDat&0x0f);
       
        uiTempDat=RDS1302(MONTH|0x01);   //读取月
        (*sys).Month=((uiTempDat&0x1f)>>4)*10+(uiTempDat&0x0f);       

        uiTempDat=RDS1302(DAY|0x01);   //读取日
        (*sys).Day=((uiTempDat&0x3f)>>4)*10+(uiTempDat&0x0f);

        uiTempDat=RDS1302(HOUR|0x01);
        (*sys).Hour=((uiTempDat&0x3f)>>4)*10+(uiTempDat&0x0f);

        uiTempDat=RDS1302(MINUTE|0x01);
        sys->Minute=((uiTempDat&0x7f)>>4)*10+(uiTempDat&0x0f);

        uiTempDat=RDS1302(SECOND|0x01);
        sys->Second=((uiTempDat&0x7f)>>4)*10+(uiTempDat&0x0f);

        uiTempDat=RDS1302(MONTH|0x01);
        (*sys).Month=uiTempDat&0x17;

        uiTempDat=RDS1302(WEEK|0x01);
        sys->Week=uiTempDat&0x07;
}
*/

void GetTime(SYSTIME *Time)  //获取时钟芯片的时钟数据到自定义的结构型数组
{
        unsigned char ReadValue;
        ReadValue = RDS1302(SECOND);
        Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
        ReadValue = RDS1302(MINUTE);
        Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
        ReadValue = RDS1302(HOUR);
        Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
        ReadValue = RDS1302(DAY);
        Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);       
        ReadValue = RDS1302(WEEK);
        Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
        ReadValue = RDS1302(MONTH);
        Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
        ReadValue = RDS1302(YEAR);
        Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);       
}

void DateToStr(SYSTIME *Time)    //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
{   if(hide_year<2)                 //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
    {                              
          Time->DateString[0] = '2';
          Time->DateString[1] = '0';         
          Time->DateString[2] = Time->Year/10 + '0';
          Time->DateString[3] = Time->Year%10 + '0';
        }
          else
            {
              Time->DateString[0] = ' ';
              Time->DateString[1] = ' ';                 
              Time->DateString[2] = ' ';
              Time->DateString[3] = ' ';
                }
        Time->DateString[4] = '/';
        if(hide_month<2)
        {
          Time->DateString[5] = Time->Month/10 + '0';
          Time->DateString[6] = Time->Month%10 + '0';
        }
          else
          {
            Time->DateString[5] = ' ';
            Time->DateString[6] = ' ';
          }
        Time->DateString[7] = '/';
        if(hide_day<2)
        {
          Time->DateString[8] = Time->Day/10 + '0';
          Time->DateString[9] = Time->Day%10 + '0';
        }
          else
          {
            Time->DateString[8] = ' ';
            Time->DateString[9] = ' ';            
          }
        if(hide_week<2)
        {
          week_value[0] = Time->Week%10 + '0';  //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
        }
          else
          {
            week_value[0] = ' ';
          }
          week_value[1] = '\0';

        Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符
}

void TimeToStr(SYSTIME *Time)  //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];
{   if(hide_hour<2)
    {
          Time->TimeString[0] = Time->Hour/10 + '0';
          Time->TimeString[1] = Time->Hour%10 + '0';
        }
          else
            {
              Time->TimeString[0] = ' ';
              Time->TimeString[1] = ' ';
                }
        Time->TimeString[2] = ':';
    if(hide_min<2)
        {
          Time->TimeString[3] = Time->Minute/10 + '0';
          Time->TimeString[4] = Time->Minute%10 + '0';
        }
          else
            {
              Time->TimeString[3] = ' ';
              Time->TimeString[4] = ' ';
               }
        Time->TimeString[5] = ':';
    if(hide_sec<2)
    {
          Time->TimeString[6] = Time->Second/10 + '0';
          Time->TimeString[7] = Time->Second%10 + '0';
    }
      else
       {
         Time->TimeString[6] = ' ';
             Time->TimeString[7] = ' ';
       }
        Time->DateString[8] = '\0';
}

void show_time(void)   //液晶显示程序
{
  GetTime(&CurrentTime);  //获取时钟芯片的时间数据
  TimeToStr(&CurrentTime);       //时间数据转换液晶字符
  DateToStr(&CurrentTime);       //日期数据转换液晶字符
  
  Write_String_atXY(0,1,CurrentTime.TimeString);
// Location_XY(0,1);
// write_data(CurrentTime.TimeString); //显示时间
  Write_String_atXY(0,0,CurrentTime.DateString);
// GotoXY(0,0);
// write_data(CurrentTime.DateString); //显示日期
  Write_String_atXY(4,2,week_value);
  Write_String_atXY(0,2,"Week");
  //Location_XY(4,2);
  //write_data(week_value);             //显示星期
  //Location_XY(0,2);
  //write_data("Week");        //在液晶上显示 字母 week
  delay_ms(400);                 //扫描延时
}

void Initial_DS1302(void)   //时钟芯片初始化
{   
        unsigned char Second=RDS1302(SECOND);
        if(Second&0x80)              //判断时钟芯片是否关闭          
    {
        WDS1302(0x8e,0x00); //写入允许
        WDS1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55
        WDS1302(0x88,0x07);
        WDS1302(0x86,0x25);
        WDS1302(0x8a,0x07);
        WDS1302(0x84,0x23);
        WDS1302(0x82,0x59);
        WDS1302(0x80,0x55);
        WDS1302(0x8e,0x80); //禁止写入
        }
}

void  main(void)
{
     DDRB = 0xff;       //端口B设为输出方式
     DDRD = 0xff;       //端口D设为输出方式
         Initial_LCD();
         Initial_DS1302();

        // SetTime(CurrentTime);
        // GUI_Init();

         while(1)         
         {
                show_time();
        //        Time_Set();         //时间设置
         }       
}

相关帖子

沙发
zjy.zz| | 2011-6-18 13:36 | 只看该作者
1302是只读的,读出时分秒,是压缩bcd码好向,我用的ds1307较多,只要读出来了,就是正确的,你把bcd码分离一下,显示就行了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

140

帖子

1

粉丝