51单片机的DS1302的驱动程序

 DS1302实时时钟模块


 对于时钟芯片,我们只要知道它的写入时序图和读出时序图,以及时钟芯片内部

 所对应的地址就可以了,

 所谓写是写入EEPROM里面,即设定好一个时钟的初值,然后每次刷新的时钟的

 新值都写入EEPROM里保存起来,再从EEPROM里读出来,这样就能保证当外部

 电源掉电后,自带的电池仍能按照掉电时的时间继续刷新,而不是回到初始值。

 

读一个数据的时序图

51单片机的DS1302的驱动程序_第1张图片

     

 写一个数据的时序图

       51单片机的DS1302的驱动程序_第2张图片

 内部各功能地址

    51单片机的DS1302的驱动程序_第3张图片



 驱动程序:

   

#include 
#include "./delay/delay.h"


#define ds1302_sec_add			   0x80	   //设置秒的地址
#define ds1302_min_add			   0x82	   //设置分的地址	
#define ds1302_hr_add			     0x84  //设置时的地址
#define ds1302_date_add			   0x86	   //设置天的地址	
#define ds1302_month_add		   0x88	   //设置月的地址
#define ds1302_year_add			   0x8c	   //设置年的地址
#define ds1302_control_add		 0x8e		
#define ds1302_charger_add		 0x90 					 
#define ds1302_clkburst_add		 0xbe

sbit RST = P1^2;
sbit SCK = P1^1;
sbit IO = P1^0;

unsigned char tempbuf[3];
unsigned char timebuf[3] = {20,59,30};           //时间
unsigned char readbuf[6];
unsigned char disbuf[7];
unsigned char writebuf[6];

unsigned char disyear[3] = {16,8,17};          //日期



/*LCD*/
#define LCDPORT P0
#define LCD_WRITE_DATA   1
#define LCD_WRITE_COM    0
sbit RS = P2^4;
sbit RW = P2^5;
sbit E = P2^6;

void ds1302_write_byte(unsigned char addr, unsigned char byte)
{
		unsigned char i;
		addr = addr & 0xfe;
		SCK = 0;
		RST = 0;
	
		RST = 1;
		for(i = 0; i < 8; i++)
		{
				IO = addr & 0x01;
				SCK = 0;
				SCK = 1;
				addr >>= 1;
		}
		for(i = 0; i < 8; i++)
		{
				IO = byte & 0x01;
				SCK = 0;
				SCK = 1;
				byte >>= 1;
		}
		SCK = 0;
		RST = 0;
}

unsigned char ds1302_read_byte(unsigned char addr)
{
		unsigned char i;
		unsigned char temp;
		addr = addr & 0xfe;
		SCK = 0;
		RST = 0;
	
		RST = 1;
		addr = addr + 1;
		for(i = 0; i < 8; i++)
		{
				IO = addr & 0x01;
				SCK = 0;
				SCK = 1;
				addr >>= 1;
		}
		for(i = 0; i < 8; i++)
		{	
				SCK = 1;
				SCK = 0;
				temp >>= 1;
				if(IO)
				{
						temp += 0x80;
				}
		}
		//SCK = 0;
		RST = 0;
		return temp;
}
	
void ds1302_write_time()
{
		unsigned char i;
		unsigned char temp;
		unsigned char temp1;
		for(i = 0; i < 6; i++)
		{  
				temp  = timebuf[i] / 10;
        temp1 = timebuf[i] % 10;
        writebuf[i] = (temp << 4) | temp1;
				//writebuf[i] = ((timebuf[i] / 10) << 4) + (timebuf[i] % 10);
		}
		
		ds1302_write_byte(ds1302_control_add,0x00);
		ds1302_write_byte(ds1302_hr_add,writebuf[0]);
		ds1302_write_byte(ds1302_min_add,writebuf[1]);
		ds1302_write_byte(ds1302_sec_add,writebuf[2]);
		
		ds1302_write_byte(ds1302_year_add,writebuf[3]);
		ds1302_write_byte(ds1302_month_add,writebuf[4]);
		ds1302_write_byte(ds1302_date_add,writebuf[5]);
		ds1302_write_byte(ds1302_control_add,0x80);		
}

