DS1302实时时钟模块
对于时钟芯片,我们只要知道它的写入时序图和读出时序图,以及时钟芯片内部
所对应的地址就可以了,
所谓写是写入EEPROM里面,即设定好一个时钟的初值,然后每次刷新的时钟的
新值都写入EEPROM里保存起来,再从EEPROM里读出来,这样就能保证当外部
电源掉电后,自带的电池仍能按照掉电时的时间继续刷新,而不是回到初始值。
读一个数据的时序图
写一个数据的时序图
内部各功能地址
驱动程序:
#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(); //打印读出的数据
}
}
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』