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

📄 pcf8563.c

📁 avr单片机
💻 C
字号:
#include <iom16v.h>
#include <stdio.h>
#include <macros.h>
#include <string.h>

#include "pcf8563.h"
#include "lcd.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 number12[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();
}

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

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];
unsigned int address;
unsigned char *num,*time;
num=numb;
initlcm();
maini=kbscan();
if(maini==12)
{			
    delay(65000);
 	delay(65000);
    delay(65000);
    delay(65000);
    delay(65000);
    delay(65000);
    maini=kbscan();
    if(maini==12)
    {
      GetPCF8563(time);
	  display(0x80,0x30+(*(time+5)>>4),0x30+(*(time+5)&0x0F));
      display(0x81,0x2e,0x30+(*(time+4)>>4));
      display(0x82,0x30+(*(time+4)&0x0F),0x2e);
      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,0x2e,0x30+(*(time+1)>>4));
      display(0x87,0x30+(*(time+1)&0x0F),0x2e);
      while(mainj<10)
      {
       maini=kbscan();
        if(maini<10)
        {
         numb[mainj]=number12[maini];
         mainj++;
        }
        else if(maini==12)
        {
         if(mainj>0)
         mainj--;
         numb[mainj]=number12[10];
        }
      display(0x80,*numb,*(numb+1 ));
      display(0x81,0x2f,*(numb+2));
      display(0x82,*(numb+3 ),0x2f);
      display(0x83,*(numb+4 ),*(numb+ 5));
      display(0x84,0x20,0x20);
      display(0x85,*(numb+6 ),*(numb+ 7));
      display(0x86,0x3a,*(numb+8 ));
      display(0x87,*(numb+ 9),0x20);
      delay(50000);
      }
  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);
  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);
  display(0x98,0x30+(*time>>4),0x30+(*time&0x0F));
}

⌨️ 快捷键说明

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