使用STM32和DS3231 RTC:设置并获取时间和日期

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

使用STM32和DS3231 RTC:设置并获取时间和日期——笔记
在本文中,将使用STM32开发一个驱动程序,用于在DS3231中设置和获取时间存储。

在本文中,将介绍以下内容:
DS3231模块。

与STM32F411核-64的连接。

源文件。

产品图片
DS3231模块
DS3231是一款低成本、极其精确的I 2 C实时时钟(RTC),集成温度补偿晶体振荡器(TCXO)和晶体。

该器件集成了电池输入,并在器件的主电源中断时保持精确的计时。

晶体谐振器的集成提高了设备的长期精度,并减少了生产线中的零件数量。

RTC 维护秒、分钟、小时、星期、日期、月份和年份信息。

对于少于31 天的月份,月底的日期会自动调整,包括闰年的更正。

时钟以24 小时制或12 小时制运行,带有AM/PM 指示器。

提供两个可编程时间闹钟和一个可编程方波输出。

地址和数据通过I 2 C双向总线串行传输。

该模块可在3.3 或5 V 电压下工作,适用于许多开发平台或微控制器。

电池输入为3V,典型的CR2032 3V电池可以为模块供电并保持信息超过一年。

与STM32F411核-64的连接:
在开始开发驱动器之前,需要I2C多读和多写才能使DS3231工作。

我们首先创建名称为ds3231.h 的新头文件。

在头文件中,我们将声明一个结构如下:
该结构将包含以下内容:
秒。

分。

小时。

月中的某天。

月。

年。

计算所需的其他数据。

此外,声明以下三个函数:
首先是设置时间和数据,并以结构为参数。

第二个是从DS3231读取时间,并获取指向结构的指针。

第三个功能将打印时间。

因此,整个头文件如下所示:
创建一个名称为ds3231.c 的新源代码。

在此声明以下宏:
此外,还有两个功能:
第一个将 dec 转换为 BCD 的方法:
第二个是将 BCD 转换为 dec :
为了设置时间和日期:
由于我们已经超过了2000 年,因此我们将世纪位设置为1:
并从给定年份中减去2000。

然后将变量转换为BCD,并将变量发送到DS3231,以设置时间和日期。

为了获得时间:
为了获取时间,它类似于设置时间,但使用BCD 来减少并将2000 添加到年份中。

