STM32基于标准库工程驱动DS1302

STM32基于标准库工程驱动DS1302


  • ✨申明:本文章仅发表在CSDN网站,任何其他网站,未注明来源,见此内容均为盗链和爬取,请多多尊重和支持原创!
  • 🍁对于文中所提供的相关资源链接将作不定期更换。
  • 📌相关篇《STM32基于HAL工程读取DS1302时间数据
  • 📍《STM32基于HAL工程通过硬件SPI驱动DS1302
  • 🎈驱动相关参考来源:https://www.cnblogs.com/qsyll0916/p/8127925.html
  • 🎯本工程使用STM32F103VE+DS1302实物验证没有问题。
🎉基于标准库工程,使用的是正点原子的工程模版创建,当然不局限与STM32其他型号的芯片的使用,只要是stm32芯片都可以使用该源文件进行驱动,方便适配移植,减少不必要的重复开发工作。
  • 📜串口打印信息:
    在这里插入图片描述

📓驱动文件

  • 🌿DS1302.h文件
#ifndef _DS1302_H
#define _DS1302_H

#include "stm32f10x.h"
#include "sys.h"

//DS1302引脚定义,可根据实际情况自行修改端口定义
#define DS1302_OutPut_Mode() {GPIOA->CRL &= 0xF0FFFFFF;GPIOA->CRL |= 0x03000000;}//将 GPIOA 口的 PA6 引脚设置成推挽输出模式,并清空了其他引脚的配置
#define DS1302_InPut_Mode()  {GPIOA->CRL &= 0xF0FFFFFF;GPIOA->CRL |= 0x08000000;}//PA7 引脚既可以作为普通的 GPIO 输出口
 
#define DS1302_IN  PAin(6)
#define DS1302_OUT PAout(6)
#define DS1302_RST PAout(5)
#define DS1302_CLK PAout(7)
 
typedef struct TIMEData
{
	u16 year;
	u8  month;
	u8  day;
	u8  hour;
	u8  minute;
	u8  second;
	u8  week;
}DS1302_Time_t;

void DS1302_Init(void);
void DS1302_WriteByte(u8 addr,u8 data);
u8   DS1302_ReadByte(u8 addr);
void DS1302_WriteTime(void);
void DS1302_ReadTime(void);
void DS1302_GetTime(DS1302_Time_t* time);
 
#endif



  • 🌿DS1302.c文件
#include "DS1302.h"
#include "delay.h"
#include "usart.h"
/*
DS1302接口:
	GPIOA_5 ->DS1302_RST
	GPIOA_6 ->DS1302_DAT
	GPIOA_7 ->DS1302_CLK
*/
//struct TIMEData TimeData;
//DS1302地址定义
#define DS1302_SEC_ADDR           0x80		//秒数据地址
#define DS1302_MIN_ADDR           0x82		//分数据地址
#define DS1302_HOUR_ADDR          0x84		//时数据地址
#define DS1302_DAY_ADDR           0x86		//日数据地址
#define DS1302_MONTH_ADDR         0x88		//月数据地址
#define DS1302_WEEK_ADDR          0x8a		//星期数据地址
#define DS1302_YEAR_ADDR          0x8c		//年数据地址
#define DS1302_CONTROL_ADDR       0x8e		//控制数据地址
#define DS1302_CHARGER_ADDR       0x90 		//充电功能地址			 
#define DS1302_CLKBURST_ADDR      0xbe
 
//初始时间定义
static u8 time_buf[8] = {0x20,0x19,0x04,0x12,0x15,0x07,0x00,0x06};//初始时间2019年4月12号15点07分00秒 星期五
u8 sec_buf=0;  //秒缓存
u8 sec_flag=0; //秒标志位
 
//DS1302初始化函数
void DS1302_Init() 
{
	/*1.GPIOC时钟*/
	RCC->APB2ENR |= 1<<2;
	/*2. 配置GPIOA_5/6/7模式*/
	GPIOA->CRL &= 0X000FFFFF;//先将 GPIOA 口的 CRL 寄存器的低 20 位清零,这样可以确保只修改 CRL 的高 12 位,不影响其他位。
	GPIOA->CRL |= 0X33300000;//将 GPIOA 口的前六个引脚(0~5)的模式和速率配置为推挽输出模式,最大输出速率50MHz
	GPIOA->ODR |=1<<6;//PA6输出高电平
}
//向DS1302写入一字节数据
void DS1302_WriteByte(u8 addr,u8 data) 
{
	u8 i;
	DS1302_RST=0; //禁止数据传输 !!!这条很重要
	DS1302_CLK=0; //确保写数据前SCLK为低电平
	DS1302_RST=1;	//启动DS1302总线	
	DS1302_OutPut_Mode();
	addr=addr&0xFE;  //最低位置零,寄存器0位为0时写,为1时读
	for(i=0;i<8;i++) //写入目标地址:addr
	{
		if (addr&0x01) DS1302_OUT=1;
		else DS1302_OUT=0;
		DS1302_CLK=1; //时钟上升沿写入数据
		DS1302_CLK=0;
		addr=addr>>1;
	}	
	for (i=0;i<8;i++) //写入数据:data
	{
		if(data&0x01) DS1302_OUT=1;
		else DS1302_OUT=0;
		DS1302_CLK=1;    //时钟上升沿写入数据
		DS1302_CLK=0;
		data = data >> 1;
	}
	DS1302_CLK=1;    // 将时钟电平置于高电平状态 ,处于已知状态
	DS1302_RST=0;	//停止DS1302总线
}
 
