STM32F446RE Nucleo RTC Timestamp

This program demonstrates the RTC timestamp feature of the STM32F4 family of MCUs. The timestamp is activated by one of two external pins (PA0 or PC13 on the STM32F446). Since the PC13 pin is connected to the user button on the Nucleo board, we use it in this demonstration to activate the timestamp. The timestamp feature can be used in either polling or interrupt mode. This demonstration utilizes the interrupt and callback. The ISR in this code simply flags a timestamp overflow by turning on the LED.

The code should be self explanatory. This code is compiled inside the Arduino IDE using the official STM 2.0 Core.

// RTC timestamp demo.
// 1. timestamp occurs when user button is pressed.
// 2. include a sketch level "build_opt.h" file with "-DHAL_RTC_MODULE_ONLY"

// LSI
#define RTC_ASYNCH_PREDIV    0x7F
#define RTC_SYNCH_PREDIV     0x00F9
// LSE
//#define RTC_ASYNCH_PREDIV  0x7F
//#define RTC_SYNCH_PREDIV   0x00FF

RTC_HandleTypeDef RtcHandle;
RTC_TimeTypeDef sTimeStamp;
RTC_DateTypeDef sDateStamp;

volatile bool stamp {false};

static void RTC_TimeStampConfig(void) 
{
  RTC_DateTypeDef sDate;
  RTC_TimeTypeDef sTime;

  // RTC TimeStamp generation: TimeStamp Rising Edge on PC13 Pin 
  HAL_RTCEx_SetTimeStamp_IT(&RtcHandle, RTC_TIMESTAMPEDGE_RISING, RTC_TIMESTAMPPIN_PC13);
  
  // Set a date & time.
  sTime.Hours = 0x1;
  sTime.Minutes = 0x2;
  sTime.Seconds = 0x3;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&RtcHandle, &sTime, RTC_FORMAT_BCD) != HAL_OK)
    while (1); 
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_SEPTEMBER;
  sDate.Date = 0x14;
  sDate.Year = 0x0;
  if (HAL_RTC_SetDate(&RtcHandle, &sDate, RTC_FORMAT_BCD) != HAL_OK)
    while (1); 
}

void RTC_Init(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_PeriphCLKInitTypeDef RCC_RTCPeriClkInit;

  // 1. Turn on the LSI
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.LSEState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    while (1);
  // 2. Select LSI as RTCCLK
  RCC_RTCPeriClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  RCC_RTCPeriClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
  if (HAL_RCCEx_PeriphCLKConfig(&RCC_RTCPeriClkInit) != HAL_OK)
    while (1);
  
  __HAL_RCC_RTC_ENABLE(); 
  // Configure the NVIC for RTC TimeStamp. 
  HAL_NVIC_SetPriority(TAMP_STAMP_IRQn, 0x0F, 0);
  HAL_NVIC_EnableIRQ(TAMP_STAMP_IRQn);
  
  // Configure RTC prescaler and RTC data registers 
  // - Hour Format    = Format 12
  // - Asynch Prediv  = Value according to source clock
  // - Synch Prediv   = Value according to source clock
  // - OutPut         = Output Disable
  // - OutPutPolarity = High Polarity
  // - OutPutType     = Open Drain 
  __HAL_RTC_RESET_HANDLE_STATE(&RtcHandle);
  RtcHandle.Instance = RTC;
  RtcHandle.Init.HourFormat     = RTC_HOURFORMAT_12;
  RtcHandle.Init.AsynchPrediv   = RTC_ASYNCH_PREDIV;
  RtcHandle.Init.SynchPrediv    = RTC_SYNCH_PREDIV;
  RtcHandle.Init.OutPut         = RTC_OUTPUT_DISABLE;
  RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  RtcHandle.Init.OutPutType     = RTC_OUTPUT_TYPE_OPENDRAIN;
  __HAL_RTC_RESET_HANDLE_STATE(&RtcHandle);
  if (HAL_RTC_Init(&RtcHandle) != HAL_OK)
    while (1);
     
  RTC_TimeStampConfig();
}

// EXTI line detection callback.
void buttonISR() { stamp = true; }

extern "C" void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc) 
{
  HAL_RTCEx_GetTimeStamp(&RtcHandle, &sTimeStamp, &sDateStamp, RTC_FORMAT_BIN);
}

// This function handles RTC tamper and timestamp interrupts through EXTI line 21.
extern "C" void TAMP_STAMP_IRQHandler(void) 
{ 
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
  if (RTC->ISR & RTC_FLAG_TSOVF)
  {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
    CLEAR_BIT(RTC->ISR, RTC_FLAG_TSOVF);
  }
  HAL_RTCEx_TamperTimeStampIRQHandler(&RtcHandle); 
}

void setup()
{
  Serial.begin(9600);
  while(!Serial);

  RTC_Init();

  pinMode(LED_BUILTIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(PC13), buttonISR, RISING);

  Serial.println("RTC Timestamp Demo");
}

void loop() 
{
    RTC_TimeTypeDef sTime;
    RTC_DateTypeDef sDate;
    char s[16] = { 0 };

    HAL_RTC_GetTime(&RtcHandle, &sTime, RTC_FORMAT_BIN);
    HAL_RTC_GetDate(&RtcHandle, &sDate, RTC_FORMAT_BIN);
    sprintf(s, "%02d:%02d", sTime.Minutes, sTime.Seconds); 
    Serial.print(s);
    
    if (stamp)
    {
      sprintf(s, " [%02d:%02d]", sTimeStamp.Minutes, sTimeStamp.Seconds);
      Serial.println(s); 
      stamp = false;
    }
    else
      Serial.println();
      
    HAL_Delay(1000);
}

About Jim Eli

µC experimenter
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a comment