cancel
Showing results for 
Search instead for 
Did you mean: 

VBAT & RTC Issues on Circuit - STM32H563ZIT6

Bharathkumar
Associate II

I am experiencing issues with the VBAT pin on the STM32H563ZIT6 microcontroller. Specifically, the VBAT pin is not responding properly. I am using a CR2032 CMOS battery for RTC backup, but it is not maintaining the date and time as expected. When the power supply is off, the RTC does not hold and run correctly, but it resumes running once the power supply is restored.

I have attached the circuit diagram for your reference. Could you please provide a clear explanation of the potential issues and offer guidance on how to resolve them? Expert advice on this matter would be greatly appreciated.

 

VBAT & CMOS : 

VBAT_CKT.png

CMOS Battery.png

 

19 REPLIES 19

Ok, but C14 should be there. (I use 10u cer.cap here.)

+

Set in Cube the LSE drive high !

AScha3_0-1719038560736.png

Then it should work.

If you feel a post has answered your question, please click "Accept as Solution".
unsigned_char_array
Senior III

As I suspected LSE is disabled. So your crystal will never oscillate.

unsigned_char_array_0-1719042425511.png

unsigned_char_array_1-1719042672605.pngAnd you don't use LSE as clock source either.

 

Drive strength depends on the MCU family and used crystal. Higher drive strength consumes more current. Too low and it may not oscillate.
Check Table 7. "Recommended crystal / MEMS resonators for the LSE oscillator in STM32"
from an2867-guidelines-for-oscillator-design-on-stm8afals-and-stm32-mcusmpus-stmicroelectronics.pdf for what your MCU supports.I've had issues with using a not supported crystal with too high capacitance. It resulted in some boards not booting sometimes since the LSE init function time out. The trick was using a different crystal with correctly calculated capacitors and set the right drive strength (in our case second highest level was good).

Check the datasheet of your MCU to see what drive strength levels are supported for LSEDRV.
"Table 43. Low-speed external user clock characteristic" in stm32h563zi.pdf

unsigned_char_array_2-1719043062040.png

 

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

As per your instructions, the problem was solved. We checked it a few times, each for a duration of 5 to 10 minutes, over the last few days. If any issues occur in the future, I will call you back. Thank you for your support and guidance.

I'm glad you got it to work. Please kudo the posts that helped you.

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

Hi Bharath Kumar 

In my project i was also working on the RTC.

We are also got the issue which you got, which the rtc does not getting updated during the power OFF. Please help me to solve the issue 

Hi Ajay
Please follow the given STM instructions from the beginning to the end of our conversation.
Also, please provide your circuit for correction.
Ensure you use the internal oscillator

Please read this topic and other topics on RTC issues. If those don't help you, please open a new topic.

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

Yeah,

you can go through this files which contain .ioc and clock configuration.

OK @unsigned_char_array we will go through it.  but we get 1.2V on oscillator this means it is working properly??

Meanwhile we verify the hardware can you please let us know whether the code used for RTC Initialization and backup method is correct and sufficient. Please help me with this. Thankyou

 

 

 

 
/* USER CODE BEGIN Header */
#include "stdio.h"
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.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 ---------------------------------------------------------*/
RTC_HandleTypeDef hrtc;

UART_HandleTypeDef huart3;

/* USER CODE BEGIN PV */
char time[10];
char date[10];
RTC_TimeTypeDef RtcTime;
RTC_DateTypeDef RtcDate;
 
uint8_t CompareSeconds;
uint8_t CompareDate;
 
uint8_t Message[64];
uint8_t MessageLen;
uint8_t Messagexyz[64];
uint8_t MessageLenxyz;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_USART3_UART_Init(void);
void BackupDateToBR(void);
extern uint32_t CalculateDayNumber(uint8_t , uint8_t , uint8_t ); // DD.MM.YY
extern void CalculateDateFromDayNumber(uint32_t , uint8_t *, uint8_t *, uint8_t *);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint32_t CalculateDayNumber(uint8_t Date, uint8_t Month, uint8_t Year)
{
	// Format:
	// DD.MM.YY
	uint32_t _Year = Year + 20;
	Month = (Month + 9) % 12;
	_Year = _Year - (Month / 10);
	return ((365 * _Year) + (_Year / 4) - (_Year / 100) + (_Year / 400) + (((Month * 306) + 5) / 10) + (Date - 1));
}

