×
单片机 > 单片机程序设计 > 详情

AVRM16的PCF8563源码

发布时间:2020-08-21 发布时间:
|
#include

#include

#include

#include

#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));

}




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR熔丝位操作时的要点和需要注意的相关事项