大家帮忙看一下时间不能正常显示

2020-02-09 11:43发布

这是我写的一个程序,附上原理图。需要实现的是PIC16F72模拟I2C,通过实时芯片PCF8563LCD实时显示时间。结果是LCD能显示初始化,但用PROTUES仿真显示时间的时候无论怎么设置初始化的时间上排(年月日)一直是2000-01-01,下排一直是00:00:00,并且时间不走(也就是时钟不能正常初始化并且不走)         大家帮我看看错在哪里?    不知道是I2C有问题  还是PCF8563本身出错了??   请大家多多指教  谢谢了呀
#include<pic.h>
//#include <htc.h>
#include <pic1672.h>
//#include <time.h>
__CONFIG(0x3FF2);           //芯片配置字:看门狗关,上电延时  开,低电压复位开,不加密,4M晶体HX振荡

//定义接口                                               
#define E   RC6
#define RW  RC7
#define RS  RC5
#define uchar unsigned char
#define uint  unsigned int
#define SCL  TRISA3
#define SDA  TRISA1  //I2C
//#define up RC1
//#define down RC2
//#define set RC3       //按键
#define     CLOCK_DEVNO      0xA2    //8563地址
#define            CLOCK_REG             2                //8563内部时间寄存器位置

const uchar wlcome[16]={" welcome! "};
const uchar    Enter[16]={" Enter"};
uchar timedata[7]={0x01,0x08,0x00,0x00,0x02,0x10,0x10};   //预设时间设置表 2010年,1月6日,星期1,12点
bit ack;
bit ErrorBit;   //I2C 错误返回值
uchar tpmtdata = 36;      //温度设置值预设36度
uchar tep;
uchar hour,min,sec,date,week,month, year;
uchar  dis_buf1[16]={"  2010-11-24    "};  //lcd上排显示缓冲区
uchar  dis_buf2[16]={"  85'C  12:12:12"};       //lcd下排显示缓冲区                              
//****************************************************
//                 DELAY
//******************************************************

void delay_1ms(void)                 //1ms延时函数
  {
   uint i;
   for (i=0;i<1000;i++);
  }
  
void delay_nms(uint n)       //N ms延时函数
  {
   uint i=0;
   for (i=0;i<n;i++);
   delay_1ms();
  }
void delay_1us(void)                 //1us延时函数
  {
   asm("nop");
  }

void delay_nus(uint n)       //N us延时函数
  {
   uint i=0;
   for (i=0;i<n;i++);
   delay_1us();
  }

//查询LCD是否忙
void Busy ()
{  
   uchar FLAG;
   FLAG=0x00;
   RS=0;
   RW=1;
    while(FLAG&0x80==0x80)
    {
      PORTB =0xFF;                 //设置B口为输入
      
       E=1;                        //E=1
       FLAG=PORTB;
       E=0;
    }
}
///////////////////////LCD//////////////////////////
//LCD写命令函数

void LCD_write_cmd(uchar command)
{

    Busy();                    //判断液晶是否为忙                  
    RW=0;                       
    RS=0;                 //为0写命令,为1写数据
    PORTB=command;
    E=1;
    E=0;                                
}
//LCD写数据函数

void LCD_write_data(uchar data)
{

    Busy();                    //判断液晶是否为忙                  
    RW=0;                       
    RS=1;                 //为0写命令,为1写数据
    PORTB=data;
    E=1;
    E=0;                                
}
//LCD写字符串

void LCD_write_s(uchar *s)   
{   
while(*s>0)   
{
  LCD_write_data(*s);   
  s++;   
}   
}  

//LCD写入显示数据函数
void disp_lcd(uchar addr,uchar *temp1)
{
uchar i;
LCD_write_cmd(addr);
delay_nms(1500);
for(i=0;i<16;i++)
{
  LCD_write_data(temp1);
  delay_nms(1500);
}
}
//LCD初始化函数
void LCD_init(void)
{
char i;
for(i=3;i>0;i--)
{
  PORTB=0x30;
  RS=0;
  RW=0;
  E=1;
  E=0;
  delay_nms(1500);
  }
  PORTB=0x38;
  RS=0;
  RW=0;
  E=1;
  E=0;
  delay_nms(1500);
}
//LCD显示器复位函数

void LCD_reset(void)
{
  delay_nms(150);           //启动时必须的延时
  LCD_write_cmd(0x38);   //双行显示,字型使用5*7点阵
  delay_nms(1500);
  LCD_write_cmd(0x0e);   //出现光标,不闪烁
  delay_nms(1500);
  LCD_write_cmd(0x06);   //每次向右移一位,显示屏不移动
  delay_nms(1500);
  LCD_write_cmd(0x01);  //清除LCD显示屏幕
  delay_nms(1500);
}

/**********************************************
                  I2C
**************************************************/
void I2C_Init()
{
SCL = 1;
delay_nus(5) ;
SDA = 1;
delay_nus(5) ;

}

