HAL库读取RTC数据发给串口助手

实验目的

了解实时时钟RTC的原理。STM32芯片自带RTC,因此不须像其他MCU需外接RTC模块。请编程实现STM32的日历读取、设置和输出。

要求:

1)读取RTC初始时间,验证是否为 1970年1月1日零分零秒;

2)将RTC时间调整为当前时间,并以 2021年x月x日x分x秒的格式从串口输出(或输出到OLED屏),每1s改变一次;

3)如果输出内容中需加入“星期x”,请修改代码。

实验材料

硬件

  • 面包板一块
  • CH340模块
  • STM32F103C8T6最小开发版

软件

  • KEIL5
  • STM32CubeMX

项目制作

CubeMX配置

1、配置时钟RCC

在这里插入图片描述

​ 点击SystemCore -> RCC 分别使能HSE与HLE,如图所示,全部选择Crystal/Ceramic Resonator。

​ 因为本实验要读取RTC中的数据并发往串口助手,因此本实验要使用RTC与UART1。RTC使用LSE,因此这里两个都要使能。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZH9cHv0M-1667375866859)(E:\学习资料\嵌入式作业\11_hal_rtc\4.png)]

​ 在使能了HSE与LSE后,点击Clock Configuration ,按上图进行配置。

2、开启RTC

在这里插入图片描述

​ 点击Timers -> RTC ,按上图勾选,开启RTC。

​ 下面的参数设置里面主要是使用BCD码设置RTC中的时间初值。暂时不管它。

3、配置串口

在这里插入图片描述

​ 点击Connectivity -> USART1 ,选择工作模式为异步,工作参数按默认值不变(波特率115200,数据长8位,无校验位,1位停止位)

4、项目信息设置

在这里插入图片描述

在这里插入图片描述

代码编写

1、编写fputc,使能printf

在这里插入图片描述

hal库自带了printf函数,用于使用串口发送数据到串口助手,用法跟c语言的printf一样。

要使用printf函数,需要写一个fputc函数,这样就可以使用hal自带的printf函数了。

注意,要使用printf函数除了重写fputc函数之外,还要在魔术棒中勾选Use Micro Lib,如下图所示。

2、main函数读取数据并发送

在这里插入图片描述

这一步要读取RTC中的数据,并发送到串口。在HAL库中封装了以下函数与结构体,用于读取RTC数据并发送。

/*读取系统时间*/
HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
  • *hrtc RTC结构体参数 例:&hi2c2
  • RTC_TimeTypeDef sTime: 获取RTC时间的结构体,
  • Format: 获取时间的格式
    RTC_FORMAT_BIN 使用16进制 RTC_FORMAT_BCD 使用BCD进制
/*读取系统日期*/
HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
  • hrtc RTC结构体参数 例:&hi2c2
  • RTC_DateTypeDef sTime: 获取RTC日期的结构体,
  • Format: 获取日期的格式
    RTC_FORMAT_BIN 使用16进制 RTC_FORMAT_BCD 使用BCD进制

​ 上面两种函数读取年月日或者时分秒到对应的结构体中,结构体声明如下:

/**
  * @brief  RTC Time structure definition
  */
typedef struct
{
  uint8_t Hours;            /*!< Specifies the RTC Time Hour.
                                 This parameter must be a number between Min_Data = 0 and Max_Data = 23 */

  uint8_t Minutes;          /*!< Specifies the RTC Time Minutes.
                                 This parameter must be a number between Min_Data = 0 and Max_Data = 59 */

  uint8_t Seconds;          /*!< Specifies the RTC Time Seconds.
                                 This parameter must be a number between Min_Data = 0 and Max_Data = 59 */

} RTC_TimeTypeDef;

/**
  * @brief  RTC Date structure definition
  */
