51单片机的DS1302的驱动程序

2019-08-15来源: eefocus关键字:51单片机  DS1302  驱动程序

 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();              //打印读出的数据

}

}


关键字:51单片机  DS1302  驱动程序

编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic471215.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:贰拾壹:EEPROM的操作
下一篇:单片机ds18b20的介绍和源码

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

51单片机之定时器/计数器应用实例(方式0、1、2、3)

硬件:STC89C52RC开发工具:Keil uVision4     对于刚接触单片机的同学来说可能会对定时器/计数器的应用很蒙圈,特别是初值的计算和各种定时方式的选择。下面希望能给你带来一个清晰的思路。定时器:一般用于软件计时,给定时器设置一个时间,时间到了系统停止当前的工作跳转到事先定义好的定时器中断函数里,函数里可以做一些周期性的事情。计数器:一般用于检测外来脉冲信号,给计数器设置一个次数,次数到了系统停止当前的工作跳转到事先定义好的计数器中断函数里,函数里做相应的事情。先说一下相关的寄存器,也可以直接跳过,看后面的实例分析。配置定时器或者计数器就是对相应的寄存器进行赋值,下面是相关的寄存器
发表于 2019-08-20
51单片机之定时器/计数器应用实例(方式0、1、2、3)

51单片机之外部中断应用实例(电平触发、边沿触发)

硬件:STC89C52RC开发工具:Keil uVision4前言:8051是一款很经典的、历史悠久的单片机,作为一款入门级的单片机8051受到很多初学者的欢迎。89c52是8051系列的成员之一,拥有8K字节程序存储空间,512字节随机数据存储空间;I/O口控制端口、中断功能、定时器及串行接口。下面详细讲述外部中断功能的使用。外部中断:单片机提供的系统紧急事件的输入控制。事件触发的方式包括输入信号的下降沿触发、低电平触发。当触发中断后,单片机会跳到某一个固定的地址去执行中断服务程序。外部中断信号由INT0、INT1引脚传送进来,如图所示:有关中断处理的相关控制寄存器如下:计时计数器控制寄存器 TCON中断允许控制寄存器 IE
发表于 2019-08-20
51单片机之外部中断应用实例(电平触发、边沿触发)

51单片机之串口通讯应用实例(逻辑分析仪调试)

硬件:STC89C52RC开发工具:Keil uVision4前言:8051是一款很经典的、历史悠久的单片机,作为一款入门级的单片机8051受到很多初学者的欢迎。89c52是8051系列的成员之一,拥有8K字节程序存储空间,512字节随机数据存储空间;I/O口控制端口、中断功能、定时器及串行接口。下面详细讲述串行接口功能的使用。不管你用的芯片是不是STC89C52RC,只要你看完这篇文章,就能自行运用到不同的芯片上;因为一种串口通信协议的传输原理在任何芯片上都是统一的;所以它可以作为不同芯片一起协作的通信媒介。目前普遍的单片机都有串行通信的接口,因为它依赖的硬件比较简单,一条串行数据输出线(TX)、一条串行数据接收线(RX)、一条
发表于 2019-08-20
51单片机之串口通讯应用实例(逻辑分析仪调试)

STM32单片机连接HC_SR04超声波模块测距

图。         我们来分析一下这个时序图,先由触发信号启动HC-RS04测距模块,也就是说,主机要先发送至少为10us的高电平,触发HC-RS04,模块内部发出信号是传感器自动回应的,我们不用去管它。输出回响信号是我们需要关注的。信号输出的高电平就是超声波发出到重新返回接收所用的时间。用定时器,可以把这段时间记录下来,算出距离,别忘了结果要除于2,因为总时间是发送和接收的时间总和。下面是亲测可用的驱动程序。芯片型号为STM32F103ZET6,超声波测距后通过串口打印到电脑上面。驱动和测距;//超声波测距   
发表于 2019-08-19
STM32单片机连接HC_SR04超声波模块测距

矩阵键盘扫描原理详解——单片机

键盘扫描方法是:行线P10~P13为输出线,列线P14~P17为输入线。一开始单片机将行线(P10~P13)全部输出低电平,此时读入列线数据,若列线全为高电平则没有键按下,当列线有出现低电平时调用延时程序以此来去除按键抖动。延时完成后再判断是否有低电平,如果此时读入列线数据还是有低电平,则说明确实有键按下。最后一步确定键值。现在我们以第二行的S5键为例,若按下S5后我们应该怎么得到这个键值呢?当判断确实有键按下之后,行线轮流输出低电平,根据读入列线的数据可以确定键值。首先,单片机将P10输出为低电平,其它P11~P13输出高电平,此时读取列线的数据全为高电平,说明没有在第一行有键按下;其次,单片机将P11输出低电平,其它P10
发表于 2019-08-16

单片机读入4*4矩阵键盘

一、什么是矩阵键盘矩阵键盘是单片机外部设备中所使用的排布类似于矩阵的键盘组,由于电路设计时需要更多的外部输入,单独的控制一个按键需要浪费很多的IO资源,所以就有了矩阵键盘,常用的矩阵键盘有4*4和8*8,其中用的最多的是4*4。网上搜了两张实物图,大家可以看看看上图就知道,4*4键盘还是很多地方用到的吧^_^二、矩阵键盘的原理矩阵键盘又称为行列式键盘,它是用4条I/O线作为行线,4条I/O线作为列线组成的键盘。在行线和列线的每一个交叉点上,设置一个按键。这样键盘中按键的个数是4×4个。这种行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。由于单片机IO端口具有线与的功能,因此当任意一个按键按下时,行和列都有一根线被线与,通
发表于 2019-08-16
单片机读入4*4矩阵键盘

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved