文章目录
写在前面
因为毕业设计,需要用到记录时间的功能,对时钟模块一直只闻其名,却从未用过。之前的在使用其他模块的时候,总是一个劲的拿来主义,经常是在别人现成的代码上改改宏定义就直接进行使用,一旦项目需要用到的模块多了起来,每个模块别人写好一个库,在不清楚其基本原理的情况下整个项目就变得臃肿不堪了。(据我所知很多同学本科阶段使用模块都是这样一个模式)。
那么现在在刚回顾和复习完IIC通讯协议下,在这里我将IIC协议实践在DS3231时钟模块上。
文件结构,方便扩展 和 代码管理。
这里建立两个库: softwareIIC.h 和DS3231.h
DS3231.h 即存储DS3231的寄存器定义,时间变量结构体定义,等等。
softwareIIC.h即存储相关IIC的函数定义,软件 IIC 占用的 IO口定义,等等。
在使用上,只需要在DS3231.c中 #include "softwareIIC.h"即可。
同理,因为我们将模块和 IIC 协议进行了分离, 在项目中需要加到其他使用IIC协议的模块时,也只需要在对应模块的文件中 调用软件IIC的头文件 即可。
那么在之后其他项目也可以使用这个时候写好的 软件IIC 库, 只需要改改softwareIIC.h 里对于占用端口的宏定义即可, 十分方便代码的移植😉👍。
若你是初学者(虽然我也是),希望你能养成这样的一个模式、习惯,这对之后的帮助异常的大。
关于DS3231
DS3231是低成本、高精度的I2C实时时钟(RTC)。该器件包括电池输入端,断开主电源时,仍可保持精准计时。
RTC保存秒、分、时、星期、月和年信息。少于31天的月份,将自动调整月末的日期,包括闰年修正。时钟格式可以时24小时或带AM/PM的12小时格式。提供两个可设置的日历闹钟和1Hz输出。

在这里我用的是在某宝上购买的模块,已经预留出了VCC、GND、SDA、SCL。
DS3231 寄存器设置

第一眼看上去可能有点不明所以,但其实很简单。DS3231采用8421BCD码用来存储时间、日期等数据。(什么是8421BCD码? 你可以简单理解为,一般用四位二进制表示一位数字,比如十进制数字58,对应的8421BCD码即:0101 1000 , 这里1000代表个位数的8 , 0101代表十位数的 5 。)
比如Seconds(秒),寄存器地址是0x00,我们需要读取和设置 秒 ,也只需要对这个寄存器进行读写即可。
秒范围是 00 - 59,故第四位用来存储个位数0 - 9,高三位用来存储十位数 0 - 5 ( 000 - 101)。
其他寄存器同理。
另外关于采用 24小时制 还是 12小时制度,取决于Hours寄存器(0x02)中的第6位。

代码
欧克,关于IIC 借助我上一篇博客相信已经有所掌握,现在我们直接将其使用在和DS3231的通讯和设置中。
softwareIIC.h
#ifndef ___SOFTWARE_IIC
#define ___SOFTWARE_IIC
#include "stm32f10x.h"
#include "./sys/sys.h"
#define IIC_SDA_GPIOx GPIOA
#define IIC_SDA_GPIO_Pin GPIO_Pin_11
#define IIC_SDA_GPIO_RCC RCC_APB2Periph_GPIOA
#define IIC_SDA_RCCPeriphClockcmd RCC_APB2PeriphClockCmd
#define IIC_SCL_GPIOx GPIOA
#define IIC_SCL_GPIO_Pin GPIO_Pin_12
#define IIC_SCL_GPIO_RCC RCC_APB2Periph_GPIOA //上面已经定义过了
#define IIC_SCL_RCCPeriphClockcmd RCC_APB2PeriphClockCmd
#define IIC_SCLSDA_GPIO_RCC RCC_APB2Periph_GPIOA
//使用4线串行接口时使用
#define IIC_SDA PAout(11)
#define IIC_SCL PAout(12)
#define READ_SDA GPIO_ReadInputDataBit(IIC_SDA_GPIOx,IIC_SDA_GPIO_Pin)
void IIC_Init(void);
void IIC_Start(void); //产生起始条件(符)
void IIC_Stop(void); //产生结束条件(符)
uint8_t IIC_Wait_Ask(void);
void IIC_Ack(void);
void IIC_NAck(void);
void IIC_WriteByte(u8 data);
u8 IIC_Read_Byte(unsigned char ack);
#endif // ___SOFTWARE_IIC
software.c
#include "./softwareIIC/softwareIIC.h"
#include "./systick/bsp_systick.h"
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructer;
//开启时钟
IIC_SDA_RCCPeriphClockcmd(IIC_SDA_GPIO_RCC, ENABLE); //or IIC_SCL_GPIOx ,因为 sda scl 使用的是同一个gpiox
//定义pin
GPIO_InitStructer.GPIO_Pin=IIC_SDA_GPIO_Pin | IIC_SCL_GPIO_Pin; //10--SCL 11--SDA //PB10 PB11
//定义频率
GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz;
//定义IO模式
GPIO_InitStructer.GPIO_Mode=GPIO_Mode_Out_PP;
//初始化
GPIO_Init(IIC_SDA_GPIOx, &GPIO_InitStructer);
}
static void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructer;
GPIO_InitStructer.GPIO_Pin= IIC_SDA_GPIO_Pin;
GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructer.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出模式
GPIO_Init(IIC_SDA_GPIOx, &GPIO_InitStructer);
}
static void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructer;
GPIO_InitStructer.GPIO_Pin= IIC_SDA_GPIO_Pin;
GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructer.GPIO_Mode=GPIO_Mode_IPU; //上拉输入模式
GPIO_Init(IIC_SDA_GPIOx, &GPIO_InitStructer);
}
void IIC_Start(void) <

本文介绍了如何通过IIC通信协议实现DS3231实时时钟模块的时间设置与读取功能。从软件IIC库的搭建到DS3231模块的具体操作,详细讲解了每个步骤,并提供了完整的代码示例。
最低0.47元/天 解锁文章
1万+

被折叠的 条评论
为什么被折叠?



