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

📄 m16-pcf8563.txt

📁 AVR单片机M16的PCF8563源码
💻 TXT
字号:
#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 + -