江濤帶你玩0.96-OLED之實戰stm32的RTC時鐘(下)

江濤帶你玩0.96-OLED之實戰stm32的RTC時鐘(上)
 

上一篇中已經講了如何驅動OLED和自定義顯示,下面接上一篇繼續,使用STM32自帶的RTC實現時鐘顯示。


目錄

8.RTC時鐘

9.演示效果

10.參考文獻


8.RTC時鐘

RTC的配置我截圖如下

 主要注意RTC的初始化配置,我這裏用到了定時器4,這是爲何呢?一會兒大家看演示效果就知道了,先上代碼main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "rtc.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
#include "stdbool.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
RTC_DateTypeDef sDate ;
RTC_TimeTypeDef sTime ;
bool flag = true;
uint8_t second_count = 0;
char *week[7] = {"SUN","MON","TUE","WEN","THU","FRI","SAT"};
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void Time_Display(void);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void Time_Display(void)
{
    char date_str[10];
    HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN);
    HAL_RTC_GetDate(&hrtc,&sDate,RTC_FORMAT_BIN);

    // 最後一頁顯示日期和星期
    date_str[0]= '2';
    date_str[1]= '0';
    date_str[2]= sDate.Year/10+'0';
    date_str[3]= sDate.Year%10+'0';
    date_str[4]= '-';
    date_str[5]= sDate.Month/10+'0';
    date_str[6]= sDate.Month%10+'0';
    date_str[7]= '-';
    date_str[8]= sDate.Date/10+'0';
    date_str[9]= sDate.Date%10+'0';
    OLED_Show_String(0,7,date_str,SMALL);
    OLED_Show_String(100,7,week[sDate.WeekDay%7],SMALL);

    // 顯示時間
    OLED_Show_Num(14,2,sTime.Hours/10,BIG_NUM);
    OLED_Show_Num(34,2,sTime.Hours%10,BIG_NUM);
    OLED_Show_Num(74,2,sTime.Minutes/10,BIG_NUM);
    OLED_Show_Num(94,2,sTime.Minutes%10,BIG_NUM);
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_RTC_Init();
  MX_TIM4_Init();
  /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim4);
	OLED_Init();
	OLED_Show_Icon(0,0,1);
	OLED_Show_Icon(96,0,2);
	OLED_Show_Icon(112,0,0);
	Time_Display();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    while (1)
    {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

    }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(TIM4 == htim->Instance) {
        // 500ms 
        flag = !flag ;
				// 
        flag ? OLED_Show_Num(54,2,10,BIG_NUM):OLED_Show_Num(54,2,11,BIG_NUM);;
        second_count ++;
        // one second display the time
        if(second_count==2) {
            second_count = 0;
            Time_Display();
        }
    }
}

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

9.演示效果

看下演示效果

給大家講講爲何要用定時器,定時器就是實現了中間分割冒號的閃爍。

這裏定時器每隔500ms中斷一次,中斷後將中間冒號顯示部分清空或者顯示,這裏我取模的時候生成了 “:” 和“ ”(空)兩個字模,每隔500ms讓這兩個交替顯示就達到了閃爍的效果了。

另外閃爍兩次表示1s的時間到了,然後調用顯示時間的函數,刷新顯示,當有59秒到60秒變化的時候,分鐘加1

看下中斷函數的處理如下

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(TIM4 == htim->Instance) {
        // 500ms 
        flag = !flag ;
				// 
        flag ? OLED_Show_Num(54,2,10,BIG_NUM):OLED_Show_Num(54,2,11,BIG_NUM);;
        second_count ++;
        // one second display the time
        if(second_count==2) {
            second_count = 0;
            Time_Display();
        }
    }
}

/* USER CODE END 4 */

10.參考文獻

完整代碼資料在QQ羣,有需要的可以加羣索取, QQ羣:1087285029

或者掃碼添加

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章