【Blue Bridge Cup】【組み込み部門】 第11節:リアルタイムクロックRTC

リアルタイムクロック RTC

RTC の概要

  1. マイクロコントローラーを低電力モードから通常の動作モードに復元するために、自動ウェイクアップ サービスを提供できます。
  2. RTC は、独立した BCD コード (2 進化 10 進数) タイマーおよびカウンターです。
  3. 時刻、日付、年、その他の情報を提供できる
  4. 外部電源電圧が電源範囲内にある限り、RTC はカウントを停止しません。
  5. 高精度のデジタル校正
  6. RTCのクロックソースはLSEまたはHSIから選択可能(どちらも外部水晶発振器)
  7. RTCは内部LSI 32ビット低速クロックソースも選択可能

プログラミング

  1. [テンプレート] STM32CUBEMX 生成コードのプロジェクトとして。
  2. RTC の時計およびカレンダー機能を有効にします。
  3. 要件に従って、RTC のクロックと初期化ステータスを設定し、RTC モジュールへのクロック入力を 1Hz に設定します。
  4. rtc.c と rtc.h を [プログラミング プロジェクト] に移行します。
    4.1main.c には #include "rtc.h" が含まれます。
    4.2 stm32g4xx hal confh で RTC モジュールを起動します
    。 4.3 クロックの初期化。LSI を RTC のクロック ソースとして必ず初期化します
    。 4.4 HAL RTC GetTime と HAL RTC GetDate を呼び出して時刻と日付を取得します。

タイマーの下で RTC を見つけ、最初の 2 つのオプションをチェックして、RTC のクロック ソースとタイミング機能をオンにします。
ここに画像の説明を挿入します
これにより、クロック ツリー内のクロック ソースが LSI (32khz 内部低速クロック) として構成されていることがわかります。 ) デフォルトなので、デフォルトのままにしておきます。
ここに画像の説明を挿入します
次のステップでは、RTC 周波数が 1HZ になるように分周値とプリスケーラー値を設定します。
ここに画像の説明を挿入します
ここで指定されるデフォルトの分周値とプリスケーラ値は次のとおりです:
128*256=32768 (分周は 0 から始まるため、127 は実際には 128 になります)。つまり、RTC が水晶発振器に接続されている場合、周波数は 32768HZ です。 127 でプリスケールし、255 で除算すると、RTC の周波数は 1HZ になります。
しかし、現在接続しているクロックソースは32KHZなので、この値には問題があります。したがって、これら 2 つの値を変更する必要があります。
たとえば、これを 31 と 999 に変更するだけです。
ここに画像の説明を挿入します
次に、次のパラメーターのいくつかを次のように設定して、現象を観察できるようにします。
ここに画像の説明を挿入します
その後、コードを生成して移植できます。
覚えておくべき最も重要なことは、RTC の移植には LSI を RTC のクロック ソースとして初期化する手順が必要であるということです。
テンプレートの main.c で次のプログラムを使用します。

   /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC12;
  PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    
    
    Error_Handler();
  }

プログラミング ファイル main.c 内の次の段落を置き換えます。

    /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
  PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    
    
    Error_Handler();
  }
}

次に、RTC の起動プログラムを作成します。

RTC_TimeTypeDef rtc_time;
RTC_DateTypeDef rtc_date;
void RTC_Process(void)
{
    
    
	HAL_RTC_GetTime(&hrtc,&rtc_time,RTC_FORMAT_BIN);
	HAL_RTC_GetDate(&hrtc,&rtc_date,RTC_FORMAT_BIN);
}

完全な main.c は次のとおりです。

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 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 "gpio.h"
#include "led.h"
#include "key.h"
#include "i2c.h"
#include "dac.h"
#include "rtc.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* 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 */

/* 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 */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

//Led执行程序
__IO uint32_t ledTick =0,keyTick=0;
u8 led_ctrl=0xff;
void LED_Process(void)
{
    
    
	if(uwTick-ledTick<500)return;
	ledTick=uwTick;
	LED_Control(led_ctrl);
	led_ctrl=~led_ctrl;
}

//KEY
void KEY_Process(void)
{
    
    
	if(uwTick-keyTick<10)return;
	keyTick=uwTick;
	Key_Read();
//	if(Trg&0x01)
//	{
    
    
//	LED_Control(0x01);
//	}
	if(Trg)
	{
    
    
		LED_Control(Trg);
	}
}

//EEPROM
u8 val_24c02=0;

//DAC
u16 dac_ch1_val,dac_ch2_val;
void DAC_Process(void)
{
    
    
	  dac_ch1_val=(1.1f/3.3f*4095);//输出1.1V
	  dac_ch2_val=(2.1f/3.3f*4095);//输出2.2V
	
    HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,DAC_ALIGN_12B_R,dac_ch1_val);//0->0V;4095->3.3V
		HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);
	
	  HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_2,DAC_ALIGN_12B_R,dac_ch2_val);//0->0V;4095->3.3V
		HAL_DAC_Start(&hdac1,DAC_CHANNEL_2);
}

//RTC
RTC_TimeTypeDef rtc_time;
RTC_DateTypeDef rtc_date;
void RTC_Process(void)
{
    
    
	HAL_RTC_GetTime(&hrtc,&rtc_time,RTC_FORMAT_BIN);
	HAL_RTC_GetDate(&hrtc,&rtc_date,RTC_FORMAT_BIN);
}

//LCD
void LCD_Process(void)
{
    
    
	u8 display_buf[20];
	
	sprintf((char*)display_buf,"%02d-%02d-%02d",rtc_time.Hours,rtc_time.Minutes,rtc_time.Seconds);
	LCD_DisplayStringLine(Line0,display_buf);
	
	sprintf((char*)display_buf,"%04d-%02d-%02d",rtc_date.Year,rtc_date.Month,rtc_date.Date);
	LCD_DisplayStringLine(Line1,display_buf);
	
	sprintf((char*)display_buf,"EEPROM:%d",val_24c02);
  LCD_DisplayStringLine(Line2,display_buf);//输出百分号:%
	
}

/* 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();
  /* USER CODE BEGIN 2 */
	
	LCD_Init();
	LED_Control(0x00);
	MX_DAC1_Init();
	MX_RTC_Init();
	I2CInit();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	EEPROM_Write(0x10,0x55);
	val_24c02=EEPROM_Read(0x10);
	
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    LED_Process();
		KEY_Process();
		DAC_Process();
		RTC_Process();
		LCD_Process();
  }
  /* 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};
  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  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_3) != HAL_OK)
  {
    
    
    Error_Handler();
  }
	
	 /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC12;
  PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    
    
    Error_Handler();
  }
	
}

/* USER CODE BEGIN 4 */

/* 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****/

おすすめ

転載: blog.csdn.net/Gorege__Hu/article/details/129916669