【DS1302驱动】

DS1302ZN+ 实时时钟芯片驱动

正文

最近使用了DS1302ZN+ 实时时钟芯片,浅浅分享一下我写的驱动。代码也是从其他的博主那改过来的,只是将格式和一些小细节优化了一下。具体的原理懒得写了,其他博主那有很详细的。

说明

使用的平台的STM32F103,用的标准库,用IO口模拟通信时序与DS1302进行通讯。
1、如果你同样是准备移植到STM32上,并且准备使用标准库,只需要在H文件中修改对应的引脚,然后对接一下C文件中的delay_us、delay_ms这两个函数即可。
2、如果你准备移植到别的地方,那在1的基础上你还可能还需要更改一下 ds1302_gpio_init 、 ds1032_DATAOUT_init、ds1032_DATAINPUT_init 的引脚初始化;甚至H文件中下图所示的部分也需要对应修改:
H文件截图
3、在移植的时候C文件中的这个地方注意一下,读引脚电平的函数也需要自己对应修改,而且不容易发现,是一个小坑。
C文件截图

好嘞,该文章仅供参考,不严谨请多包涵。上代码:

H文件

#ifndef __DS1302_H
#define __DS1302_H

/************管脚配置**************/
//  CE 配置 
#define DS1302_CE_RCC   RCC_APB2Periph_GPIOA
#define DS1302_CE_PORT	GPIOA			  	    													  
#define DS1302_CE_PIN	GPIO_Pin_5
//  SCLK 配置
#define DS1302_SCLK_RCC   RCC_APB2Periph_GPIOA
#define DS1302_SCLK_PORT  GPIOA			  	    													  
#define DS1302_SCLK_PIN	  GPIO_Pin_7
//  I/O 配置
#define DS1302_DATA_RCC   RCC_APB2Periph_GPIOA
#define DS1302_DATA_PORT  GPIOA			  	    													  
#define DS1302_DATA_PIN	  GPIO_Pin_6

 
#define CE_L     GPIO_ResetBits(DS1302_CE_PORT,DS1302_CE_PIN)     //拉低使能位
#define CE_H     GPIO_SetBits(DS1302_CE_PORT,DS1302_CE_PIN)       //拉高使能位
#define SCLK_L   GPIO_ResetBits(DS1302_SCLK_PORT,DS1302_SCLK_PIN) //拉低时钟线
#define SCLK_H   GPIO_SetBits(DS1302_SCLK_PORT,DS1302_SCLK_PIN)   //拉高时钟线
#define DATA_L   GPIO_ResetBits(DS1302_DATA_PORT,DS1302_DATA_PIN) //拉低数据线
#define DATA_H   GPIO_SetBits(DS1302_DATA_PORT,DS1302_DATA_PIN)   //拉高数据线

//创建TIMEData数据结构方便存储时间日期数据
typedef struct    
{
	uint16_t year;
	uint8_t  month;
	uint8_t  day;
	uint8_t  hour;
	uint8_t  minute;
	uint8_t  second;
	uint8_t  week;
}TIMEData;

extern TIMEData TimeData;             //全局变量

extern void ds1032_init(void);              //ds1302初始化函数
extern void ds1302_gpio_init(void);         //ds1302端口初始化
extern TIMEData ds1032_read_realTime(void); //获取当前时间
extern void ds1302_wirte_rig(uint8_t address,uint8_t data);//向指定寄存器写一字节数据
extern uint8_t ds1302_read_rig(uint8_t address);           //从指定寄存器读一字节数据



#endif

C文件

#include "systick.h"
#include "stm32f10x.h"
#include "ds1302.h"

TIMEData TimeData;    //定义一个存放时间数据的变量TimeData

