当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 讲师博文 > RTC DS3231与8051微控制器的接口

RTC DS3231与8051微控制器的接口 时间:2021-03-19      来源:原创

您是否想过您的计算机和智能小工具如何显示时间?这是使用RTC(实时时钟)完成的。本教程介绍使用I2C与8051连接的DS3231 RTC

在学习完本教程之后,您将知道如何使用I2C协议DS3231 RTC编写嵌入式c代码

为了显示日期和时间,我同时连接了PC和LCD。在本文中,我将解释如何使用DS3231在LCD上显示日期和时间。

DS3231 RTC硬件连接

我选择了8051微控制器作为主机,而DS3231作为设备。

上拉电阻连接到微控制器的RTC的SDA和SCL引脚。

建议使用10K欧姆上拉电阻,以使RTC正常工作。

所述INT_RTC悬空并且可以用于产生用于外部或内部事件报警中断。

使用I2c将RTC DS3231与8051微控制器接口

连接图

要开始使用实时时钟,需要了解DS3231的工作原理。这是对RTC进行编程所需的步骤。

对DS3231编程的步骤

#1通过设置控制寄存器来初始化RTC

void Initialize_RTC void <字体> < / font >
{ <字体> < / font >
Write_To__RTC control_Register,0x00 ; <字体> < / font >
Write_To__RTC Status_Register,0x08 ; <字体> < / font >
}

当控制寄存器中的所有位都设置为零时,振荡器将运行其时钟,直到应用VBAT
 

但是,日期和时间不是必需的。由于不需要温度转换来显示时间和日期,因此请设置CONV = 0

少量 姓名 环境
0 A1IE 0
1个 A2IE 0
2个 情报网 0
3 RS1 0
4 RS2 0
5 转换 0
6 BBSQW 0
7 EOSC 0

#2通过设置状态寄存器初始化RTC

状态寄存器字节

该寄存器监视计时寄存器的状态,例如日期,月份,年份,分钟,小时和秒。

要启用该寄存器,请将EN32kHz位设置“ 1”

少量 姓名 环境
0 A1F 0
1个 A2F 0
2个 BSY 0
3 EN32kHz的 1个
4 0 0
5 0 0
6 0 0
7 OSF 0

#3使用计时寄存器设置日期和时间

 DS3231中的RTC寄存器

RTC地址 0x68
读取地址 D1
写地址 D0
日期 0x04
0x05
0x06
第二 0x00
分钟 0x01
小时 0x02

现在,您可以使用setTime和setDate函数设置日期和时间参数。

RTC有设定0x60的0x40的启用小时的格式和AM / PM。

void setTime unsigned char sethour,unsigned char setminute,unsigned char setsecond,short am_pm,short hour_twelve_twentyfour <字体> < / font >
{ <字体> < / font >
无符号char temp = 0 ; <字体> < / font >
Write_To__RTC 秒,Convert_DECIMAL_BCD setsecond )); <字体> < / font >
Write_To__RTC 分钟,Convert_DECIMAL_BCD setminute )); <字体> < / font >
开关hour_twelve_twentyfour <字体> < / font >
{<字体> < / font >
情况1 <字体> < / font >
{ <字体> < / font >
开关am_pm <字体> < / font >
{<字体> < / font >
情况1 <字体> < / font >
{ <字体> < / font >
temp = 0x60 ; <字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
默认值:<字体> < / font >
{ <字体> < / font >
temp = 0x40 ; <字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
} <字体> < / font >
Write_To__RTC 小时,(((temp | 0x1F Convert_DECIMAL_BCD sethour )))))); <字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
默认值:<字体> < / font >
{ <字体> < / font >
Write_To__RTC 小时,0x3F Convert_DECIMAL_BCD sethour )))); <字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
} <字体> < / font >
}

要设置日期,日期和月份,请使用04、05、06地址。时间和日历寄存器以BCD格式预定义。因此,我们必须将Decimal格式转换为BCD表示法以将数据写入RTC。

void setDate unsigned char setday,unsigned char setdate,unsigned char setmonth,unsigned char setyear <字体> < / font >
{ <字体> < / font >
Write_To__RTC 天,Convert_DECIMAL_BCD (设置日期))); <字体> < / font >
Write_To__RTC 日期,Convert_DECIMAL_BCD setdate ))); <字体> < / font >
Write_To__RTC 月,Convert_DECIMAL_BCD setmonth ))); <字体> < / font >
Write_To__RTC 年,Convert_DECIMAL_BCD setyear ))); <字体> < / font >
}

 

写入数据后,我们可以使用以下功能读取计时寄存器。

#4读取日期和时间

