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 */
2025-04-08 6:05 AM
Hello @oliverTelecom and welcome to the community;
I recommend to look at the Getting started with RTC - stm32mcu wiki and check the RTC initialization.
Then, you can based on STM32CubeMX toolchain to use the alarm masks to ignore days, hours as mentioned in this wiki.
I hope this help you.
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.