当前位置:   article > 正文

蓝桥杯嵌入式学习笔记(9):RTC程序设计

蓝桥杯嵌入式学习笔记(9):RTC程序设计

目录

前言

1. RTC介绍

2. 使用CubeMx进行源工程配置

3. 代码编程

3.1 准备工作

3.2 进行bsp_rtc.h编写

3.3 进行bsp_rtc.c编写 

3.4 main.c编写

3.4.1 头文件引用

3.4.2 变量声明 

3.4.3 子函数声明

3.4.4 函数实现

3.4.5 main函数编写

4. 代码实验

5. 总结 


前言

因本人备赛蓝桥杯嵌入式省赛,故编写此学习笔记进行学习上的记录。

上文我们实现了TIM程序设计,本文我们进行RTC程序设计

1. RTC介绍

RTC是一个独立的定时器,RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。

从STM32G4系列微控制器参考手册的时钟树图可以看出,RTCCLK 时钟源可以是 HSE/32、LSE 或 LSI 时钟。

LSE 时钟位于 RTC 域中,而 HSE 和 LSI 时钟则不在 RTC 域中。

  • 如果选择 LSE 作为 RTC 时钟:

        即使 VDD 电源关闭,RTC 仍可继续工作,前提是VBAT电源得到维持。

  • 如果选择LSI作为RTC时钟:

        如果 VDD 电源断电,则无法保证 RTC 状态。

  • 如果将除以预分频器的 HSE 时钟用作 RTC 时钟:

        如果 VDD 电源断电或内部电压调节器已关闭电源(从 VCORE 域断开电源)。

当RTC时钟为LSE或LSI时,RTC在系统下保持时钟和功能重置。

2. 使用CubeMx进行源工程配置

-【Pinout&Configuration】

-【Timers】

-【RTC】

         -【Mode】

                -【Activate Clock Source】和【Activate Calendar】

-在【Clock Configuration】配置RTC时钟源为HSE_RTC,时钟源频率为750KHz。

RTC时钟频率 = RTC时钟源 / ((Asynchronous Predivider value + 1) * (Synchronous Predivider value + 1)) 

         -【Parameter Settings】

                 -【Asynchronous Predivider Value】设置为124

                -【Synchronous Predivider value 】设置为5999。

这样,RTC时钟频率就为1Hz。

配置完成后,我们去生成源文件。

3. 代码编程

3.1 准备工作

接下来我们在Test_Project工程里的Src文件夹创建BSP\RTC\bsp_rtc.c,同理,在Inc文件夹创建BSP\RTC\bsp_rtcm.h。这就是我们后面要编写的中间层代码文件。

打开Test_Project工程,进行文件Group的添加

在bsp_rtc.c中添加依赖文件

#include "RTC/bsp_rtc.h"

随后进行编译。

添加stm32g4xx_hal_rtc.c和stm32g4xx_hal_rtc_ex.c驱动文件

在stm32g4xx_hal_conf.h中去掉#define HAL_RTC_MODULE_ENABLED 的注释。 

#define HAL_RTC_MODULE_ENABLED   

3.2 进行bsp_rtc.h编写

通过Source工程生成的tim模块进行剪裁修改,h文件如下

  1. /* Includes ------------------------------------------------------------------*/
  2. #include "main.h"
  3. /* USER CODE BEGIN Includes */
  4. /* USER CODE END Includes */
  5. extern RTC_HandleTypeDef hrtc;
  6. void RTC_Init(void);

3.3 进行bsp_rtc.c编写 