RTC中的日历寄存器和计时寄存器为BCD格式。因此,要读取RTC日期和时间,请将BCD格式转换为十进制表示法。

void Readtime void <字体> < / font >
{<字体> < / font >
无符号char temp = 0 ,hour_twelve_twentyfour,t; <字体> < / font >
RTCsec = Read_From_RTC ; <字体> < / font >
RTCsec = Convert_BCD_DECIMAL RTCsec ; <字体> < / font >
RTCmin = Read_From_RTC 分钟; <字体> < / font >
RTCmin = Convert_BCD_DECIMAL RTCmin ; <字体> < / font >
hour_twelve_twentyfour = 0 ; //输入24小时<font> </ font>
开关hour_twelve_twentyfour )<字体> < / font >
{<字体> < / font >
情况1 <字体> < / font >
{<字体> < / font >
temp = Read_From_RTC 小时; <字体> < / font >
temp&= 0x20 ; <字体> < / font >
t = )(temp >> 5 ; <字体> < / font >
RTC_hour = 0x1F Read_From_RTC 小时)); <字体> < / font >
RTC_hour = Convert_BCD_DECIMAL RTC_hour ; <字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
默认值:<字体> < / font >
{<字体> < / font >
RTC_hour = 0x3F Read_From_RTC 小时)); <字体> < / font >
RTC_hour = Convert_BCD_DECIMAL RTC_hour ; <字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
} <字体> < / font >
} <字体> < / font >
void ReadDate void <字体> < / font >
{ <字体> < / font >
RTCyear = Read_From_RTC ; <字体> < / font >
RTCyear = Convert_BCD_DECIMAL RTCyear ; <字体> < / font >
RTCmonth = 0x1F Read_From_RTC month )); <字体> < / font >
RTCmonth = Convert_BCD_DECIMAL RTCmonth ; <字体> < / font >
RTCdate = 0x3F Read_From_RTC date )); <字体> < / font >
RTCdate = Convert_BCD_DECIMAL RTCdate ; <字体> < / font >
RTCday = 0x07 Read_From_RTC )); <字体> < / font >
RTCday = Convert_BCD_DECIMAL RTCday ; <字体> < / font >
}

RTC DS3231的LCD功能

如果使用LCD显示日期和时间,则可能会遇到困难。因为RTC的时间和日期格式为整数格式。问题是LCD仅显示ASCII字符。因此,我为LCD的ASCII函数写了一个整数

将整数转换为ASCII格式的函数

  1. 提取整数。
  2. 添加0x30以转换为ASCII。
  3. 将ASCII字符存储在数组中。
  4. 将整数除以直到零。
  5. 反转数组以转换为原始形式。
void Show_Integer_Ascii unsigned char lineno,unsigned char cursor_position,unsigned long value )<字体> < / font >
{<字体> < / font >
无符号字符a [ 11 ] ,b [ 11 ] ,i,m,n; <字体> < / font >
if value == 0 && cursor_position == 4 <字体> < / font >
{<字体> < / font >
转到loop1; <字体> < / font >
} <字体> < / font >
否则if value == 0 )<字体> < / font >
{<字体> < / font >
b [ 0 ] = '0' ; <字体> < / font >
b [ 1 ] = '\ 0' ; <字体> < / font >
转到循环; <字体> < / font >
} <字体> < / font >
loop1:for i = 0 ; i < 11 ; i ++ )<字体> < / font >
{<字体> < / font >
a [ i ] = 值%10 + 0x30 ; <字体> < / font >
价值=价值/ 10 ; <字体> < / font >
if value == 0 )<字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
a [ i + 1 ] = '\ 0' ; <字体> < / font >
n = 0 ; <字体> < / font >
M = 1; M > = 0 ; M-- {<字体> < / FONT >
b [ n ] = a [ m ] <字体> < / font >
n ++; <字体> < / font >
如果m == 0 )<字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
b [ n ] = '\ 0' ; <字体> < / font >
循环:if lineno == 1 )<字体> < / font >
Disp_Data lineno,cursor_position,b ; <字体> < / font >
if lineno == 2 )<字体> < / font >
Disp_Data lineno,cursor_position,b ; <字体> < / font >
memset b,0 sizeof b )); <字体> < / font >
}

在液晶显示屏上显示日期