typedef struct
{
  uint8_t WeekDay;  /*!< Specifies the RTC Date WeekDay (not necessary for HAL_RTC_SetDate).
                         This parameter can be a value of @ref RTC_WeekDay_Definitions */

  uint8_t Month;    /*!< Specifies the RTC Date Month (in BCD format).
                         This parameter can be a value of @ref RTC_Month_Date_Definitions */

  uint8_t Date;     /*!< Specifies the RTC Date.
                         This parameter must be a number between Min_Data = 1 and Max_Data = 31 */

  uint8_t Year;     /*!< Specifies the RTC Date Year.
                         This parameter must be a number between Min_Data = 0 and Max_Data = 99 */

} RTC_DateTypeDef;

​ 数据保存到结构体中后,直接访问其成员就可以得到时间数据。

​ main函数代码如下:

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_RTC_Init();
  MX_USART1_UART_Init();
  RTC_DateTypeDef GetDate;  //获取日期结构体
  RTC_TimeTypeDef GetTime;   //获取时间结构体
  while (1)
  {
		HAL_RTC_GetTime(&hrtc,&GetTime,RTC_FORMAT_BIN);
		HAL_RTC_GetDate(&hrtc,&GetDate,RTC_FORMAT_BIN);
		printf("%02d-%02d-%02d %02d:%02d:%02d  ",GetDate.Year,GetDate.Month,GetDate.Date,GetTime.Hours,GetTime.Minutes,GetTime.Seconds);
		if(GetDate.WeekDay==1){
			printf(" 星期一\r\n");
		}else if(GetDate.WeekDay==2){
			printf(" 星期二\r\n");
		}else if(GetDate.WeekDay==3){
			printf(" 星期三\r\n");
		}else if(GetDate.WeekDay==4){
			printf(" 星期四\r\n");
		}else if(GetDate.WeekDay==5){
			printf(" 星期五\r\n");
		}else if(GetDate.WeekDay==6){
			printf(" 星期六\r\n");
		}else if(GetDate.WeekDay==7){
			printf(" 星期日\r\n");
		}
        HAL_Delay(1000);
  }
}

3、初始化时间

在这里插入图片描述

​ 进入rtc.c文件中的MX_RTC_Init(void),如上图所示,RTC中的年月日,时分秒都在这里被初始化,默认的是00年1月1日,0时0分0秒。

​ 在这里使用BCD码对年,日,时,分,秒进行初始化,而月已经被hal封装好,不用自己写BCD码。

​ 这里有几点要注意:

  • 第一,使用BCD码进行初始化,BCD码用4位二进制表示一位十进制的0-9,因此在赋值时直接在十进制值前面加上0x赋值给结构体变量即可。
  • 第二,HAL库的年是从2000年开始的,你输入0x00,保存的是2000年。可是结构体变量用的是uint8来表示年的啊,你怎么知道0x00就是2000而不是其他年份呢?下面是第三条。
  • 第三,HAL库根据年月日,自动配置星期。你配置了年月日后,不用再配置星期,hal库自动进行计算。而且你也不能修改星期。

从第三点HAL库的自动计算星期,可以验证第二点,HAL库的年从2000年开始。

先配置年0x00,1月1日,输出结果如图所示:

在这里插入图片描述

2000年1月1日星期:

在这里插入图片描述

接着手动配置一下星期,输出结果不变:

在这里插入图片描述

在这里插入图片描述

改一下年份为0x01,1月1日,输出如下:

在这里插入图片描述

2001年1月1日星期如下:

在这里插入图片描述

实验现象

​ 在没有修改初始化时间时,输出的时间默认为00年1月1日 00:00:00,如图所示:

在这里插入图片描述

​ 修改一下初始时间,可以看到输出的时间发生变化:在这里插入图片描述

总结

本实验介绍了如何在STM32CUBEMX对RTC,USART1进行配置,以及如何编写代码得到RTC的数据,并发往串口助手。

如果在配置初值时使用的BCD形式,那么在读取时要使用BIN形式,才能读出BCD码所对应的值。

尤其注意:HAL库的年份是从2000年开始的,即0x00代表2000,0x01代表2001,,,而且HAL库的星期是根据你输入的年月日自动推算的,手动更改不会生效。

参考资料

https://blog.csdn.net/as480133937/article/details/105741893

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值