void ds1302_read_time()
{
		unsigned char i;
	
		readbuf[0] = ds1302_read_byte(ds1302_hr_add);
		readbuf[1] = ds1302_read_byte(ds1302_min_add);
		readbuf[2] = ds1302_read_byte(ds1302_sec_add);
	
		readbuf[3] = ds1302_read_byte(ds1302_year_add);
		readbuf[4] = ds1302_read_byte(ds1302_month_add);
		readbuf[5] = ds1302_read_byte(ds1302_date_add);
		
		
		for(i = 0; i < 6; i++)
		{
			
				disbuf[i] =  ((readbuf[i] >> 4) * 10) + (readbuf[i] & 0x0f);               		
		}
		
}

void lcd1602_write(unsigned char byte, unsigned char flag)
{
		if(flag)
		{
				RS = 1;                    //选择输入的数据为数据
		}
		else
		{
				RS = 0;                      //选择输入的数据为命令
		}
		RW = 0;                           //写
		E = 1;                            //选中lcd
		LCDPORT = byte;
		delay_ms(5);
		E = 0;                          //失能LCD      高电平有效
		
}

void lcd1602_init()
{
		delay_ms(15);
	  lcd1602_write(0x38,LCD_WRITE_COM);                  //设置8位数据接口,两行指令,5*8点阵字符
	  delay_ms(5);
	  lcd1602_write(0x38,LCD_WRITE_COM);
	  delay_ms(5);
	  lcd1602_write(0x38,LCD_WRITE_COM);
	  delay_ms(5);
	  lcd1602_write(0x38,LCD_WRITE_COM);
	  delay_ms(5);
	  lcd1602_write(0x08,LCD_WRITE_COM);             //关闭显示,关闭光标和闪烁
	  delay_ms(5);
	  lcd1602_write(0x01,LCD_WRITE_COM);            //清屏
	  delay_ms(5);
	  lcd1602_write(0x06,LCD_WRITE_COM);           //设置指针方式,画面不平移
	  delay_ms(5);
	  lcd1602_write(0x0c,LCD_WRITE_COM);          //设置指针方式,画面不平移
	  delay_ms(5);  
}


void lcd1602_dis_str(unsigned char x, unsigned char y, unsigned char *s)               //打印字符串
{
		if((x > 1) || (y > 15))
		{
				return ;
		}
		if(0 == x)
		{
			 lcd1602_write(y + 0x80,LCD_WRITE_COM);
			 
		}
		else if(1 == x)
		{
			 lcd1602_write(y + 0xc0,LCD_WRITE_COM);
		}
		while(*s)
		{
			
			lcd1602_write(*s, LCD_WRITE_DATA);
			s++;	
		}
}



void lcd1602_dis_time()
{
	
		unsigned char lcddisbuf[9] = {0};
		unsigned char lcdday[9] = {0};

		lcddisbuf[0] = (disbuf[0] / 10) + 0x30;                //显示时间
		lcddisbuf[1] = (disbuf[0] % 10) + 0x30;
		lcddisbuf[2] = ':';
		lcddisbuf[3] = (disbuf[1] / 10) + 0x30;
		lcddisbuf[4] = (disbuf[1] % 10) + 0x30;
		lcddisbuf[5] = ':';
		lcddisbuf[6] = (disbuf[2] / 10) + 0x30;
		lcddisbuf[7] = (disbuf[2] % 10) + 0x30;
		

		lcdday[0] =  (disbuf[3] / 10) + 0x30;                 //显示日期
		lcdday[1] =  (disbuf[3] % 10) + 0x30;
		lcdday[2] =  '-';
		lcdday[3] =  (disbuf[4] / 10) + 0x30;
		lcdday[4] =  (disbuf[4] % 10) + 0x30;
		lcdday[5] =  '-';
		lcdday[6] =  (disbuf[5] / 10) + 0x30;
		lcdday[7] =  (disbuf[5] % 10) + 0x30;
	
		
		lcd1602_dis_str(0,0,"time:");
		lcd1602_dis_str(0,6,lcddisbuf);
		lcd1602_dis_str(1,0,lcdday);
}
	
void main()
{
		lcd1602_init();
	
		ds1302_write_time();                  //写入数据
	
		while(1)
		{
				ds1302_read_time();              //读出数据
				lcd1602_dis_time();              //打印读出的数据
		}
}

你可能感兴趣的:(单片机)