void Display_Date_LCD void )<字体> < / font >
{<字体> < / font >
ReadDate (); <字体> < / font >
Disp_Data 1 7 “/” ; <字体> < / font >
if RTCdate > = 0 && RTCdate < = 9 )<字体> < / font >
{ <字体> < / font >
Disp_Data 1 5 “0” ; <字体> < / font >
Show_Integer_Ascii 1 6 ,RTCdate ; <字体> < / font >
} <字体> < / font >
else <字体> < / font >
{ <字体> < / font >
Show_Integer_Ascii 1 5 ,RTCdate ; <字体> < / font >
} <字体> < / font >
Disp_Data 1 10 “/” ; <字体> < / font >
if RTCmonth > = 0 && RTCmonth < = 9 )<字体> < / font >
{<字体> < / font >
Disp_Data 1 8 “0” ; <字体> < / font >
Show_Integer_Ascii 1 9 ,RTCmonth ; <字体> < / font >
} <字体> < / font >
else <字体> < / font >
{ <字体> < / font >
Show_Integer_Ascii 1 8 ,RTCmonth ; <字体> < / font >
} <字体> < / font >
if RTCyear > = 0 && RTCyear < = 9 )<字体> < / font >
{ <字体> < / font >
Disp_Data 1 11 “0” ; <字体> < / font >
Show_Integer_Ascii 1 12 ,RTCyear ; <字体> < / font >
} <字体> < / font >
else <字体> < / font >
{ <字体> < / font >
Show_Integer_Ascii 1 11 ,RTCyear ; <字体> < / font >
} <字体> < / font >
}

在LCD上显示时间

void Readtime void <字体> < / font >
{<字体> < / font >
无符号char temp = 0 ,hour_twelve_twentyfour,t; <字体> < / font >
RTCsec = Read_From_RTC ; <字体> < / font >
RTCsec = Convert_BCD_DECIMAL RTCsec ; <字体> < / font >
RTCmin = Read_From_RTC 分钟; <字体> < / font >
RTCmin = Convert_BCD_DECIMAL RTCmin ; <字体> < / font >
hour_twelve_twentyfour = 0 ; //输入24小时<font> </ font>
开关hour_twelve_twentyfour )<字体> < / font >
{<字体> < / font >
情况1 <字体> < / font >
{<字体> < / font >
temp = Read_From_RTC 小时; <字体> < / font >
temp&= 0x20 ; <字体> < / font >
t = )(temp >> 5 ; <字体> < / font >
RTC_hour = 0x1F Read_From_RTC 小时)); <字体> < / font >
RTC_hour = Convert_BCD_DECIMAL RTC_hour ; <字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
默认值:<字体> < / font >
{<字体> < / font >
RTC_hour = 0x3F Read_From_RTC 小时)); <字体> < / font >
RTC_hour = Convert_BCD_DECIMAL RTC_hour ; <字体> < / font >
休息; <字体> < / font >
} <字体> < / font >
} <字体> < / font >
}

RTC DS3231的C代码

这是读取RTC日期和时间的完整C代码。我已经使用8051微控制器的两个引脚通过I2C与实时时钟进行通信。

#include <reg51.h> <font> </ font>
#include“ header.h” <font> </ font>
void main ()<字体> < / font >
{<字体> < / font >
lcd_init (); <字体> < / font >
lcd_delay 2 ; <字体> < / font >
Disp_Data 1 0 “DS3231接口” ; <字体> < / font >
Disp_Data 2 0 “通过Codrey.com” ; <字体> < / font >
lcd_delay 10 ; <字体> < / font >
Disp_Data 1 0 “” ; <字体> < / font >
Disp_Data 2 0 “” ; <字体> < / font >
Initialize_RTC ; / *初始化RTC DS3231 * / <字体> < / font >
lcd_delay 2 ; <字体> < / font >
时刻设定10 20 25 0 0 ; / *设置小时,分钟,秒* / <字体> < / font >
的setDate 2 16 05 18 ; / *设置日期,日期,月份,年份* / <字体> < /字体>
<字体> < / font >
/ *无限WHILE循环,用于读取RTC的日期和时间* / <字体> < / font >
Disp_Data 1 0 “DATE” ; <字体> < / font >
Disp_Data 2 0 “TIME” ; <字体> < / font >
ReadDate ; //获取日,月和年<font> </ font>
Display_Date_LCD ; <字体> < / font >
<字体> < / font >
ReadTime (); / *从DS3231获取时间* / <字体> < / font >
Display_Time_LCD ; <字体> < / font >
}

RTC的I2c功能

以下是使用I2c与RTC进行通信的步骤。

  1. 使用开始条件开始I2C通信。
  2. 写入RTC地址。
  3. 阅读确认。
  4. 写寄存器写地址。
  5. 从RTC读取数据。
  6. 阅读确认书
  7. 不写任何确认。
  8. 停止i2c通信。