/**********************************************************************************************************
*	函 数 名:  ds1302_gpio_init
*	功能说明:  初始化DS1302的CE和SCLK引脚
*	形    参:  无
*	返 回 值:  无
**********************************************************************************************************/
void ds1302_gpio_init(void) //CE,SCLK端口初始化
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(DS1302_CE_RCC, ENABLE);
	GPIO_InitStructure.GPIO_Pin = DS1302_CE_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(DS1302_CE_PORT, &GPIO_InitStructure);
	GPIO_ResetBits(DS1302_CE_PORT,DS1302_CE_PIN); 
	 
	RCC_APB2PeriphClockCmd(DS1302_SCLK_RCC, ENABLE);
	GPIO_InitStructure.GPIO_Pin = DS1302_SCLK_PIN; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_Init(DS1302_SCLK_PORT, &GPIO_InitStructure);
	GPIO_ResetBits(DS1302_SCLK_PORT,DS1302_SCLK_PIN); 
}

/**********************************************************************************************************
*	函 数 名:  ds1032_DATAOUT_init
*	功能说明:  将DS1302的数据引脚配置为输出
*	形    参:  无
*	返 回 值:  无
**********************************************************************************************************/
void ds1032_DATAOUT_init(void) 
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(DS1302_DATA_RCC, ENABLE);
	 
	GPIO_InitStructure.GPIO_Pin = DS1302_DATA_PIN; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(DS1302_DATA_PORT, &GPIO_InitStructure);
	GPIO_ResetBits(DS1302_DATA_PORT,DS1302_DATA_PIN);
}
 
/**********************************************************************************************************
*	函 数 名:  ds1032_DATAINPUT_init
*	功能说明:  将DS1302的数据引脚配置为输入
*	形    参:  无
*	返 回 值:  无
*   注      :  无
**********************************************************************************************************/
void ds1032_DATAINPUT_init(void)//配置双向I/O端口为输入态
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(DS1302_DATA_RCC, ENABLE);
	GPIO_InitStructure.GPIO_Pin = DS1302_DATA_PIN; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DS1302_DATA_PORT, &GPIO_InitStructure);
}
 
/**********************************************************************************************************
*	函 数 名:  ds1302_write_onebyte
*	功能说明:  向DS1302发送一字节数据
*	形    参:  data 要发送的数据
*	返 回 值:  无
*     注    :  被读写DS1302寄存器的函数调用
**********************************************************************************************************/
void ds1302_write_onebyte(uint8_t data)
{
	ds1032_DATAOUT_init(); //配置数据引脚为输出
	uint8_t count=0;
	SCLK_L;
	for(count=0;count<8;count++)
	{	
		SCLK_L;      //拉高时钟线
		if(data&0x01)  DATA_H;
		else           DATA_L; 
		SCLK_H;      //拉高时钟线,发送数据
		data>>=1;
	}
}

/**********************************************************************************************************
*	函 数 名:  ds1302_wirte_rig
*	功能说明:  向指定寄存器地址写数据
*	形    参:  address:要写的寄存器地址  data:要发送的数据
*	返 回 值:  无
**********************************************************************************************************/
void ds1302_wirte_rig(uint8_t address,uint8_t data)
{
	uint8_t temp1=address;
	uint8_t temp2=data;
	CE_L;SCLK_L;delay_us(1);
	CE_H;delay_us(2);
	ds1302_write_onebyte(temp1); //写地址
	ds1302_write_onebyte(temp2); //写数据
	CE_L;SCLK_L;delay_us(2);
}

/**********************************************************************************************************
*	函 数 名:  ds1302_read_rig
*	功能说明:  读取指定寄存器的一字节数据
*	形    参:  address:要读的寄存器地址
*	返 回 值:  读到的数据
**********************************************************************************************************/
uint8_t ds1302_read_rig(uint8_t address)
{
	uint8_t temp3=address;
	uint8_t count=0;
	uint8_t return_data=0x00;
	CE_L;SCLK_L;delay_us(3);
	CE_H;delay_us(3);
	ds1302_write_onebyte(temp3);//写寄存器地址
	ds1032_DATAINPUT_init();    //配置数据引脚为输入
	delay_us(2);
	for(count=0;count<8;count++)
	{
		delay_us(2);        //使电平持续一段时间
		return_data>>=1;    //将数据移位保存
		SCLK_H;delay_us(4); //使高电平持续一段时间
		SCLK_L;delay_us(14);//延时14us后再去读取电平,更加准确
		
		if(GPIO_ReadInputDataBit(DS1302_DATA_PORT,DS1302_DATA_PIN)) //读取数据引脚的电平
			return_data=return_data|0x80;                           //记录数据		
	}
	delay_us(2);
	CE_L;DATA_L;
	return return_data;
}
 