void CalculateDateFromDayNumber(uint32_t DayNumber, uint8_t *Date, uint8_t *Month, uint8_t *Year)
{
	uint32_t _Date, _Month, _Year;
	_Year = ((10000 * DayNumber) + 14780) / 3652425;
	int32_t ddd = DayNumber - ((365 * _Year) + (_Year / 4) - (_Year / 100) + (_Year / 400));
	if (ddd < 0)
	{
		_Year -= 1;
		ddd = DayNumber - ((365 * _Year) + (_Year / 4) - (_Year / 100) + (_Year / 400));
	}
	int32_t mi = ((100 * ddd) + 52) / 3060;
	_Month = (mi + 2) % 12 + 1;
	_Year = _Year + (mi + 2)/12;
	_Date = ddd - ((mi * 306) + 5)/10 + 1;
	*Date = _Date;
	*Month = _Month;
	*Year = _Year - 20;
}

/* 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_USART3_UART_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
  HAL_Delay(200);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
  HAL_Delay(200);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
  HAL_Delay(2000);
	while(1)
	{
     HAL_RTC_GetTime(&hrtc, &RtcTime, RTC_FORMAT_BIN);
	  HAL_RTC_GetDate(&hrtc, &RtcDate, RTC_FORMAT_BIN);

	  if(RtcTime.Seconds != CompareSeconds)
	  {
		  MessageLen = sprintf((char*)Message, "Date: %02d.%02d.20%02d Time: %02d:%02d:%02d\n\r", RtcDate.Date, RtcDate.Month, RtcDate.Year, RtcTime.Hours, RtcTime.Minutes, RtcTime.Seconds);
		  HAL_UART_Transmit(&huart3, Message, MessageLen, 100);
		  CompareSeconds = RtcTime.Seconds;
	  }
	  if(RtcDate.Date != CompareDate)
	  {
		  BackupDateToBR();
		  CompareDate = RtcDate.Date;
	  }
		
	}
    /* 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 RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  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_DIV2;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses 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_DIV2;
  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_LSE;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief RTC Initialization Function
  *  None
  * @retval None
  */
static void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */
  /* USER CODE END RTC_Init 0 */

  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef DateToUpdate = {0};

  /* USER CODE BEGIN RTC_Init 1 */
  /* USER CODE END RTC_Init 1 */

  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
  hrtc.Init.OutPut = RTC_OUTPUTSOURCE_ALARM;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */

  RTC_DateTypeDef BackupDate;
 
  RtcDate.Date = (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2) >> 8);
  RtcDate.Month = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
  RtcDate.Year = (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3) >> 8);
  RtcDate.WeekDay = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3);
 
  MessageLenxyz = sprintf((char*)Messagexyz, "Backup Date Value: %d, Month: %d, Year: %d, Weekday: %d\n\r", RtcDate.Date, RtcDate.Month, RtcDate.Year, RtcDate.WeekDay);
 
 
  HAL_RTC_GetTime(&hrtc, &RtcTime, RTC_FORMAT_BIN); // There is also an internal date update based on HW RTC time elapsed!!
  HAL_RTC_GetDate(&hrtc, &BackupDate, RTC_FORMAT_BIN); // Days elapsed since MCU power down
 
  uint32_t BackupDateDays = CalculateDayNumber(BackupDate.Date, BackupDate.Month, BackupDate.Year);
  uint32_t RtcDateDays = CalculateDayNumber(RtcDate.Date, RtcDate.Month, RtcDate.Year);
 
      // MessageLenxyz = sprintf((char*)Messagexyz, "BackupDateDays : %d RtcDateDays: %d\n\r", BackupDateDays,RtcDateDays);
 
 
  RtcDateDays += (BackupDateDays - CalculateDayNumber(1, 1, 0));
 
  CalculateDateFromDayNumber(RtcDateDays, &RtcDate.Date, &RtcDate.Month, &RtcDate.Year);
 
  HAL_RTC_SetDate(&hrtc, &RtcDate, RTC_FORMAT_BIN);
    return;
  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 0x10;
  sTime.Minutes = 0x10;
  sTime.Seconds = 0x30;

  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  DateToUpdate.WeekDay = RTC_WEEKDAY_SATURDAY;
  DateToUpdate.Month = RTC_MONTH_JULY;
  DateToUpdate.Date = 0x27;
  DateToUpdate.Year = 0x24;

  if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */
  /* USER CODE END RTC_Init 2 */

}

/**
  * @brief USART3 Initialization Function
  *  None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{

  /* USER CODE BEGIN USART3_Init 0 */
  /* USER CODE END USART3_Init 0 */

  /* USER CODE BEGIN USART3_Init 1 */
  /* USER CODE END USART3_Init 1 */
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART3_Init 2 */
  /* USER CODE END USART3_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  *  None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);

  /*Configure GPIO pin : PB13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PA15 */
  GPIO_InitStruct.Pin = GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
void BackupDateToBR(void)
{
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, ((RtcDate.Date <<  | (RtcDate.Month)));
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, ((RtcDate.Year <<  | (RtcDate.WeekDay)));
}
/* 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 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.
  *   file: pointer to the source file name
  *   line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
View more

 

Ajay_9121_0-1722584944731.png

 

 

 

0 Kudos