//从DS1302读出一字节数据
u8 DS1302_ReadByte(u8 addr) 
{
	u8 i,temp;	
	DS1302_RST=0; //这条很重要
	DS1302_CLK=0; //先将SCLK置低电平,确保写数居前SCLK被拉低
	DS1302_RST=1; //启动DS1302总线
	DS1302_OutPut_Mode();
	//写入目标地址:addr
	addr=addr|0x01; //最低位置高,寄存器0位为0时写,为1时读
	for(i=0;i<8;i++) 
	{
		if (addr&0x01) DS1302_OUT=1;
		else DS1302_OUT=0;
		DS1302_CLK=1; //写数据
		DS1302_CLK=0;
		addr = addr >> 1;
	}	
	//从DS1302读出数据:temp
	DS1302_InPut_Mode();
	for(i=0;i<8;i++)
	{
		temp=temp>>1;
		if (DS1302_IN) temp|=0x80;
		else temp&=0x7F;
		DS1302_CLK=1;
		DS1302_CLK=0;
	}	
	DS1302_CLK=1;  //将时钟电平置于已知状态
	DS1302_RST=0;	//停止DS1302总线
	return temp;
}
//向DS1302写入时钟数据,用于时间校准修改
void DS1302_WriteTime() 
{
	DS1302_WriteByte(DS1302_CONTROL_ADDR,0x00);       //关闭写保护 
	DS1302_WriteByte(DS1302_SEC_ADDR,0x80);           //暂停时钟 
	//DS1302_WriteByte(DS1302_CHARGER_ADDR,0xa9);     //涓流充电 
	DS1302_WriteByte(DS1302_YEAR_ADDR,time_buf[1]);   //年 
	DS1302_WriteByte(DS1302_MONTH_ADDR,time_buf[2]);  //月 
	DS1302_WriteByte(DS1302_DAY_ADDR,time_buf[3]);    //日 
	DS1302_WriteByte(DS1302_HOUR_ADDR,time_buf[4]);   //时 
	DS1302_WriteByte(DS1302_MIN_ADDR,time_buf[5]);    //分
	DS1302_WriteByte(DS1302_SEC_ADDR,time_buf[6]);    //秒
	DS1302_WriteByte(DS1302_WEEK_ADDR,time_buf[7]);	  //周 
	DS1302_WriteByte(DS1302_CHARGER_ADDR,0xA5);//打开充电功能 选择2K电阻充电方式
	DS1302_WriteByte(DS1302_CONTROL_ADDR,0x80);//打开写保护     
}
//从DS1302读出时钟数据
void DS1302_ReadTime(void)  
{
	time_buf[1]=DS1302_ReadByte(DS1302_YEAR_ADDR);          //年 
	time_buf[2]=DS1302_ReadByte(DS1302_MONTH_ADDR);         //月 
	time_buf[3]=DS1302_ReadByte(DS1302_DAY_ADDR);           //日 
	time_buf[4]=DS1302_ReadByte(DS1302_HOUR_ADDR);          //时 
	time_buf[5]=DS1302_ReadByte(DS1302_MIN_ADDR);           //分 
	time_buf[6]=(DS1302_ReadByte(DS1302_SEC_ADDR))&0x7f;    //秒,屏蔽秒的第7位,避免超出59
	time_buf[7]=DS1302_ReadByte(DS1302_WEEK_ADDR);          //周 	
}
 
//主函数
void DS1302_GetTime(DS1302_Time_t* time)
{ 
    DS1302_ReadTime(); //读取时间
    time->year=(time_buf[0]>>4)*1000+(time_buf[0]&0x0F)*100+(time_buf[1]>>4)*10+(time_buf[1]&0x0F); //计算年份
    time->month=(time_buf[2]>>4)*10+(time_buf[2]&0x0F);  //计算月份
    time->day=(time_buf[3]>>4)*10+(time_buf[3]&0x0F);    //计算日期
    time->hour=(time_buf[4]>>4)*10+(time_buf[4]&0x0F);   //计算小时
    time->minute=(time_buf[5]>>4)*10+(time_buf[5]&0x0F); //计算分钟
    time->second=(time_buf[6]>>4)*10+(time_buf[6]&0x0F); //计算秒钟
    time->week=(time_buf[7]&0x0F);                       //计算星期
  //printf("时间:%d-%d-%d %d:%d:%d %d \n",TimeData.year,TimeData.month,TimeData.day,TimeData.hour,TimeData.minute,TimeData.second,TimeData.week);																												
}


📝主程序驱动代码

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "DS1302.h"
int main(void)
{
    DS1302_Time_t time = {0};
	 const char *WEEK[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
    delay_init();            //延时函数初始化
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    uart_init(115200);   //串口初始化为115200
    DS1302_Init();   //DS1302引脚初始化
		
    while (1)
    {
			DS1302_GetTime(&time);
			printf("Current Time: %02d-%02d-%02d %02d:%02d:%02d T:%s\r\n", time.year, time.month, time.day, time.hour, time.minute, time.second,WEEK[time.week-1]);
        delay_ms(2000);
        delay_ms(2000);
        delay_ms(2000);
        delay_ms(2000);

    }
}

📚程序源码

  • ✨申明:本文章仅发表在CSDN网站,任何其他网站,未注明来源,见此内容均为盗链和爬取,请多多尊重和支持原创!
  • 🍁对于文中所提供的相关资源链接将作不定期更换。
链接: https://pan.baidu.com/s/1F_WIZCkYTWKIJojFbQ02kA
提取码: 9zze
  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值