历史上的今天
今天是:2025年08月15日(星期五)
2019年08月15日 | 51单片机的DS1302的驱动程序
2019-08-15 来源:eefocus
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(); //打印读出的数据 } }
上一篇:贰拾壹:EEPROM的操作
下一篇:单片机ds18b20的介绍和源码
史海拾趣
|
这是我的毕业设计 希望大家帮帮我 我现在已经焦头烂额了 网上都是基于DSP控制的滤波器 就是没有基于单片机控制的 真的郁闷 我的邮箱是westlife009@tom.com 我的QQ是232125740 欢迎大家一起交流 [ 本帖最后由 westlifeljb 于 2008-5-15 17:15 编 ...… 查看全部问答> |
|
这是一个初学者常问的问题,也是初学者问嵌入式该如何入门的根源。我感觉有两个方面,偏硬和偏软.我不认为嵌入式开发软件占绝对比重,相反,软硬件都懂,才是嵌入式高手所应该追求的,也是高手的必由之路。 硬件道路: 第一步: pcb设 ...… 查看全部问答> |
|
这里要求程序在窗口最小化的方式下启动,这里在OnInitDlg()中用ShowWindow(SW_MINIMIZE);窗口会闪一下,至少上面的标题栏会改变,是否有什么办法可以解决,我看了一下CDialog::OnInitDialog()的原文件,里面是用::SetForegroundWindow(m_hWnd);来显示窗 ...… 查看全部问答> |
|
湿度计的读写时序包括读时序和写时序,写时序如下:向 SH T21写8 个数据位 ,然后在第9 个时钟周期 ,读取 SHT21 的应答位 ,应位为 0 ,表示SHT21正确接收到了一个字节 ,也就是 8 个写时序加 1 个读时序。SH T21 读写数据的规则是:DA TA在 SCK时钟的下 ...… 查看全部问答> |
|
能量效率更高、功能更强的新型LED固态发光(SSL)产品的发展很快,被认为是照明市场上的主要革命性进步。在许多垂直应用中,如信号灯、汽车、LCD TV背光,LED已经毫无争议地成为传统光源的替代产品。但对于范围更广的通用照明,LED还没有被广泛接受 ...… 查看全部问答> |
|
我准备使用TI研讨会发的LM3S811套件,我看原理图811的UART口,也就是PA0,PA1和板上另一个芯片的PA0.PA1通过0欧姆电阻相连,如果我要使用811的UART,把PA0,PA1引出到232芯片上进行串口通信时,会不会对另一个芯片产生影响,或者是应该如何把811的 ...… 查看全部问答> |
|
看到这个题目,忽然感到自己想说些话,关于技术,也关于一些感触。 在无锡呆了多年,作为一个电子技术不算特别发达的城市,真正能称得上电子产业的除了前几年轰轰烈烈的电动车产业链外,恐怕就只能算上现在的物联网示范城市了。 &n ...… 查看全部问答> |