void I2C_Start(void)
{
   SDA=1;            /*发送起始条件的数据信号*/
   delay_nus(5) ;
   SCL=1;
   delay_nus(5) ;  /*起始条件建立时间大于4.7us,延时*/
   SDA=0;     /*发送起始信号*/
   delay_nus(5) ;     /* 起始条件锁定时间大于4μs*/
   SCL=0;     /*钳住I2C总线,准备发送或接收数据 */
   delay_nus(5) ;
}

void I2C_Stop(void)
{
   SDA=0;    /*发送结束条件的数据信号*/
   delay_nus(5);     /*发送结束条件的时钟信号*/
   SCL=1;    /*结束条件建立时间大于4us*/
   delay_nus(5);
   SDA=1;    /*发送I2C总线结束信号*/
   delay_nus(8);
}
//应答信号,在第九个时钟周期把SDA拉低表示应答信号
void I2C_Ack(void)
{
        uchar i;
        SCL=1;                 
                delay_nus(5);
        SDA=1;
                delay_nus(5);
        if((SDA==1)&&(i<100))
        i++;
        SCL=0;                 
                delay_nus(5);
}
//没有应答信号,
void I2C_NoAck(void)
{
        SDA=1;                //起始信号//
        delay_nus(5);
        SCL=1;                 
        delay_nus(5);
        SCL=0;                 
        delay_nus(5);
}

bit I2C_TestAck() //应答位检测子函数
{
     SCL=1;
     delay_nus(5);
     ErrorBit=SDA;          //SDA=1非应答
     SCL=0;
     delay_nus(5);  
     return(ErrorBit);   
}

void I2C_Write8Bit(uchar input) //发送一个字节子函数   
{
    uchar i;
     for(i=0;i<8;i++)
      {
         if((input<<i) & 0x80)
             SDA=1;              //判断发送位
           else SDA=0;
            SCL=1;
           delay_nus(5);
           SCL=0;
         delay_nus(8);
      }
    //SSPBUF=input;
   // do{;}
   //while (SSPIF==0);
   //SSPIF=0;
    }

////24CO2B写

void I2C_Write(uchar *buffer,uint address,uchar number,uchar devicNO )//参数:buffer为写入数据缓冲区指针,address为写入数据地址, len为写入数据长度,devicNO为I2C设备的访问地址
{
        I2C_Start();
        I2C_Write8Bit(devicNO);
        I2C_TestAck();
        I2C_Write8Bit(address);
        I2C_TestAck();
        for(;number!=0;number--)
{   
I2C_Write8Bit(*buffer);   
I2C_TestAck();  
buffer++;   
}
I2C_Ack(); //应答  
I2C_Stop();   
delay_nms(5);
}

//
uchar I2C_Read8Bit()    //接收1个字节子函数
{
   uchar temp,rbyte=0;
     SCL=0;       //读入数据
    delay_nus(5);
    SDA=1;
    delay_nus(5);
   for(temp=8;temp!=0;temp--)
     {
       SCL=1;      
       delay_nus(5);
       rbyte = ( rbyte << 1 );
       rbyte = ( rbyte | ((uchar)(SDA)) );
       SCL=0;
       delay_nus(5);
      }
    delay_nus(8);
   return(rbyte);
//SDA=0;
//do{;}
//while(SSPIF==0);
  // SSPIF=0;
  // return SSPBUF;
   
}

//////24CO2B读

void I2C_Read(uchar *buffer,uint address,uchar bytes,uchar devicNO)//buffer为读出数据缓冲区指针,address为读数据起始地址, len为读出数据长度,devicNO为I2C设备的访问地址
{
   I2C_Start();
   I2C_Write8Bit(devicNO);
   I2C_TestAck();
   I2C_Write8Bit(address);
   I2C_TestAck();
   I2C_Start();
   I2C_Write8Bit(devicNO+1);
   I2C_TestAck();
   while(bytes!=1)
{   
*buffer=I2C_Read8Bit();   
I2C_Ack(); //应答  
buffer++;   
bytes--;   
}   
  I2C_Stop();
}
////////////////////////////////////////8563/////////////////////////////////
//BCD到16进制

uchar bcd_convert_hex(uchar bcd_data)
{
   uchar shu;
   shu=((bcd_data&0xF0>>4)&0x0F)*10+(bcd_data&0x0F);
   return (shu);

}


//16进制到BCD
uchar hex_convert_bcd(uchar hex_data)
{
   uchar temp;
   uchar bcd_data;
   temp=hex_data%100;
   bcd_data=(temp/10<<4)|(temp%10);
   return bcd_data;
}