/**********************************************************************************************************
*	函 数 名:  ds1032_SetTime
*	功能说明:  更改DS1302的当前时间
*	形    参:  year: 年份    mon: 月份	 date: 日期	 hours:小时   min:分钟  sec:秒钟   week:星期
*	返 回 值:  无
*     注    :  形参为(0x22,0x06,0x30,0x17,0x30,0x25,0x04)  即设置当前时间为 2022-06-30-17:30-25秒-星期四
**********************************************************************************************************/
void ds1032_SetTime(uint8_t year,uint8_t mon,uint8_t date,uint8_t hours,uint8_t min,uint8_t sec,uint8_t week)
{
	ds1302_wirte_rig(0x8e,0x00); //关闭写保护
	ds1302_wirte_rig(0x80,sec);  //sec    
	ds1302_wirte_rig(0x82,min);  //min    
	ds1302_wirte_rig(0x84,hours);//hours  
	ds1302_wirte_rig(0x86,date); //date   
	ds1302_wirte_rig(0x88,mon);  //mon    
	ds1302_wirte_rig(0x8a,week); //week   
	ds1302_wirte_rig(0x8c,year); //year   
	ds1302_wirte_rig(0x8e,0x80); //关闭写保护
}
	
/**********************************************************************************************************
*	函 数 名:  ds1032_read_time
*	功能说明:  读取当前的时间(BCD格式)
*	形    参:  无
*	返 回 值:  无
**********************************************************************************************************/
TIMEData ds1032_read_realTime(void)
{
	TIMEData time;        //暂时保存时间数据
	uint8_t read_time[7]; //暂时保存BCD格式的时间数据 
	
	//读取BCD格式的时间数据
	read_time[0]=ds1302_read_rig(0x81);//读秒
	read_time[1]=ds1302_read_rig(0x83);//读分
	read_time[2]=ds1302_read_rig(0x85);//读时
	read_time[3]=ds1302_read_rig(0x87);//读日
	read_time[4]=ds1302_read_rig(0x89);//读月
	read_time[5]=ds1302_read_rig(0x8B);//读星期
	read_time[6]=ds1302_read_rig(0x8D);//读年 
	
	//BCD码转换为10进制
	time.second=(read_time[0]>>4)*10+(read_time[0]&0x0f);
	time.minute=((read_time[1]>>4)&(0x07))*10+(read_time[1]&0x0f);
	time.hour  =(read_time[2]>>4)*10+(read_time[2]&0x0f);
	time.day   =(read_time[3]>>4)*10+(read_time[3]&0x0f);
	time.month =(read_time[4]>>4)*10+(read_time[4]&0x0f);
	time.week  =read_time[5];
	time.year  =(read_time[6]>>4)*10+(read_time[6]&0x0f)+2000;
	
	return time;
}

