DS1302时钟芯片驱动程序
/*****************************************************************************
FileName : DS1302.c
Function : DS1302驱动
Author : mike
Email : hxtiou@163.com
Version : V1.0
Date : 2019-10-21
注意:DS1302写寄存器是地址是偶数,读的时候地址+1
比如:往0x80地址写入0x01,读取时需要从0x81读取
DS1302控制字:
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
1 RAM/-CK A4 A3 A2 A1 A1 RD/-WR
[7] :控制字的最高有效位(位7)必须是逻辑1,如果它为 0 则不能把数据写入DS1302;
[6] :如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;
[5:1]:指示操作单元的地址;
[0] :0表示要进行写操作,为1表示进行读操作;
控制字总是从最低位开始输出.在控制字指令输入后的下一个SCLK时钟的上升沿时数据
被写入DS1302,数据输入从最低位(0位)开始.同样,在紧跟8位的控制字指令后的下一个
SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位.
存取日历时钟(BCD码):其中9~31地址不能存储数据
写入地址:0x00|0x80~0x3E|0x80 = 0x80~0xBE(取偶数)
读取地址:0x00|0x81~0x3E|0x81 = 0x81~0xBF(取奇数)
存取RAM:其中31地址不能存储数据
写入地址:0x00|0xC0~0x3E|0xC0 = 0xC0~0xFE(取偶数)
读取地址:0x00|0xC1~0x3E|0xC1 = 0xC1~0xFF(取奇数)
0x80---秒寄存器的BIT7表示时间暂停位,BIT7为1时停止工作,0时开始工作
0x84---小时寄存器的BIT表示12/24小时制,BIT7为1表示12时制,为0表示24时制;
BIT5为AM/PM位,BIT5为1表示PM,0表示AM
0x8E---写保护<写入0x00表示允许进行写操作,0x80表示不允许写操作>
写日期时间寄存器:
0x80---秒
0x82---分
0x84---时
0x86---日
0x88---月
0x8A---星期
0x8C---年
读日期时间寄存器:
0x81---秒
0x83---分
0x85---时
0x87---日
0x89---月
0x8B---星期
0x8D---年
*****************************************************************************/
include "include.h"
include "DS1302.h"
type_time t_time;
if 0
u8 max_day[12]={31,28,31,30,31,30,31,31,30,31,30,31}; //各月的天数
/**********************************************************
检查是否润年,返回当前二月最大天数
判断润年的完整公式为A=X410+X3,B=4,A/B;A=B10+X2,B=4,A/B;A=B10+X1,B=4,A/B
*********************************************************/
u8 chk_max_day(void)
{
if(t_time.month == 2)
{
if(t_time.year % 4) //t_time.year取值00~99
return (29); //如果是润年,返回29天。
else
return (28); //否则为28天。
}
else
{
return max_day[t_time.month-1];
}
}
endif
void ds1302_write_byte(u8 dat)//写一个字节
{
u8 i;
DS1302_IO_OUT();
delay(5);
for(i = 8;i > 0;i --)
{
if(dat & 0x01)
{
DS1302_IO_HIGH();
}
else
{
DS1302_IO_LOW();
}
dat >>= 1;
DS1302_CLK_HIGH();
delay(5);
DS1302_CLK_LOW();
delay(5);
}
}
u8 ds1302_read_byte(void)//读一个字节
{
u8 i = 0;
u8 dat = 0;
DS1302_IO_IN();
delay(5);
for(i = 8;i > 0;i --)
{
dat >>= 1;
if(DS1302_IO_IS_HIGH())
{
dat |= BIT(7);
}
else
{
dat &= ~BIT(7);
}
DS1302_CLK_HIGH(); //下降沿读取数据
delay(5);
DS1302_CLK_LOW();
delay(5);
}
return dat;
}
void ds1302_write(u8 adr,u8 dat)//向1302芯片写函数,指定写入地址,数据
{
DS1302_RST_LOW();
DS1302_CLK_LOW();
DS1302_RST_HIGH();
ds1302_write_byte(adr);
ds1302_write_byte(dat);
DS1302_RST_LOW();
DS1302_CLK_HIGH();
}
u8 ds1302_read(u8 adr)//从1302读数据函数,指定读取数据来源地址
{
u8 temp = 0;
DS1302_RST_LOW();
DS1302_CLK_LOW();
DS1302_RST_HIGH();
ds1302_write_byte(adr);
temp = ds1302_read_byte();
DS1302_RST_LOW();
//DS1302_CLK_HIGH();
return temp;
}
u8 bcd_dec(u8 bcd)//BCD码转10进制函数
{
return ((bcd/16)*10+(bcd%16));
}
u8 dec_bcd(u8 dec)//10进制转BCD码
{
return ((dec/10)*16+(dec%10));
}
void ds1302_write_time(void)//写入时间日期
{
ds1302_write(0x8E,0x00); //允许写
//t_time.wday = week_conversion(t_time.year,t_time.month,t_time.day);
ds1302_write(0x80,dec_bcd(t_time.second)); //秒
ds1302_write(0x82,dec_bcd(t_time.minute)); //分
ds1302_write(0x84,dec_bcd(t_time.hour)); //时
ds1302_write(0x86,dec_bcd(t_time.day)); //日
ds1302_write(0x88,dec_bcd(t_time.month)); //月
//ds1302_write(0x8A,dec_bcd(t_time.wday)); //星期
ds1302_write(0x8C,dec_bcd(t_time.year)); //年
ds1302_write(0x8E,0x80); //禁止写
}
void ds1302_read_time(void) //读取时间数据
{
t_time.second = bcd_dec(ds1302_read(0x81)&0x7F); //秒
t_time.minute = bcd_dec(ds1302_read(0x83)); //分
t_time.hour = bcd_dec(ds1302_read(0x85)&0x1F); //时
t_time.day = bcd_dec(ds1302_read(0x87)); //日
t_time.month = bcd_dec(ds1302_read(0x89)); //月
//t_time.wday = bcd_dec(ds1302_read(0x8B)); //星期
t_time.year = bcd_dec(ds1302_read(0x8D)); //年
t_time.wday = week_conversion(t_time.year,t_time.month,t_time.day);
//printf("%d : %d : %d\n",t_time.hour,t_time.minute,t_time.second);
//printf("日期 : 20%d年%d月%d日 星期%d\n",t_time.year,t_time.month,t_time.day,t_time.wday);
//printf("时间 : %02d : %02d : %02d\n\n",t_time.hour,t_time.minute,t_time.second);
}
void ds1302_conversion_hourly(u8 hourly,u8 ampm) //转换12/24小时制,AM/PM
{
ds1302_write(0x8E,0x00); //允许写
if(hourly == HOURLY_12) //12小时制
{
t_time.hour |= BIT(7);
if(ampm == HOURLY_PM) //PM
t_time.hour |= BIT(5);
else if(ampm == HOURLY_AM)
t_time.hour &= ~BIT(5);
}
else if(hourly == HOURLY_24) //24小时制
{
t_time.hour &= ~BIT(7);
}
ds1302_write(0x84,dec_bcd(t_time.hour));
ds1302_write(0x8E,0x80); //禁止写
}
void ds1302_write_ram(void)//写入RAM的记忆信息
{
ds1302_write(0x8E,0x00); //允许写
/
此处记忆闹钟数据,地址范围0xc0,0xc2...~0xe4
ds1302_write(0xc0,0x08);//闹钟一小时位
ds1302_write(0xc2,0x00);//闹钟一分钟位
ds1302_write(0xc4,0x08);//闹钟二小时位
ds1302_write(0xc5,0x00);//闹钟二分钟位
/
ds1302_write(0x8E,0x80); //禁止写
}
void ds1302_reset(void)//复位---写入寄存器时间日期和记忆信息
{
//默认时间日期初始化
t_time.second = 0;
t_time.minute = 0;
t_time.hour = 8;
t_time.day = 1;
t_time.month = 10;
t_time.year = 17;
t_time.wday = week_conversion(t_time.year,t_time.month,t_time.day);
//写入时间日期
//ds1302_write_time();
/*********************************************************************
//写入RAM的记忆信息
ds1302_write_ram();
*********************************************************************/
ds1302_write_time();
ds1302_write(0x8E,0x00); //允许写
ds1302_write(0xFC,0x99); //用于判断是否曾经初始化过时间
ds1302_write(0x8E,0x80); //禁止写
}
void ds1302_init(void) //1302芯片初始化
{
u8 temp = 0;
DS1302_IO_INIT();
DS1302_RST_LOW();
DS1302_CLK_LOW();
temp = ds1302_read(0xFD); //判断振荡器是否为开
if(temp != 0x99) //如果特定寄存器的数据不是默认写入的值---重写默认时间
{
ds1302_reset(); //重新写入时间
printf("DS1302 reinit ......\n");
}
/********************************************************************************/
ds1302_write(0x8E,0x00); //允许写
ds1302_write(0xFA,0x89); //写0x89
ds1302_write(0x8E,0x80); //禁止写
//delay_ms(10);
temp = ds1302_read(0xFB);
if(temp == 0x89) //读取写进去的值
{
printf("DS1302 init successful !\n");
}
else
{
printf("DS1302 init error !\n");
}
/********************************************************************************/
ds1302_read_time(); //读取时间
t_time.second &= 0x7F; //启动DS1302时钟振荡器(0x80寄存器的bit7置0)
ds1302_write(0x8E,0x00); //允许写
/********************************************************/
ds1302_write(0x80,dec_bcd(t_time.second));
ds1302_write(0x90,TCS_OFF|DS_OFF); //充电被禁止
//ds1302_conversion_hourly(HOURLY_12,HOURLY_PM);//设置小时制
/********************************************************/
//ds1302_write(0x90,TCS_ON|DS_DIODE_TWO|CS_RES_8K); //启动充电---2个二极管,8K电阻涓流充电
ds1302_write(0x8E,0x80); //禁止写
/
if(t_time.second > 59)
t_time.second = 0;
if(t_time.minute > 59)
t_time.minute = 0;
if(t_time.hour > 23)
t_time.hour = 0;
if(t_time.day > 31)
t_time.day = 1;
if(t_time.month > 12)
t_time.month = 1;
if(t_time.year > 99)
t_time.year = 0;
/
}
/****************************************************************************
算法:日期+年份+所过闰年数+月较正数之和除7 的余数就是星期,但如果是在闰年又不到
3月份,上述之和要减一天再除7,星期数为0
century=0 为21世纪,century=1 为20世纪
输入输出数据均为BCD数据
年月日为16进制数
*****************************************************************************/
u8 week_conversion(u8 year,u8 month,u8 day) //星期转换
{
u16 y = year + 2000;
//一月和二月被当作前一年的
if((month==1)||(month==2))
{
month+=12;
y--;
}
//u8 week=(day+2month+3(month+1)/5+y+y/4-y/100+y/400)%7;
//printf("new:%d.%d.%d\n",y,month,day);
return (day+2month+3(month+1)/5+y+y/4-y/100+y/400)%7+1;
}
DS1302时钟芯片驱动程序的更多相关文章
- 单片机课程设计——《基于AT89S52单片机和DS1302时钟芯片的电子时钟(可蓝牙校准)》
引言 本设计以AT89S52单片机为控制核心,时钟芯片DS1302提供时钟源,配合LCD1602液晶显示模块,组成基本硬件系统,同时利用HC-05嵌入式蓝牙串口通讯模块,可在手机端进行日期.时间的校准 ...
- spi接口的ds1302时钟芯片控制在lcd1602上显示
spi接口的ds1302时钟芯片控制在lcd1602上显示 ...
- 基于STM32F1的时钟芯片DS1302驱动
目录 DS1302.h源代码 DS1302.c源代码 DS1302.h源代码 /** ********************************************************* ...
- 轻松吃透实时时钟芯片DS1302软硬件设计,看完秒懂
今天我们来讨论一款老掉牙的实时时钟芯片DS1302.什么是实时时钟(RealTime Clock, RTC)呢?为什么我们需要它呢?假设你使用单片机实现万年历应用,一般的做法是这样的:设置中断后判断1 ...
- 「雕爷学编程」Arduino动手做(29)——DS1302时钟模块
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...
- STC8H开发(十四): I2C驱动RX8025T高精度实时时钟芯片
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- DS1337 时钟芯片在 C8051F 上的实现
一.DS1337介绍 DS1337串行实时时钟芯片是一种低功耗.全部采用BCD码的时钟日历芯片,它带有两个可编程的定时闹钟和一个可编程的方波输出.其地址和数据可通过I2C总线串行传输,能提供秒.分.时 ...
- ENC28j60以太网芯片驱动程序简介
ENC28j60以太网芯片驱动程序简介 ENC28J60 驱动开发要点 enc28J60 和 Arduino (1)——ping通你的Arduino MCU51单片机uIP协议栈+ENC28J60网卡 ...
- Arduino和C51开发DS1302时钟
技术:51单片机.Arduino.DS1302时钟.串口通信 概述 本文实现51单片机和Arduino串口实时显示时钟功能,让读者对DS1302能够更好的理解,这次功能也和上节课学到的串口通信运用 ...
随机推荐
- windows下离线安装mysql8.0服务(支持多个安装,端口不同就可以)
1.官网下载 mysql文件.官网下载链接:https://dev.mysql.com/downloads/mysql/ 选择mysql下载的系统版本. 此处可以下载MSI安装包,图简单的朋友可以 ...
- 原生JS实现单向链表
1.前言 用JS实现一个简单的单向链表,并完成相关的功能 2.功能说明 push(value):从链表尾部添加一个新的节点 insertAfer(value,item):向链表中的item节点之后插入 ...
- 大数据之路day04_2--经典bug(equals与==比较不同,break的跳出不同)
一.equals与==比较不同 在实现某个人去5个商场去购物,控制台输入是否购物(Y/N)的时候,在比较出了问题,发现无论输入什么都是false,后来查阅资料发现,字符串的比较,==和equals不一 ...
- 中文企业云操作系统 CecOS
CecOS介绍 CecOS(原中文企业云操作系统.第一个版本基于oVirt 3.0,后续在此基础上不断升级迭代拓展至今,已形成基于基础底层和应用功能拓展集成在内的10款产品和四大平台),旨在通过先进的 ...
- pandas处理excel的常用方法技巧(上)
1. 导库 import pandas as pd 2. 读取excel文件 这里要注意的就是第二个参数header如果不设置,pandas会默认把excel的第一行当作columns,header= ...
- [LINQ2Dapper]最完整Dapper To Linq框架(三)---实体类关系映射
此特性需要安装Kogel.Dapper.Mssql或者Oracle 3.06及以上版本,实体类层需要安装Kogel.Dapper.Extension 3.06及以上版本 目录 [LINQ2Dapper ...
- Java线程池中线程的状态简介
首先明确一下线程在JVM中的各个状态(JavaCore文件中) 1.死锁,Deadlock(重点关注) 2.执行中,Runnable(重点关注) 3.等待资源,Waiting on condition ...
- 【algo&ds】3.栈和队列
1.堆栈 堆栈(Stack):具有一定操作约束的线性表(只在一端(栈顶,Top)做插入.删除) 先进后出特性 1.1堆栈的抽象数据类型描述 类型名称: 堆栈(Stack) 数据对象集:一个有0个或多个 ...
- kubernetes实战(二十八):Kubernetes一键式资源管理平台Ratel安装及使用
1. Ratel是什么? Ratel是一个Kubernetes资源平台,基于管理Kubernetes的资源开发,可以管理Kubernetes的Deployment.DaemonSet.Stateful ...
- Arduino 将 String 转化为 int
Arduino 将 String 转化为 int 函数:toInt() 实例: String my_str = "; int my_int = my_str.toInt();