RTC Alarm Minutes and Seconds on STM32U575VI
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2025-03-31 2:56 AM
Hi,
I'm currently working on an application for a STM32U575VI6. It's supposed to generate an interruption every 4 minutes and 9 seconds. However, it works only when I mask the seconds, and only work with minutes. The moment I try configure both and enable them, it doesn't activates. Do you know why ? The function that configures the alarm is at line 527.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "i2c.h"
#include "icache.h"
#include "memorymap.h"
#include "rtc.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "fm24cl64.h"
#include "RA08.h"
#include <stdio.h>
#include <stdlib.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define AN_INTERVAL 2
#define DIG_INTERVAL 10
#define ANA_WAIT 5000
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t alarmFlag = 0;
uint8_t flagAlarmA = 0;
uint8_t flagAlarmB = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void adjustAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint8_t interval);
void saveAnalogAvg(I2C_HandleTypeDef *hi2c2, uint32_t avgAna, uint16_t eepromAddress);
uint32_t ADC_ConvertRank3(ADC_HandleTypeDef *hadc);
uint32_t ADC_ConvertRank4(ADC_HandleTypeDef *hadc);
HAL_StatusTypeDef transmitAllData(RA08_Handle *ra08h, I2C_HandleTypeDef *hi2c2, uint8_t counterAdd);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t error101[11] = "ERROR101\r\n";
uint8_t error201[11] = "ERROR201\r\n";
uint8_t error202[11] = "ERROR202\r\n";
uint32_t avgAna3 = 0;
uint32_t avgAna4 = 0;
uint32_t analog_ch3 = 0;
uint32_t analog_ch4 = 0;
uint32_t anValue3[25] = {0};
uint32_t anTimer;
//uint32_t digValue[25] = {0};
uint16_t eepromAddressAn3 = 0;
uint8_t joinFlag = 0;
//uint8_t anInterval = 1; HOW MANY MINUTES WITHIN THE INTERVAL BETWEEN LECTURES
//uint8_t digInterval = 1;
uint8_t anCounter = 0;
uint8_t anCounterAdd = 0;
//uint8_t digCounter = 0;
char cal_end[15] = "CONFIG. MODE\r\n";
char uart_buffer[50];
char packetToSend[13] = "43770";
char hora_char[3] = {0};
char minutos_char[3] = {0};
RA08_Handle ra08h;
RTC_AlarmTypeDef alarmA;
RTC_AlarmTypeDef alarmB;
/* 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_MEMORYMAP_Init();
MX_ICACHE_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_I2C2_Init();
MX_RTC_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
/*
* LED1_PIN = VERDE
* LED2_PIN = ROJO
*/
HAL_Delay(5000);
/*- PARA OBTENER LA HORA DEBEMOS CREAR UN OBJETO DE TIPO RTC_TIMETYPEDEF PARA ALMACENARLO. LUEGO SE PUEDE PASAR A CHAR MEDIANTE ITOA, PARA SU VISUALIZACION -*/
/*
HAL_RTC_GetTime(&hrtc, ¤tTime, FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, ¤tDate, FORMAT_BIN);
itoa(currentTime.Hours, hora_char, 10);
itoa(currentTime.Minutes, minutos_char, 10);
*/
// ENTER MANUALLY LORAWAN PARAMETERS
if(HAL_GPIO_ReadPin(GPIOB, PROG_PIN_Pin) == GPIO_PIN_RESET)
{
RA08_Restore(&ra08h, &huart1, &huart2);
HAL_UART_Transmit(&huart2, (uint8_t*)cal_end, strlen(cal_end), 500);
RA08_Config(&ra08h, &huart2, &hi2c2);
while(1)
{
// WHEN FINISHED, THE RED LED WILL START TO BLINK
HAL_GPIO_TogglePin(GPIOC, LED2_Pin);
HAL_Delay(500);
}
}
/* MODULE CONFIG.--------------------------*/
if(RA08_Init(&ra08h, &huart1, &hi2c2) == HAL_ERROR)
{
// IT BLOCKS IF WAS NOT PREVIOUSLY CONFIGURED
HAL_UART_Transmit(&huart2, error101, sizeof(error101), UART_TIMEOUT);
while(1)
{
HAL_GPIO_TogglePin(GPIOC, LED1_Pin);
HAL_Delay(500);
}
}
RA08_SetCLASS(&ra08h, &huart2);
RA08_SetJoinMode(&ra08h, &huart2);
RA08_SetWindowsParam(&ra08h, &huart2);
RA08_SetFreqBAND(&ra08h, &huart2);
RA08_SetDevEUI(&ra08h, &huart2);
RA08_SetAppEUI(&ra08h, &huart2);
RA08_SetAppKEY(&ra08h, &huart2);
RA08_SetADR(&ra08h, &huart2);
/*-- SET THE SPREADING FACTOR IF THE ADR IS OFF --*/
if (ra08h.adr[0] == 0) RA08_SetSF(&ra08h, &huart2);
RA08_SetULDLMODE(&ra08h, &huart2);
RA08_SetConfirm(&ra08h, &huart2);
RA08_SaveParam(&ra08h, &huart2);
/*-------------------------*/
/*-- JOIN LORAWAN SERVER --*/
joinFlag = RA08_JoinNET(&ra08h, &huart2);
if (joinFlag == HAL_ERROR)
{
// LORA MODULE DID NOT RESPOND AFTER AT COMMAND
HAL_UART_Transmit(&huart2, error201, sizeof(error201), UART_TIMEOUT);
}
else if (joinFlag == HAL_TIMEOUT)
{
// DEVICE WAS UNABLE TO JOIN THE SERVER BECAUSE IT REACHED NUMBER OF TR
HAL_UART_Transmit(&huart2, error202, sizeof(error202), UART_TIMEOUT);
}
RA08_SendPacket(&ra08h, &huart2, packetToSend);
// RA08_ReadBuffer(&ra08h, &huart2, downlinkBuff);
/*- THE DOWNLINK PACKET KEEPS TH HOUR UPDATED, AND AN OPTIONAL COMMAND, THIS FUNCTION SAVES THE HOUR IN currentTime TO SAVE IT LATER IN THE RTC -*/
// RA08_exeCommand(¤tTime, &huart2, downlinkBuff);
// HAL_RTC_SetTime(&hrtc, ¤tTime, RTC_FORMAT_BIN);
/* - WE GET THE VALUE OF THE ALARM PREVIOUSLY SET, AND CHANGE THE TIME OF THE ALARM BY current.Time + alarmInterval. */
HAL_RTC_GetAlarm(&hrtc, &alarmA, RTC_ALARM_A, FORMAT_BIN);
HAL_RTC_GetAlarm(&hrtc, &alarmB, RTC_ALARM_B, FORMAT_BIN);
adjustAlarm(&hrtc, &alarmA, AN_INTERVAL);
adjustAlarm(&hrtc, &alarmB, DIG_INTERVAL);
HAL_ADC_Stop(&hadc1);
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED);
HAL_Delay(1000);
anTimer = HAL_GetTick();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/*- GetTime Y GetDate DEBEN IR JUNTOS EN ESTE ORDEN -*/
/*
HAL_RTC_GetTime(&hrtc, ¤tTime, FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, ¤tDate, FORMAT_BIN);
itoa(currentTime.Hours, hora_char, 10);
itoa(currentTime.Minutes, minutos_char, 10);
*/
if(HAL_GetTick() - anTimer >= ANA_WAIT)
{
/*- analog alarm */
HAL_RTC_GetAlarm(&hrtc, &alarmA, RTC_ALARM_A, FORMAT_BIN);
adjustAlarm(&hrtc, &alarmA, AN_INTERVAL);
// TURN ON DC/DC CONVERTER GATE
// AN 1 ROUTINE
analog_ch3 = ADC_ConvertRank3(&hadc1);
anValue3[anCounter] = analog_ch3;
// Convertir el valor a texto para UART
sprintf(uart_buffer, "\r\nADC Ch3 Value: %lu\r\n", analog_ch3);
// Transmitir por UART
HAL_UART_Transmit(&huart2, (uint8_t*)uart_buffer, strlen(uart_buffer), 500);
/*
*
* HERE GOES AN 2 ROUTINE
*
*/
anCounter ++; // IT INCREASES EACH LECTURE, USED TO KNOW THE SIZE OF THE PAGE
anTimer = HAL_GetTick();
/*
* TAREAS PENDIENTES:
*
* 1. ANADIR LOS DATOS EN UN ARRAY, O EN UNA EEPROM.
* 2. REALIZAR LA MEDIA Y ALMACENARLA EN LA EEPROM, O ENVIARLA A LA BASE DE DATOS
* 3. GESTIONAR LAS ALARMAS, PUESTO QUE HAY VARIOS TIPOS DE EVENTOS, PERO SOLAMENTE DOS ALARMAS
*
*/
}
if(flagAlarmA == 1)
{
for(int x = 0; x <= anCounter; x++)
{
avgAna3 = avgAna3 + anValue3[x];
}
avgAna3 = avgAna3 / anCounter; // AVERAGE OF ANALOG 3 LECTURES
saveAnalogAvg(&hi2c2, avgAna3, eepromAddressAn3);
eepromAddressAn3 = eepromAddressAn3 + 7; // PARA LA TRAMA DE DATOS QUE VAMOS A ENVIAR, NECESITAMOS 6 DIRECCIONES DE DATOS DE LA EEPROM
anCounter = 0;
avgAna3 = 0;
memset(anValue3, 0, sizeof(anValue3 ));
anCounterAdd ++;
adjustAlarm(&hrtc, &alarmA, AN_INTERVAL);
flagAlarmA = 0;
}
if(flagAlarmB == 1)
{
transmitAllData(&ra08h, &hi2c2, anCounterAdd);
/*
* DIGITAL LECTURE
*/
/*- EN TEORIA, adjustAlarm será innecesaria, porque esta alarma será cada 24 horas.-*/
adjustAlarm(&hrtc, &alarmB, DIG_INTERVAL);
anCounterAdd = 0;
flagAlarmB = 0;
}
// Retardo para evitar saturar la transmisión
/* 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};
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE4) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI
|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_4;
RCC_OscInitStruct.LSIDiv = RCC_LSI_DIV1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
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_CLOCKTYPE_PCLK3;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void saveAnalogAvg(I2C_HandleTypeDef *hi2c2, uint32_t avgAna, uint16_t eepromAddress)
{
RTC_TimeTypeDef currentTime;
RTC_DateTypeDef currentDate;
uint8_t anaWritingBuffer[4] = {0};
HAL_RTC_GetTime(&hrtc, ¤tTime, FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, ¤tDate, FORMAT_BIN);
anaWritingBuffer[0] = currentTime.Hours;
anaWritingBuffer[1] = currentTime.Minutes;
anaWritingBuffer[2] = 0; // IT CAN BE C00, OR 01
anaWritingBuffer[3] = (avgAna >> 24) & 0xFF;
anaWritingBuffer[4] = (avgAna >> 16) & 0xFF;
anaWritingBuffer[5] = (avgAna >> 8) & 0xFF;
anaWritingBuffer[6] = avgAna & 0xFF;
FM24CL_WRITE(hi2c2, FM24_1, eepromAddress, anaWritingBuffer, sizeof(anaWritingBuffer));
}
uint32_t ADC_ConvertRank3(ADC_HandleTypeDef *hadc)
{
/*
* ESTA FUNCION NOS PERMITE REALIZAR VARIAS LECTURAS ANALOGICAS, A TRAVES DE DIFERENTES CANALES SIN USAR DMA.
* HABRA UNA FUNCION POR CADA CANAL, EN CADA CUAL SE ASIGNARA EL RANK 1 AL CANAL CORRESPONDIENTE, PARA MAXIMIZAR SU PRIORIDAD
*/
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_REGULAR_RANK_2; // PARA QUE AMBOS CANALES FUNCIONEN, DEBEN AMBOS PERMANECER EN RANK 2
sConfig.SamplingTime = ADC_SAMPLETIME_5CYCLE;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
HAL_ADC_Start(hadc);
HAL_ADC_PollForConversion(hadc, 100);
uint32_t adcval = HAL_ADC_GetValue(hadc);
HAL_ADC_Stop(&hadc1);
return adcval;
}
uint32_t ADC_ConvertRank4(ADC_HandleTypeDef *hadc)
{
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = ADC_REGULAR_RANK_2;
sConfig.SamplingTime = ADC_SAMPLETIME_5CYCLE;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
HAL_ADC_Start(hadc);
HAL_ADC_PollForConversion(hadc, 100);
uint32_t adcval = HAL_ADC_GetValue(hadc);
HAL_ADC_Stop(&hadc1);
return adcval;
}
HAL_StatusTypeDef transmitAllData(RA08_Handle *ra08h, I2C_HandleTypeDef *hi2c2, uint8_t counterAdd)
{
HAL_StatusTypeDef errorFlag;
char packetToSend[60] = {0};
uint8_t bufferSend[60] = {0};
uint8_t i = 0; // Var for iteration
uint16_t address = 0;
for(i = 0; i < counterAdd; i++)
{
address = 7 * i;
errorFlag = FM24CL_RANDOM_READ(hi2c2, FM24_1, address, &bufferSend[address], 7);
itoa(bufferSend[i], &packetToSend[i], 10);
}
RA08_SendPacket(ra08h, ra08h->uart, packetToSend);
return errorFlag;
}
void adjustAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint8_t interval)
{
/*
* ACTUALIZA EL TIEMPO DE ALARMA SEGUN EL INTERVALO INDICADO POR EL USUARIO Y LA HORA ACTUAL
* AÑADIR SEGUNDOS TAMBIÉN. DOS ALARMAS NO PUEDEN COINCIDIR.
* E.G. ALARMa AT 01:59, ALARMb AT 01:57
*
*/
uint8_t anAlarm;
RTC_DateTypeDef currentDate;
RTC_TimeTypeDef currentTime;
HAL_RTC_GetTime(hrtc, ¤tTime, FORMAT_BIN);
HAL_RTC_GetDate(hrtc, ¤tDate, FORMAT_BIN);
anAlarm = interval + currentTime.Minutes;
if(anAlarm > 59)
{
anAlarm = anAlarm - 59;
}
sAlarm->AlarmTime.Minutes = anAlarm;
/*- PASAMOS DE 0 SEGUNDOS A 9. ESTO SE HACE PARA EVITAR QUE SE SOLAPEN LAS ALARMAS ENTRE ELLAS, ESPECIALMENTE CUANDO UNA ES CADA MINUTO, Y LA OTRA ES CADA DOS MINUTOS -*/
/*
if(interval >= 2)
{
sAlarm->AlarmTime.Seconds = 7;
}
*/
HAL_RTC_SetAlarm_IT(hrtc, sAlarm, FORMAT_BIN);
}
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
flagAlarmA = 1;
HAL_RTC_DeactivateAlarm(hrtc, RTC_ALARM_A);
/*
* CALLBACK FUNCTION FOR WHEN THE ALARM GOES OFF
*
* 1 SET THE ALARM AGAIN
* 2 CHANGE THE ALARM TIME
*
* e.g.
*
* ALARMA DE 1 SEGUNDO, QUE SE REEDITA CONSTANTEMENTE
*
* RTC_AlarmTypeDef sAlarm;
* HAL_RTC_GetAlarm(hrtc,&sAlarm,RTC_ALARM_A,FORMAT_BIN);
*
* NECESITAMOS ALMACENAR LOS PARAMETROS DE RTC ALARM A EN UNA STRUCT DE TIPO RTC_AlarmTypeDef
*
* if(sAlarm.AlarmTime.Seconds>58)
* {
* sAlarm.AlarmTime.Seconds=0;
*
* }
* else
* {
* sAlarm.AlarmTime.Seconds=sAlarm.AlarmTime.Seconds+1;
* }
*
* VOLVEMOS A COLOCAR LA ALARMA CON INTERRUPCION
*
* while(HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, FORMAT_BIN)!=HAL_OK){}
*
*
*/
//alarmFlag = 1;
}
void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
{
flagAlarmB = 1;
HAL_RTC_DeactivateAlarm(hrtc, RTC_ALARM_B);
/*
* WRITE YOUR CODE HERE
*/
}
/* 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 */
__disable_irq();
while (1)
{
}
/* 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,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
View more
Labels:
- Labels:
-
RTC
-
STM32U5 series
0 REPLIES 0
