在 STM32 上延时两小时上传传感器数据时,直接使用 delay 函数是不推荐的,尤其是像 HAL_Delay() 或基于忙等待的 delay 函数,因为它会阻塞 CPU,导致 MCU 在延时期间无法执行其他任务。
如果你不需要精确到秒的延时,下面介绍几个专业且有意思的方法,既能保证延时,又不影响 MCU 的其他工作。
1
使用定时器和中断
STM32 提供了丰富的定时器资源,可以用定时器配合中断来进行非阻塞延时。
你可以设置定时器每隔一段时间产生中断,并在中断处理函数中累计时间,直到达到两小时的时间间隔。这种方式不仅能保持系统的低功耗,还能在延时期间执行其他任务。
具体步骤:
使用 STM32 的一个定时器(如 TIM2),设定定时器的周期为1秒或者1分钟。
在每次定时器溢出中断时,递增一个变量来记录累计的时间。
当累计时间达到两小时(7200秒)时,上传数据并重置计数器。
示例代码如下:
volatile uint32_t seconds_elapsed = 0;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
seconds_elapsed++;
if (seconds_elapsed >= 7200) // 2 hours
{
upload_sensor_data();
seconds_elapsed = 0;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
void setup_timer()
{
// Timer configuration code here
// Set the timer to trigger every second or minute
}
2
低功耗模式配合 RTC(实时时钟)唤醒
如果你希望 STM32 在不需要工作时处于低功耗模式,RTC 是一个理想的选择。
STM32 的 RTC 模块不仅可以保持时间跟踪,还可以设置定时唤醒 MCU,节省电量,尤其在低功耗物联网设备中广泛使用。
步骤如下:
配置 RTC 定时唤醒中断,每两小时触发一次。
MCU 在唤醒时上传数据,然后再次进入低功耗模式等待下一个唤醒信号。
示例代码如下:
void RTC_Wakeup_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_WUT) != RESET)
{
upload_sensor_data();
RTC_ClearITPendingBit(RTC_IT_WUT);
}
}
void setup_rtc()
{
// 配置 RTC 为每 2 小时唤醒一次
}
这种方式可以让你的 MCU 大部分时间处于睡眠状态,仅在需要上传数据时唤醒,非常适合对功耗敏感的应用场景。
3
RTOS软件定时器
如果你的项目使用了 RTOS,例如FreeRTOS 。可以直接利用 FreeRTOS 的软件定时器来处理延时。软件定时器是 FreeRTOS 中的任务之一,它在后台运行,支持精确到毫秒级别的定时。
如果你不需要非常精确的延时,可以把定时器的周期设为 2 小时,定时器到期时调用上传数据的任务。
示例代码如下:
void vUploadDataCallback(TimerHandle_t xTimer)
{
upload_sensor_data();
}
void setup_software_timer()
{
TimerHandle_t xTimer = xTimerCreate("UploadTimer", pdMS_TO_TICKS(7200000), pdTRUE, 0, vUploadDataCallback);
xTimerStart(xTimer, 0);
}
这也是一种非常灵活的方案,并且在 FreeRTOS 环境下易于实现,可以同时执行其他任务。
从专业的角度来看,基于定时器和中断、RTC 低功耗唤醒或 RTOS软件定时器的方式都比 delay 函数更高效,不会阻塞系统,确保 STM32 能在等待的过程中处理其他任务。
这些方式不仅更加专业,还是嵌入式系统开发中比较“优雅”的解决方案,尤其是在资源有限和功耗敏感的设备上。
最后,选择哪种方式主要取决于你的具体项目需求和资源:
如果对功耗比较敏感,RTC 低功耗唤醒是最佳选择。
如果你的项目已经在使用 RTOS,那软件定时器会更方便。
如果你希望保持简单但不阻塞系统,定时器中断是经典的做法。