void Start_I2C void )<字体> < / font >
{<字体> < / font >
SCL_DISABLE; <字体> < / font >
SDA_ENABLE; <字体> < / font >
SCL_ENABLE; <字体> < / font >
SDA_DISABLE; <字体> < / font >
} <字体> < / font >
void Slave_Write unsigned char byte <字体> < / font >
{<字体> < / font >
无符号字符j,k; <字体> < / font >
k =字节;<字体> < / font >
对于j = 0 ; j < 8 ; j ++ )<字体> < / font >
{<字体> < / font >
SCL_DISABLE; <字体> < / font >
SDA = k&0x80 >> j ))1 0 ; / *写bit_by_bit * / <字体> < / font >
SCL_ENABLE; <字体> < / font >
} <字体> < / font >
} <字体> < / font >
void Read_Ack void )<字体> < / font >
{<字体> < / font >
SCL_DISABLE; <字体> < / font >
SDA_ENABLE; <字体> < / font >
SCL_ENABLE; <字体> < / font >
SDA ; <字体> < / font >
} <字体> < / font >
void Read_Ack void )<字体> < / font >
{<字体> < / font >
SCL_DISABLE; <字体> < / font >
SDA_ENABLE; <字体> < / font >
SCL_ENABLE; <字体> < / font >
SDA ; <字体> < / font >
} <字体> < / font >
<字体> < / font >
void No_Acknowledgement void <字体> < / font >
{<字体> < / font >
SCL_DISABLE; <字体> < / font >
SDA_ENABLE; <字体> < / font >
SCL_ENABLE; <字体> < / font >
} <字体> < / font >
unsigned char Read_I2C_Data void )<字体> < / font >
{<字体> < / font >
无符号字符m,data_byte = 0 ; <字体> < / font >
对于m = 0 ; m < 8 ; m ++ )<字体> < / font >
{<字体> < / font >
SCL_DISABLE; <字体> < / font >
SCL_ENABLE; <字体> < / font >
如果SDA )<字体> < / font >
data_byte | = 0x80 >> m; <字体> < / font >
} <字体> < / font >
返回data_byte; <字体> < / font >
} <字体> < / font >
<字体> < / font >
unsigned char Read_From_RTC unsigned char地址< font > < / font >
{ <字体> < / font >
无符号char val = 0 ; <字体> < / font >
Start_I2C (); <字体> < / font >
Slave_Write DS3231_Write ; <字体> < / font >
Read_Ack (); <字体> < / font >
Slave_Write 地址; <字体> < / font >
Read_Ack (); <字体> < / font >
Start_I2C (); <字体> < / font >
Slave_Write DS3231_Read ; <字体> < / font >
Read_Ack (); <字体> < / font >
val = Read_I2C_Data (); <字体> < / font >
No_Acknowledgement ; <字体> < / font >
Stop_I2C (); <字体> < / font >
返回VAL; <字体> < / font >
} <字体> < / font >
<字体> < / font >
void Write_To__RTC unsigned char regaddress,unsigned char val <字体> < / font >
{ <字体> < / font >
unsigned char loop_time; <字体> < / font >
Start_I2C (); <字体> < / font >
Slave_Write DS3231_Write ; <字体> < / font >
Read_Ack (); <字体> < / font >
Slave_Write regaddress ; <字体> < / font >
Read_Ack (); <字体> < / font >
Slave_Write val ; <字体> < / font >
Read_Ack (); <字体> < / font >
Stop_I2C (); <字体> < / font >
for loop_time = 0 ; loop_time < 255 ; loop_time ++ ; <字体> < / font >
for loop_time = 0 ; loop_time < 255 ; loop_time ++ ; <字体> < / font >
}

变形模拟

RTC DS3231与8051微控制器的接口-原理图

DS3231的应用

  1. 用于GPS中以获取日期,时间,纬度,经度,位置,高度
  2. 用于服务器中以实现网络定时协议
  3. 在智能功率计中用于跟踪当前账单的日期和时间。
  4. 用于电信和网络应用。

最后的想法

RTC DS3231精确地保持低漂移的精确时间。这使其非常适合计时应用。

DS3231高度准确,可以管理日期,时间,年,月,日和秒。

此外,RTC具有±2ppm的精度,适合实时功能。

希望您了解如何使用I2C将DS3231 RTC与8051连接。由于8051没有内部i2c,因此我使用位冲击方法来生成时钟和数据以进行串行通信

整个代码已经通过8051微控制器进行了测试,并且可以在任何稍作改动的情况下与任何微控制器一起使用。

 

上一篇:将实时时钟(RTC)DS3231与8051微控制器配合使用

下一篇:学会单片机的UART,就学会了通信,UART详解

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部