//8563写
void Write8563(uchar CFG_add,uchar CFG_data)
{         
I2C_Start();               // 启动I2C
I2C_Write8Bit(0xA2);     // 发送器件所在地址
I2C_Ack();         //调用应答信号
I2C_Write8Bit(CFG_add);       // 发送寄存器地址
I2C_Ack();
I2C_Write8Bit(CFG_data);    // 发送寄存器数据
I2C_Ack();
I2C_Stop();         // 全部发完则停止
delay_nus(5);
}
//8563读
uchar Read8563(uchar CFG_add)
{
uchar  receive_da=0;
I2C_Start();
I2C_Write8Bit(0xA2);  //器件写地址
I2C_Ack();
I2C_Write8Bit(CFG_add);  //写寄存器地址
I2C_Ack();
I2C_Start();
I2C_Write8Bit(0xA3);  //器件读地址
I2C_Ack();
receive_da=I2C_Read8Bit();
I2C_Stop();
return(receive_da);
}

//写时间
void pcf8563_rewrite_time(uchar *ptr)
{                  
  uchar i;
  uchar timeBCD[7];
  for(i=0;i<7;i++)
   {
    timeBCD=hex_convert_bcd(ptr);
   
   }
  Write8563(0x00,0x20);   // PCF8563时钟芯停止运行
  I2C_Write(timeBCD,0x02,7,0xA2);  // 将设置时间写入PCF8563
  
  Write8563(0x00,0x00);   // PCF8563时钟芯开始运行
  Write8563(0x01,0x11);
}
//读时间
void pcf8563_get_time()
  {
  sec=bcd_convert_hex((Read8563(0x02))&0x7F);   //
   if(sec>=60){sec=0;}   
  min=bcd_convert_hex((Read8563(0x03))&0x7F);   // 分
   if(min>=60){min=0;}
  hour=bcd_convert_hex((Read8563(0x04))&0x3F);   // 小时
   if(hour>=24){hour=0;}
  date=bcd_convert_hex((Read8563(0x05))&0x3F);   // 日
   if( date>=32){ date=1;}
  week=Read8563(0x06);
   if(week>6){week=0;}
  month=bcd_convert_hex((Read8563(0x07))&0x1F);   // 月
   if(month>=13){month=1;}
  year=bcd_convert_hex(Read8563(0x08));       // 年
   if(year>99){year=0;}
}


//更新显示缓冲区
void update_disbuf(uchar t2[])
{

dis_buf1[4]=year/10+0x30 ;
dis_buf1[5]=year%10+0x30 ;
dis_buf1[7]=month/10+0x30 ;
dis_buf1[8]=month%10+0x30 ;
dis_buf1[10]=date/10+0x30 ;
dis_buf1[11]=date%10+0x30 ;
dis_buf2[2]=t2[0] ;   //显示温度
dis_buf2[3]=t2[1] ;
dis_buf2[8]=hour/10+0x30 ;
dis_buf2[9]=hour%10+0x30 ;
dis_buf2[11]=min/10+0x30 ;
dis_buf2[12]=min%10+0x30 ;
dis_buf2[14]=sec/10+0x30 ;
dis_buf2[15]=sec%10+0x30 ;
}
//显示处理程序
void pro_display()
{
disp_lcd(0x80,dis_buf1);
disp_lcd(0xc0,dis_buf2);
}

//初始化8563
void pcf8563_star(void)
{
  I2C_Start();
  Write8563(0x00,0x00);   // PCF8563时钟芯开始运行
  Write8563(0x01,0x11);
  Write8563(0x0D,0x10);
pcf8563_rewrite_time(timedata);
  
}



//////////////////////////单片机上电启动///////////////////////
void Start()

{
  
  TRISB=0x00;
  TRISC=0x00;
  PORTC=0X00;
  PORTA=0x00;
  TRISA=0x02;
  INTCON=0x00;
  PCON=0x01;
  POR=1;  
  
}

//////////////////////////初始化////////////////////////////////
void Initialize()
{
  //ADIE=1;        //使能A/D转换中断
  
  SSPCON = 0x0E;            
  SSPSTAT =0x26;              //初始化寄存器
  GIE=0;                     //关闭中断
  
  SSPEN=1;                    //SSP标志使能
// SSPADD=0x02;
  pcf8563_star();
  LCD_init();              //LCD初始化
  LCD_reset();            //复位
disp_lcd(0x80,wlcome);
  disp_lcd(0xc0,Enter);
// delay_nus(3000);                //保持3秒显示内容

}


///////////////////////////////主程序///////////////////////////
void main()
{
  
  I2C_Init();
// tep=tpmtdata;
  Start();              //调用启动程序
  Initialize();         //调用初始化程序

while(1)
{
pcf8563_get_time();
update_disbuf("20");
  pro_display();
// if(tpmtdata>tep)                        //温度上限判断
  // {
    // PORTA=0x00;                  //电机关闭
     //delay_nus(1000);                    //延时,使检测不至太频繁
   //}
   //else if(tpmtdata<tep-0x66)             //温度下限判断
    //{           
      //PORTA=0x04;                 //电机开启
      //delay_nus(10);
      //ADON =1;                    //启动下一次转换
   
     //}                                             
  }
}

原理图ourdev_535522.pdf(文件大小:420K) (原文件名:PCB_Project1.pdf)
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。