⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcf8563.c

📁 pcf8563时钟操作C语言
💻 C
字号:
#include <iom16v.h>
#include <stdio.h>
#include <macros.h>
#include <string.h>

#include "pcf8563.h"
#include "lcd.h"
#include "keyboard.h"

//时钟芯片数据接口PA0
#define DATE_DT_set asm("sbi 0x1B,0")
#define DATE_DT_clr asm("cbi 0x1B,0")
//时钟芯片时钟接口PA1
#define DATE_CLK_set asm("sbi 0x1B,1")
#define DATE_CLK_clr asm("cbi 0x1B,1")
unsigned char old_minute,new_minute;
unsigned char number1[13]=
{
 0x30,  //0
 0x31,   //1
 0x32,  //2
 0x33,  //3
 0x34,  //4
 0x35,  //5
 0x36,  //6
 0x37,   //7
 0x38,  //8
 0x39,  //9
 0x20,  //空格
 0x2E,  //.
 0x3A  //:
};

void delayus(unsigned char i)
{
 while(i)
 i--;
}

// ************************************************ //
// *** This routine will send the I2C Start Bit *** //
// ************************************************ //
void I2C_Start (void)         //I2C发送开始位
{
 DDRA|=0x03;                  //将PA0数据端口(SDA),PA1时钟端口(SCL)设为输出
 DATE_CLK_set;            //将时钟端口(SCL)设为高
 DATE_DT_set;            //将数据端口(SDA)设为高
 delayus(2); 
 DATE_DT_clr;            //将数据端口(SDA)设为低
 delayus(2);
 DATE_DT_set;
}

// *********************************************** //
// *** This routine will send the I2C Stop Bit *** //
// *********************************************** //

void I2C_Stop (void)          //I2C发送停止位
{
 DDRA|=0x03;                  //将PA0数据端口(SDA),PA1时钟端口(SCL)设为输出
 DATE_DT_clr;            //将数据端口(SDA)设为低
 DATE_CLK_set;                //将时钟端口(SCL)设为高
 delayus(2);
 DATE_DT_set;            //将数据端口(SDA)设为高
 delayus(2);
}

// *********************************************************************** //
// *** 发送完毕检查校验位,有校验位返回1,无返回0 *** //
// *********************************************************************** //

unsigned char I2C_Ackn(void)
{
 unsigned char errtime=255;
 //DATE_CLK_clr;              // 将时钟端口(SCL)设为低
 DDRA|=0x02;
 DDRA&=0xFE;               // 设置数据口(SDA)为输入 
 delayus(2);  
 while(PINA&0x01) 
 {
    errtime--;
    if (!errtime)      //errtime=0,没接收到
    {
   I2C_Stop();
      return 0x00;
    }
  }  
 DATE_CLK_set;
 delayus(2); 
 DATE_CLK_clr;                // 将时钟端口(SCL)设为低
 delayus(2);
 return 0x01;      //true 
}

// ******************************************************** //
// *** This routine will write a byte to the I2C device *** //
// ******************************************************** //

void Write_I2C_Byte(unsigned char byte)     //写一个字节到I2C设备
{
 unsigned char i;
 DDRA|=0x03;                        //将PA0数据端口(SDA)设为输出
 for (i = 0; i < 8; i++)          //传送8位数据
     {   
  DATE_CLK_clr;                   //将时钟端口(SCL)设为低  
     if((byte & 0x80)) DATE_DT_set;      // 设置 SDA 位
  else DATE_DT_clr;        // 清除 SDA 位
  delayus(2);
    DATE_CLK_set;                   //将时钟端口(SCL)设为高
     asm("nop"); 
   byte = byte << 1;        //将输出数据左移一位
 }
 DATE_CLK_clr;                       // 校验标志位 (每传送8位,有一校验位)
 if (I2C_Ackn()==0)         // Check for acknowledge from I2C device
 yonghudenglu();
 //DATE_CLK_clr;
}

// ********************************************************* //
// *** This routine will read a byte from the I2C device *** //
// ********************************************************* //

unsigned char Read_I2C_Byte(void)   //读取I2C设备的数据
{ 
 unsigned char i,buff = 0;
 delayus(2);
 DDRA|=0x02;                   //PA1为时钟,输出
 DDRA&=0xfe;                //设置数据口(SDA)为输入
 for (i = 0; i < 8; i++)
    {
  DATE_CLK_clr;                 // 将时钟端口(SCL)设为低
  delayus(2);
     DATE_CLK_set;                 //将时钟端口(SCL)设为高
  delayus(2);
   // 在 SDA 位上读取数据
  if ( PINA&=0x01 ) 
  buff++;
  buff = (buff << 1);
  delayus(2);
   }
 DDRA|=0x03;                  //设为输出,发送校验位
 DATE_DT_clr;
 delayus(2);
 DATE_CLK_set;
 delayus(2);
 DATE_CLK_clr;                     //将时钟端口(SCL)设为高
 //DATE_DT_clr;       
 return buff;          // 返回读取值
}