要打印时间:
在main.c 文件中:
包括头文件,如下所示:
声明结构:
然后在结构中设置时间和日期:
调用DS3231_set函数:
在1 个循环中:
调用获取时间函数,然后调用打印时间函数并等待半秒:
将代码编译并加载到STM32F411并打开串行终端应用程序后,得到设置的内容:
ds3231.c源码:
#include "ds3231.h"
#include "i2c.h"
#define DS3231_I2C_ADDR 0x68
// time keeping registers
#define DS3231_TIME_CAL_ADDR 0x00
#define DS3231_ALARM1_ADDR 0x07
#define DS3231_ALARM2_ADDR 0x0B
#define DS3231_CONTROL_ADDR 0x0E
#define DS3231_STATUS_ADDR 0x0F
#define DS3231_AGING_OFFSET_ADDR 0x10
#define DS3231_TEMPERATURE_ADDR 0x11
// control register bits
#define DS3231_CONTROL_A1IE 0x1/* Alarm 2 Interrupt Enable */
#define DS3231_CONTROL_A2IE 0x2/* Alarm 2 Interrupt Enable */
#define DS3231_CONTROL_INTCN 0x4/* Interrupt Control */
#define DS3231_CONTROL_RS10x8/* square-wave rate select 2 */
#define DS3231_CONTROL_RS2 0x10/* square-wave rate select 2 */
#define DS3231_CONTROL_CONV 0x20/* Convert Temperature */
#define DS3231_CONTROL_BBSQW 0x40/* Battery-Backed Square-Wave Enable */ #define DS3231_CONTROL_EOSC0x80/* not Enable Oscillator, 0 equal on */
// status register bits
#define DS3231_STATUS_A1F 0x01/* Alarm 1 Flag */
#define DS3231_STATUS_A2F 0x02/* Alarm 2 Flag */
#define DS3231_STATUS_BUSY 0x04/* device is busy executing TCXO */ #define DS3231_STATUS_EN32KHZ 0x08/* Enable 32KHz Output */
#define DS3231_STATUS_OSF 0x80/* Oscillator Stop Flag */
static uint8_t dectobcd(const uint8_t val)
{
return ((val / 10 * 16) + (val % 10));
}
static uint8_t bcdtodec(const uint8_t val)
{
return ((val / 16 * 10) + (val % 16));
}
void DS3231_set(ts t)
{
uint8_t i, century;
century = 0x80;
t.year_s = t.year - 2000;
uint8_t TimeDate[7] = { t.sec, t.min, t.hour, t.wday, t.mday, t.mon, t.year_s };
for (i=0;i<=6;i++)
{
TimeDate[i] = dectobcd(TimeDate[i]);
if(i == 5){TimeDate[5] |= century;}
}
i2c_WriteMulti(DS3231_I2C_ADDR,DS3231_TIME_CAL_ADDR,(char*)TimeDate,7); }
void DS3231_get(ts *t)
{
uint8_t TimeDate[7]; //second,minute,hour,dow,day,month,year
uint8_t i;
uint16_t year_full;
i2c_ReadMulti(DS3231_I2C_ADDR,DS3231_TIME_CAL_ADDR,7,(char*)TimeDate);
for (i = 0; i <= 6; i++) {
if (i == 5) {
TimeDate[5] = bcdtodec(TimeDate[i] & 0x1F);
} else
TimeDate[i] = bcdtodec(TimeDate[i]);
}
year_full = 2000 + TimeDate[6];
t->sec = TimeDate[0];
t->min = TimeDate[1];
t->hour = TimeDate[2];
t->mday = TimeDate[4];
t->mon = TimeDate[5];
t->year = year_full;
t->wday = TimeDate[3];
t->year_s = TimeDate[6];
}
void print_time(ts *t)
{
printf("Current DS3231 Time: %d:%d:%d\r\n",t->hour,t->min,t->sec);
printf("Current DS3231 Date: %d/%d/%d\r\n",t->year,t->mon,t->mday);
}
Ds3231.h源码:
#ifndef DS3231_H_
#define DS3231_H_
#include "stdint.h"
typedef struct ts {
uint8_t sec; /* seconds */
uint8_t min; /* minutes */
uint8_t hour; /* hours */
uint8_t mday; /* day of the month */
uint8_t mon; /* month */
int16_t year; /* year */
uint8_t wday; /* day of the week */
uint8_t yday; /* day in the year */
uint8_t isdst; /* daylight saving time */
uint8_t year_s; /* year in short notation*/
}ts;
void DS3231_set(ts t);
void DS3231_get(ts *t);
void print_time(ts *t);
#endif /* DS3231_H_ */
IIC.c源码:
#include "i2c.h"
uint8_t inited=0;
void i2c_init(void){
if(inited==0){
RCC->AHB1ENR|=RCC_AHB1ENR_GPIOBEN; //enable gpiob clock RCC->APB1ENR|=RCC_APB1ENR_I2C1EN; //enable i2c1 clock
GPIOB->MODER|=0xA0000; //set pb8and9 to alternative function GPIOB->AFR[1]|=0x44;
GPIOB->OTYPER|=GPIO_OTYPER_OT8|GPIO_OTYPER_OT9; //set pb8 and pb9 as open drain I2C1->CR1=I2C_CR1_SWRST;
I2C1->CR1&=~I2C_CR1_SWRST;
I2C1->CR2|=50;
I2C1->CCR=80;
I2C1->TRISE=17; //output max rise
I2C1->CR1|=I2C_CR1_PE;
inited=1;
}
}
char i2c_readByte(char saddr,char maddr, char *data)
{
while(I2C1->SR2&I2C_SR2_BUSY){;}
I2C1->CR1|=I2C_CR1_START;
while(!(I2C1->SR1&I2C_SR1_SB)){;}
I2C1->DR=saddr<<1;
while(!(I2C1->SR1&I2C_SR1_ADDR)){;}
(void)I2C1->SR2;
while(!(I2C1->SR1&I2C_SR1_TXE)){;}
I2C1->DR=maddr;
while(!(I2C1->SR1&I2C_SR1_TXE)){;}
I2C1->CR1|=I2C_CR1_START;
while(!(I2C1->SR1&I2C_SR1_SB)){;}
I2C1->DR=saddr<<1|1;
while(!(I2C1->SR1&I2C_SR1_ADDR)){;}
I2C1->CR1&=~I2C_CR1_ACK;
(void)I2C1->SR2;
I2C1->CR1|=I2C_CR1_STOP;
while(!(I2C1->SR1&I2C_SR1_RXNE)){;}
*data++=I2C1->DR;
return 0;
}
void i2c_writeByte(char saddr,char maddr,char data)
{
while(I2C1->SR2&I2C_SR2_BUSY){;} /*wait until bus not busy*/
I2C1->CR1|=I2C_CR1_START; /*generate start*/
while(!(I2C1->SR1&I2C_SR1_SB)){;} /*wait until start bit is set*/
I2C1->DR = saddr<< 1; /* Send slave address*/
while(!(I2C1->SR1&I2C_SR1_ADDR)){;} /*wait until address flag is set*/
(void)I2C1->SR2; /*clear SR2 by reading it */
while(!(I2C1->SR1&I2C_SR1_TXE)){;} /*Wait until Data register empty*/
I2C1->DR = maddr; /* send memory address*/
while(!(I2C1->SR1&I2C_SR1_TXE)){;} /*wait until data register empty*/
I2C1->DR = data;
while (!(I2C1->SR1 & I2C_SR1_BTF)); /*wait until transfer finished*/
I2C1->CR1 |=I2C_CR1_STOP;/*Generate Stop*/
}
void i2c_WriteMulti(char saddr,char maddr,char *buffer, uint8_t length)
{
while (I2C1->SR2 & I2C_SR2_BUSY); //wait until bus not busy
I2C1->CR1 |= I2C_CR1_START; //generate start
while (!(I2C1->SR1 & I2C_SR1_SB)){;}//wait until start is generated I2C1->DR = saddr<< 1; // Send slave address
while (!(I2C1->SR1 & I2C_SR1_ADDR)){;} //wait until address flag is set
(void) I2C1->SR2; //Clear SR2
while (!(I2C1->SR1 & I2C_SR1_TXE)); //Wait until Data register empty
I2C1->DR = maddr; // send memory address while (!(I2C1->SR1 & I2C_SR1_TXE)); //wait until data register empty
//sending the data
for (uint8_t i=0;i<length;i++)
{
I2C1->DR=buffer[i]; //filling buffer with command or data
while (!(I2C1->SR1 & I2C_SR1_BTF));
}
I2C1->CR1 |= I2C_CR1_STOP;//wait until transfer finished
}
void i2c_ReadMulti(char saddr,char maddr, int n, char* data)
{
while (I2C1->SR2 & I2C_SR2_BUSY){;}
I2C1->CR1|=I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB)){;}
I2C1->DR=saddr<<1;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){;}
(void)I2C1->SR2;
while(!(I2C1->SR1&I2C_SR1_TXE)){;}
I2C1->DR = maddr;
while(!(I2C1->SR1&I2C_SR1_TXE)){;}
I2C1->CR1|=I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB)){;}
I2C1->DR=saddr<<1|1;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){;}
(void)I2C1->SR2;
I2C1->CR1|=I2C_CR1_ACK;
while(n>0U)
{
if(n==1U)
{
I2C1->CR1&=~I2C_CR1_ACK;
I2C1->CR1|=I2C_CR1_STOP;
while(!(I2C1->SR1&I2C_SR1_RXNE)){;}
*data++=I2C1->DR;
break;
}
else
{
while(!(I2C1->SR1&I2C_SR1_RXNE)){;}
(*data++)=I2C1->DR;
n--;
}
}
}
void i2c_bus_scan(void)
{
int a=0; //address variable
for (uint8_t i=0;i<128;i++) //go through all 127 address
{
I2C1->CR1 |= I2C_CR1_START; //generate start
while(!(I2C1->SR1 & I2C_SR1_SB)); // wait to start to be generated
I2C1->DR=(i<<1|0); // transmit the address
while(!(I2C1->SR1)|!(I2C1->SR2)){}; //clear status register
I2C1->CR1 |= I2C_CR1_STOP; //generate stop condition
delayuS(100);//minium wait time is 40 uS, but for sure, leave it 100 uS
a=(I2C1->SR1&I2C_SR1_ADDR); //read the status register address set
if (a==2)//if the address is valid
{
//print the address
printf("Found I2C device at adress 0x%X (hexadecimal), or %d (decimal)\r\n",i,i);
}
}
}
IIC.h源码:
#ifndef __i2c_H
#define __i2c_H
//#include "stm32f7xx.h" // Device header
#include "stm32f4xx.h" // Device header
#include "delay.h"
#include <stdint.h>
#include "stdio.h"
void i2c_init(void);
char i2c_readByte(char saddr,char maddr,char *data);
void i2c_writeByte(char saddr,char maddr,char data);
void i2c_WriteMulti(char saddr,char maddr,char *buffer, uint8_t length);
void i2c_ReadMulti(char saddr,char maddr, int n, char* data);
void i2c_bus_scan(void);
#endif。

相关文档
最新文档