通过Source工程生成的tim模块进行剪裁修改,c文件如下

  1. #include "RTC/bsp_rtc.h"
  2. RTC_HandleTypeDef hrtc;
  3. void RTC_Init(void)
  4. {
  5. RTC_TimeTypeDef sTime = {0};
  6. RTC_DateTypeDef sDate = {0};
  7. /** Initialize RTC Only
  8. */
  9. hrtc.Instance = RTC;
  10. hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  11. hrtc.Init.AsynchPrediv = 125;
  12. hrtc.Init.SynchPrediv = 6000;
  13. hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  14. hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  15. hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  16. hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  17. hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
  18. if (HAL_RTC_Init(&hrtc) != HAL_OK)
  19. {
  20. Error_Handler();
  21. }
  22. /** Initialize RTC and set the Time and Date
  23. */
  24. sTime.Hours = 0;
  25. sTime.Minutes = 0;
  26. sTime.Seconds = 0;
  27. sTime.SubSeconds = 0;
  28. sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  29. sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  30. if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
  31. {
  32. Error_Handler();
  33. }
  34. sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  35. sDate.Month = RTC_MONTH_JANUARY;
  36. sDate.Date = 1;
  37. sDate.Year = 0;
  38. if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
  39. {
  40. Error_Handler();
  41. }
  42. }
  43. void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
  44. {
  45. if(rtcHandle->Instance==RTC)
  46. {
  47. /* RTC clock enable */
  48. __HAL_RCC_RTC_ENABLE();
  49. }
  50. }
  51. void HAL_RTC_MspDeInit(RTC_HandleTypeDef* rtcHandle)
  52. {
  53. if(rtcHandle->Instance==RTC)
  54. {
  55. /* Peripheral clock disable */
  56. __HAL_RCC_RTC_DISABLE();
  57. }
  58. }

3.4 main.c编写

3.4.1 头文件引用

  1. #include "main.h"
  2. #include "LCD\bsp_lcd.h"
  3. #include "RTC\bsp_rtc.h"

3.4.2 变量声明 

  1. //变量声明
  2. __IO uint32_t uwTick_Lcd_Set_Point;//LCD减速
  3. //*LCD显示专用变量
  4. unsigned char Lcd_Disp_String[22];
  5. //RTC相关变量
  6. RTC_TimeTypeDef H_M_S_Time;
  7. RTC_DateTypeDef Y_M_D_Date;

3.4.3 子函数声明

  1. //***子函数声明区
  2. void SystemClock_Config(void);
  3. void Lcd_Proc(void);

3.4.4 函数实现

3.4.4.1 时钟函数定义

  1. void SystemClock_Config(void)
  2. {
  3. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  4. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  5. RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  6. /** Configure the main internal regulator output voltage
  7. */
  8. HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
  9. /** Initializes the RCC Oscillators according to the specified parameters
  10. * in the RCC_OscInitTypeDef structure.
  11. */
  12. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  13. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  14. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  15. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  16. RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
  17. RCC_OscInitStruct.PLL.PLLN = 20;
  18. RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  19. RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  20. RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  21. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  22. {
  23. Error_Handler();
  24. }
  25. /** Initializes the CPU, AHB and APB buses clocks
  26. */
  27. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  28. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  29. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  30. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  31. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  32. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  33. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  34. {
  35. Error_Handler();
  36. }
  37. /** Initializes the peripherals clocks
  38. */
  39. PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1
  40. |RCC_PERIPHCLK_ADC12;
  41. PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  42. PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_PLL;
  43. PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32;
  44. if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  45. {
  46. Error_Handler();
  47. }
  48. }

3.4.4.2 LCD函数实现

  1. void Lcd_Proc(void)
  2. {
  3. if((uwTick - uwTick_Lcd_Set_Point)<200)
  4. return;
  5. uwTick_Lcd_Set_Point = uwTick;
  6. //RTC内容显示
  7. HAL_RTC_GetTime(&hrtc,&H_M_S_Time,RTC_FORMAT_BIN);
  8. HAL_RTC_GetDate(&hrtc,&Y_M_D_Date,RTC_FORMAT_BIN);
  9. sprintf((char*)Lcd_Disp_String,"Time:%02d-%02d-%02d",(unsigned int)H_M_S_Time.Hours,(unsigned int)H_M_S_Time.Minutes,(unsigned int)H_M_S_Time.Seconds);
  10. LCD_DisplayStringLine(Line4,Lcd_Disp_String);
  11. }

3.4.5 main函数编写

  1. int main(void)
  2. {
  3. HAL_Init();
  4. SystemClock_Config();
  5. LCD_Init();
  6. LCD_Clear(White);
  7. LCD_SetBackColor(White);
  8. LCD_SetTextColor(Blue);
  9. //RTC初始化
  10. RTC_Init();
  11. while (1)
  12. {
  13. Lcd_Proc();
  14. }
  15. }

4. 代码实验

将代码进行编译并下载到开发板上。效果如下图所示。

时钟计时按1s为单位进行增加,RTC基本功能已成功实现!

5. 总结 

本文通过CubeMx进行配置RTC的参数以及时钟资源,并通过CubeMx生成的源工程进行二次编写成功实现了RTC的基本功能。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/368124
推荐阅读
相关标签
  

闽ICP备14008679号