一、DS1302时钟模块介绍
DS1302 是一种常见的实时时钟(RTC)模块,广泛用于需要时间跟踪的嵌入式系统。它可以提供准确的年、月、日、星期、小时、分钟、秒等时间信息,并且有内建的电池供电功能,可以在断电时继续保持时间。
主要特点:
- 时钟与日历功能:能够提供秒、分、时、日、月、年、星期等日期时间信息。
- 内置电池:DS1302内置一颗外部可更换的电池(通常为CR2032锂电池),可在没有主电源时继续维持时间的准确性,电池寿命一般可达5年以上。
- 低功耗设计:相较于其他时钟模块,DS1302的功耗较低,适合长时间运行。
- 简易通信:DS1302通过串行接口(SPI)与单片机通信。与I2C相比,SPI通信速度更快,且连接更简单。
- 外部晶振:内部使用32.768kHz的石英晶振,具有较高的时间准确性。
优缺点:
- 优点:低功耗、易于使用、提供准确的时间、内置电池保持时间。
- 缺点:与一些高级RTC模块相比,DS1302的精度和稳定性稍逊,且SPI接口需要更多的引脚。
二、DS1302时钟模块接线说明
DS1302 时钟模块接线说明
DS1302 引脚 | 连接目标 | 说明 |
---|---|---|
VCC | 3.3V 或 5V | 主电源引脚,DS1302 的工作电压范围为 2.0V 至 5.5V,通常接 3.3V 或 5V。 |
GND | GND | 电源地,连接单片机的 GND。 |
CLK | 单片机的任意数字引脚(如 Arduino 的 D7) | 时钟信号输入引脚,用于同步数据传输。 |
DAT | 单片机的任意数字引脚(如 Arduino 的 D6) | 数据输入/输出引脚,用于与单片机通信。 |
RST | 单片机的任意数字引脚(如 Arduino 的 D5) | 复位信号引脚,高电平有效,用于启动或停止数据传输。 |
三、测试说明、DS1302时钟模块驱动代码
编译环境:keil5
测试单片机: STM32F103C8T6
功能:功能1:采集年月日时分秒数据在OLED屏幕上显示出来
功能2:把采集年月日时分秒数据发送到串口调试助手上
DS1302.c文件编写时钟模块驱动代码如下:
uint8_t time_buf[8] = {0x20};//初始时间
uint8_t readtime[8] = {0x20};//当前时间
DS1302ClassStruct DS1302Class = {
.Init = DS1302_Init,
.SetTime = DS1302_SetTime,
.GetTime = DS1302_GetTime
};
static void DS1302_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DS1302_CLK_CLK | DS1302_DAT_CLK | DS1302_RST_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin=DS1302_CLK_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(DS1302_CLK_PORT,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=DS1302_RST_PIN;
GPIO_Init(DS1302_RST_PORT,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=DS1302_DAT_PIN;
GPIO_Init(DS1302_DAT_PORT,&GPIO_InitStructure);
}
//向DS1302写入一字节数据
static void DS1302_WriteByte(uint8_t addr,uint8_t data)
{
uint8_t i;
DS1302_RST_0; //禁止数据传输 !!!这条很重要
DS1302_CLK_0; //确保写数据前SCLK为低电平
DS1302_RST_1; //启动DS1302总线
DS1302_DAT_OutPut_Mode();
addr=addr&0xFE; //最低位置零,寄存器0位为0时写,为1时读
for(i=0;i<8;i++) //写入目标地址:addr
{
if (addr&0x01) DS1302_DAT_1;
else DS1302_DAT_0;
DS1302_CLK_1; //时钟上升沿写入数据
DS1302_CLK_0;
addr=addr>>1;
}
for (i=0;i<8;i++) //写入数据:data
{
if(data&0x01) DS1302_DAT_1;
else DS1302_DAT_0;
DS1302_CLK_1; //时钟上升沿写入数据
DS1302_CLK_0;
data = data >> 1;
}
DS1302_CLK_1; // 将时钟电平置于高电平状态 ,处于已知状态
DS1302_RST_0; //停止DS1302总线
}
//从DS1302读出一字节数据
static uint8_t DS1302_ReadByte(uint8_t addr)
{
uint8_t i,temp;
DS1302_RST_0; //这条很重要
DS1302_CLK_0; //先将SCLK置低电平,确保写数居前SCLK被拉低
DS1302_RST_1; //启动DS1302总线
DS1302_DAT_OutPut_Mode();
//写入目标地址:addr
addr=addr|0x01; //最低位置高,寄存器0位为0时写,为1时读
for(i=0;i<8;i++)
{
if (addr&0x01) DS1302_DAT_1;
else DS1302_DAT_0;
DS1302_CLK_1; //写数据
DS1302_CLK_0;
addr = addr >> 1;
}
//从DS1302读出数据:temp
DS1302_DAT_InPut_Mode();
for(i=0;i<8;i++)
{
temp=temp>>1;
if (DS1302_DAT_IN()) temp|=0x80;
else temp&=0x7F;
DS1302_CLK_1;
DS1302_CLK_0;
}
DS1302_CLK_1; //将时钟电平置于已知状态
DS1302_RST_0; //停止DS1302总线
return temp;
}
static void DS1302_SetTime(uint8_t *writeTime)
{
DS1302_WriteByte(DS1302_CONTROL_ADDR,0x00); //关闭写入
DS1302_WriteByte(DS1302_SEC_ADDR,0x80); //暂停时钟
DS1302_WriteByte(DS1302_YEAR_ADDR,writeTime[1]); //年
DS1302_WriteByte(DS1302_MONTH_ADDR,writeTime[2]); //月
DS1302_WriteByte(DS1302_DAY_ADDR,writeTime[3]); //日
DS1302_WriteByte(DS1302_HOUR_ADDR,writeTime[4]); //时
DS1302_WriteByte(DS1302_MIN_ADDR,writeTime[5]); //分
DS1302_WriteByte(DS1302_SEC_ADDR,writeTime[6]); //秒
DS1302_WriteByte(DS1302_WEEK_ADDR,writeTime[7]); //周
DS1302_WriteByte(DS1302_CHARGER_ADDR,0xA5);//打开充电功能 选择2K电阻充电方式
DS1302_WriteByte(DS1302_CONTROL_ADDR,0x80);//打开写入
}
static void DS1302_GetTime(DS1302TimeStruct *timeData)
{
uint8_t readtime[8] = {0x20};//当前时间
readtime[1]=DS1302_ReadByte(DS1302_YEAR_ADDR); //年
readtime[2]=DS1302_ReadByte(DS1302_MONTH_ADDR); //月
readtime[3]=DS1302_ReadByte(DS1302_DAY_ADDR); //日
readtime[4]=DS1302_ReadByte(DS1302_HOUR_ADDR); //时
readtime[5]=DS1302_ReadByte(DS1302_MIN_ADDR); //分
readtime[6]=(DS1302_ReadByte(DS1302_SEC_ADDR))&0x7f; //秒,屏蔽秒的第7位,避免超出59
readtime[7]=DS1302_ReadByte(DS1302_WEEK_ADDR); //周
timeData->year=(readtime[0]>>4)*1000+(readtime[0]&0x0F)*100+(readtime[1]>>4)*10+(readtime[1]&0x0F); //计算年份
timeData->month=(readtime[2]>>4)*10+(readtime[2]&0x0F); //计算月份
timeData->day=(readtime[3]>>4)*10+(readtime[3]&0x0F); //计算日期
timeData->hour=(readtime[4]>>4)*10+(readtime[4]&0x0F); //计算小时
timeData->minute=(readtime[5]>>4)*10+(readtime[5]&0x0F); //计算分钟
timeData->second=(readtime[6]>>4)*10+(readtime[6]&0x0F); //计算秒钟
timeData->week=(readtime[7]&0x0F); //计算星期
}
四、串口调试助手把采集的心率血氧数据发送出来
五、串口调试助手软件下载
串口调试助手-keil5调试工具_stm32水位传感器资源-CSDN文库
六、源代码
STM32单片机+DS1302时钟模块+OLED屏幕+时钟数据发送到串口调试助手+源代码资源-CSDN文库