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

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)
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
5条回答
millwood0
2020-02-09 22:04
"怎么没人理哟??"

maybe because you have made it difficult for others to help you?

You can make it easier for others to help by posting your mplab project + source code + sim files so people can play with it and tell you where you might have made a mistake.

for starters, you should separate the pieces and first try to see if your lcd portion is working. Then you can try to see if the transfer of value from the 8563 to your lcd display routine is correct, for example, by forcing the 8563 to return a given value and see if you can display that on the lcd, etc.

common sense, you know.

一周热门 更多>