void ds1032_init(void)
{
	ds1302_gpio_init(); //初始化ds1302端口
	delay_ms(5); 
	//	ds1032_SetTime(0x22,0x06,0x30,0x17,0x30,0x25,0x04);//设置时间为:2022-06-30-17:30-25秒-星期四
	delay_ms(5);      
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
DS1302是一款实时时钟芯片,常用于嵌入式系统中。下面是一个简单的DS1302驱动程序的示例代码,仅供参考: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <wiringPi.h> #define DS1302_SCLK_PIN 2 #define DS1302_IO_PIN 3 #define DS1302_CE_PIN 4 #define DS1302_SEC_REG 0x80 #define DS1302_MIN_REG 0x82 #define DS1302_HOUR_REG 0x84 #define DS1302_DATE_REG 0x86 #define DS1302_MONTH_REG 0x88 #define DS1302_DAY_REG 0x8A #define DS1302_YEAR_REG 0x8C void DS1302Init() { pinMode(DS1302_SCLK_PIN, OUTPUT); pinMode(DS1302_IO_PIN, OUTPUT); pinMode(DS1302_CE_PIN, OUTPUT); digitalWrite(DS1302_CE_PIN, LOW); digitalWrite(DS1302_SCLK_PIN, LOW); } void DS1302WriteByte(unsigned char addr, unsigned char data) { unsigned char i; digitalWrite(DS1302_CE_PIN, LOW); delayMicroseconds(2); for (i = 0; i < 8; i++) { digitalWrite(DS1302_IO_PIN, addr & 0x01); addr >>= 1; digitalWrite(DS1302_SCLK_PIN, HIGH); delayMicroseconds(2); digitalWrite(DS1302_SCLK_PIN, LOW); delayMicroseconds(2); } for (i = 0; i < 8; i++) { digitalWrite(DS1302_IO_PIN, data & 0x01); data >>= 1; digitalWrite(DS1302_SCLK_PIN, HIGH); delayMicroseconds(2); digitalWrite(DS1302_SCLK_PIN, LOW); delayMicroseconds(2); } digitalWrite(DS1302_CE_PIN, HIGH); } unsigned char DS1302ReadByte(unsigned char addr) { unsigned char i, data = 0; digitalWrite(DS1302_CE_PIN, LOW); delayMicroseconds(2); for (i = 0; i < 8; i++) { digitalWrite(DS1302_IO_PIN, addr & 0x01); addr >>= 1; digitalWrite(DS1302_SCLK_PIN, HIGH); delayMicroseconds(2); digitalWrite(DS1302_SCLK_PIN, LOW); delayMicroseconds(2); } pinMode(DS1302_IO_PIN, INPUT); delayMicroseconds(2); for (i = 0; i < 8; i++) { data >>= 1; if (digitalRead(DS1302_IO_PIN)) { data |= 0x80; } digitalWrite(DS1302_SCLK_PIN, HIGH); delayMicroseconds(2); digitalWrite(DS1302_SCLK_PIN, LOW); delayMicroseconds(2); } pinMode(DS1302_IO_PIN, OUTPUT); digitalWrite(DS1302_CE_PIN, HIGH); return data; } void DS1302WriteTime(unsigned char sec, unsigned char min, unsigned char hour, unsigned char date, unsigned char month, unsigned char day, unsigned char year) { DS1302WriteByte(DS1302_SEC_REG, sec); DS1302WriteByte(DS1302_MIN_REG, min); DS1302WriteByte(DS1302_HOUR_REG, hour); DS1302WriteByte(DS1302_DATE_REG, date); DS1302WriteByte(DS1302_MONTH_REG, month); DS1302WriteByte(DS1302_DAY_REG, day); DS1302WriteByte(DS1302_YEAR_REG, year); } void DS1302ReadTime(unsigned char *sec, unsigned char *min, unsigned char *hour, unsigned char *date, unsigned char *month, unsigned char *day, unsigned char *year) { *sec = DS1302ReadByte(DS1302_SEC_REG); *min = DS1302ReadByte(DS1302_MIN_REG); *hour = DS1302ReadByte(DS1302_HOUR_REG); *date = DS1302ReadByte(DS1302_DATE_REG); *month = DS1302ReadByte(DS1302_MONTH_REG); *day = DS1302ReadByte(DS1302_DAY_REG); *year = DS1302ReadByte(DS1302_YEAR_REG); } int main() { unsigned char sec, min, hour, date, month, day, year; wiringPiSetup(); DS1302Init(); DS1302WriteTime(0x00, 0x00, 0x12, 0x01, 0x01, 0x01, 0x21); // 设置初始时间为 2021-01-01 12:00:00 while (1) { DS1302ReadTime(&sec, &min, &hour, &date, &month, &day, &year); printf("%02x:%02x:%02x %02x-%02x-%02x\n", hour, min, sec, year, month, date); delay(1000); } return 0; } ``` 这是一个基于wiringPi库的程序,使用树莓派的GPIO口与DS1302连接。主程序循环读取实时时钟的时间,并输出到终端。注意,DS1302使用的是BCD码表示时间,需要进行转换才能正确显示。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值