2024-10-26 06:42 AM
Hello Everyone,
I'm currently working on a project using the STM32L4 micro controller, where I'm developing a multi-level menu system displayed on a Segment LCD. I'm using a magnetic switch connected to a GPIO pin, which is configured to trigger interrupts on both rising and falling edges.
What i am trying to do is,
Main Menu Switching: When the magnetic switch is held for more than 2 seconds, the system should cycle through the main menu options.
Sub menu Navigation: When the magnetic switch is held for 1 second or less, it should allow navigation within the sub menus of the current main menu.
If the switch is held for a duration between 1 to 2 seconds, no action is taken.
Implementation: To achieve this, I use the HAL_GetTick() function to measure the duration for which the magnet is near the switch. Below is a summary of the code:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch (GPIO_Pin)
{
case BSP_LCD_MAG_SWITCH_Pin:
METER_DEBUG("Magnetic Interrupt\r\n");
uint32_t current_time = HAL_GetTick(); // Get the current time in ms
METER_DEBUG("Current time = %ld\r\n", current_time);
if (!magnet_near_switch)
{
// Rising edge: magnet brought near the switch
magnet_near_switch = true;
start_time = current_time; // Record the start time
METER_DEBUG("start time = %ld\r\n", start_time);
}
else
{
// Falling edge: magnet moved away from the switch
magnet_near_switch = false;
uint32_t hold_duration = 0;
hold_duration = current_time - start_time; // Calculate hold time
METER_DEBUG("hold_duration = %ld\r\n", hold_duration);
if (hold_duration > 2000)
{ // Held for more than 2 seconds
// Switch between main menus
current_menu = (current_menu + 1) % 4; // Cycle through main menus
in_submenu = false; // Exit submenu mode
METER_DEBUG("Update main menu display\r\n");
update_lcd_menu(current_menu);
}
else if (hold_duration <= 1000)
{ // Held for 1 second or less
// Switch between submenus within the current main menu
if (in_submenu)
{
current_submenu = (current_submenu + 1) % 4; // Cycle through submenus
}
else
{
in_submenu = true; // Enter submenu mode if not already in
current_submenu = 0; // Start from the first submenu
}
METER_DEBUG("Update sub menu display\r\n");
update_lcd_submenu(current_menu, current_submenu);
}
}
break;
}
}
Problems I'm Facing:
1)Inconsistent Behavior: Occasionally, the system exits the submenu unexpectedly or doesn't navigate through the main menu as intended.
2)Power Mode Impact: I’m using the sequencer, which places the system in Stop 2 mode during idle states. This seems to affect the accuracy of the HAL_GetTick() function, leading to unreliable timing calculations.
Questions:
1)Timing Accuracy in Low-Power Mode: Is HAL_GetTick() suitable for time measurements in a system that frequently enters Stop 2 mode? If not, what alternatives can I use to get accurate timing, especially for durations like 2 seconds and 1 second?
2)RTC-Based Timing: Would using the RTC peripheral to track the timing be a more reliable approach? If yes, any guidance on implementing RTC-based time tracking in this scenario?
I am not able to get proper time ticks at HAL_GetTick() on an interrupt. please any one suggest me why HAL_GetTick() function not working properly, Did i miss some configuration?
Thanks in advance.
Taksh
2024-10-26 07:45 AM
Make sure the SysTick interrupt has a priority setting that preempts everything else, it just has to increment a count, so isn't going to have a significant impact on other execution.
Perhaps use a 32-bit TIM, maximal/free-run, provide for a timebase directly from the TIM->CNT register.
2024-10-26 08:20 AM
If you're using stop mode 2, then Systick is not running. You should use the RTC. You can look at the example code ST provides in the repository that is on your computer. Or you can use the Example selector when you start a new project in STM32CubeIDE