//读8563寄存器
unsigned char rtc_read(unsigned char address)
{
unsigned char d;
I2C_Start();
Write_I2C_Byte(0xa2);
Write_I2C_Byte(address);
I2C_Start();
Write_I2C_Byte(0xa3);
d=Read_I2C_Byte();
d=d>>1;
I2C_Stop();
//for(;;){}
return d;
}

////////////////////////////////////////////////////////////////////////////////
//写8563寄存器
void rtc_write(unsigned char address,unsigned char data1)
{
I2C_Start();
Write_I2C_Byte(0xa2);
Write_I2C_Byte(address);
Write_I2C_Byte(data1);
I2C_Stop();
}

////////////////////////////////////////////////////////////////////////////////

void rtc_start(void)
{
rtc_write(0,0);
}

////////////////////////////////////////////////////////////////////////////////

void rtc_stop(void)
{
rtc_write(0,0x20);
}

void GetPCF8563(unsigned char *time)
{ 
  CLI();
  *time=(rtc_read(2)&0x7f);           //寄存器0x02为秒寄存器
  *(time+1)=(rtc_read(3)&0x7f);       //寄存器0x03为分寄存器
  *(time+2)=(rtc_read(4)&0x3f);       //寄存器0x04为时寄存器
  *(time+3)=(rtc_read(5)&0x3f);       //寄存器0x05为天寄存器
  *(time+4)=(rtc_read(7)&0x1f);       //寄存器0x07为月寄存器
  *(time+5)=(rtc_read(8));            //寄存器0x08为年寄存器
  SEI();
}

unsigned char get_second(void)      //获得当前秒数
{
  unsigned i,j;
  i=(rtc_read(2)&0x7f);         //寄存器0x02为秒寄存器
  j=(i&0x0f)+(i>>4)*10;
  return j;
}

////////////////////////////////////////////////////////////////////////////////
void SetPCF8563(unsigned char adds,unsigned char data)
{
 CLI();
 rtc_stop();
 rtc_write(adds,data);
 rtc_start();
 SEI();
}

//设置时间  (**年/**月/**日  **时:**分)
void set8563(void)
{
  unsigned char maini=0,mainj=0,numb[12],newkey;
  unsigned char sign=0;
  unsigned char *time;
  unsigned char displayn[12];
  time=numb;
  while((mainj<10)||(sign==0))
  {
     if(kbscan()!=0x20)
  {
     maini=kbscan();
  while(kbscan()==maini)
  asm("nop");
     if(maini<10)
        {
         numb[mainj]=maini;
         displayn[mainj]=number1[maini];
   mainj++;
        }
  else if(maini==12)
        {
         if(mainj>0)
         mainj--;
         numb[mainj]=number1[10];
         displayn[mainj]=number1[10];
  }
  else if((mainj>=10)&&(maini==13))
  {
    sign=1;
  }
       display(0x80,displayn[0],displayn[1]);
       display(0x81,0x2f,displayn[2]);
       display(0x82,displayn[3],0x2f);
       display(0x83,displayn[4],displayn[5]);
       display(0x84,0x20,0x20);
       display(0x85,displayn[6],displayn[7]);
       display(0x86,0x3a,displayn[8]);
       display(0x87,displayn[9],0x20);
     }
  }
  numb[0]=(numb[0]<<4)+(numb[1]&0x0F); //年
  numb[2]=(numb[2]<<4)+(numb[3]&0x0F); //月
  numb[4]=(numb[4]<<4)+(numb[5]&0x0F); //日
  numb[6]=(numb[6]<<4)+(numb[7]&0x0F); //时
  numb[8]=(numb[8]<<4)+(numb[9]&0x0F); //分
  SetPCF8563(8,numb[0]);     //设置年
  SetPCF8563(7,numb[2]);     //设置月
  SetPCF8563(5,numb[4]);     //设置日
  SetPCF8563(4,numb[6]);     //设置时
  SetPCF8563(3,numb[8]);     //设置分
}

//显示时间函数,屏幕第一行显示
void displaytime(unsigned char *time)
{
  GetPCF8563(time);
  new_minute=*(time+1);
  if(new_minute!=old_minute)
  {
    display(0x80,0x30+(*(time+5)>>4),0x30+(*(time+5)&0x0F));
   display(0x81,0x2f,0x30+(*(time+4)>>4));
   display(0x82,0x30+(*(time+4)&0x0F),0x2f);
   display(0x83,0x30+(*(time+3)>>4),0x30+(*(time+3)&0x0F));
   display(0x84,0x20,0x20);
   display(0x85,0x30+(*(time+2)>>4),0x30+(*(time+2)&0x0F));
   display(0x86,0x3a,0x30+(*(time+1)>>4));
   display(0x87,0x30+(*(time+1)&0x0F),0x20);
 old_minute=new_minute;
  }
  //display(0x98,0x30+(*time>>4),0x30+(*time&0x0F));  
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -