在 STM32 上使用调试器时如何使用延迟?
How to used delays when using debugger with STM32?
我在 STM32F407 MCU 上使用 ST Link 调试器。我遇到的问题是数据在不同的循环缓冲区之间没有以正确的方式加载,用于从 USART 中提取字节。我想看看从 serial [4000]
数组中提取帧的线程在增加延迟后的表现如何。
下面的代码在调试器中运行良好,我可以进入每一行,并检查变量的值。
//This callback is automatically called by the HAL when the DMA transfer is completed
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
// read 50 bytes of raw data to the raw_serial buffer
HAL_UART_Receive_DMA (huart, raw_serial, 50);
//osDelay(10);
//HAL_Delay(10);
// add raw_serial to the serial[4000]
AppendSerial(raw_serial,size);
}
使用这些延迟之一:
osDelay(10);
HAL_Delay(10);
导致程序执行陷入倒计时循环之一,并阻止我到达位于等待语句之后的断点。
阅读本文 post 在我看来 osDelay
在使用 FreeRTOS 时更合适。
我能想到的唯一原因是 ST Link 缺乏兼容性或驱动程序,或者无法在中断触发的回调函数中包含延迟。
感谢您的帮助。
您不能从中断处理程序中调用延迟函数。请记住,中断处理程序的目的是尽快执行,以便程序可以 return 正常执行,延迟与该概念不兼容。
与ST-Link无关。
默认情况下,延迟函数通过监视在定时器中断中递增的变量来工作。如果该定时器中断被阻塞,则变量不会递增,延迟函数将永远不会完成。有几种解决方法。
让定时器中断抢占串行中断处理程序
确保定时器中断的优先级高于串口中断。默认情况下,HAL 在 stm32f4xx_hal_conf.h
中将定时器中断设置为尽可能低的优先级(IMO 相当愚蠢的想法)
#define TICK_INT_PRIORITY 0x0FU /*!< tick interrupt priority */
将其更改为较低的值(较高的优先级),并将 UART 中断的优先级设置为较高的值(较低的优先级)。现在,HAL_Delay()
即使在 UART 中断处理程序中也可以工作。
使 HAL_Delay()
不间断地工作
HAL_Delay()
通过重复调用 HAL_GetTick()
直到延迟时间结束。 HAL_GetTick()
应该 return 自启动以来经过的时间(以毫秒为单位)作为 32 位无符号值。您可以提供自己的 HAL_GetTick()
实现,它使用 32 位硬件计时器来确定当前时间。
有两个32位定时器,TIM2
和TIM5
,选一个。将重载值设置为 APB1 时钟频率除以 1000 减 1(默认时钟设置为 83999),开始向上计数。现在HAL_GetTick()
可以简单地return定时器计数寄存器。
uint32_t HAL_GetTick(void) {
return TIM2->CNT; // or TIM5->CNT
}
编写自己的延迟函数
例如,您可以使用 进行短暂的延迟,或者使用一个空的 for
循环来进行近似延迟,启动一次性计时器并等待完成等。
我在 STM32F407 MCU 上使用 ST Link 调试器。我遇到的问题是数据在不同的循环缓冲区之间没有以正确的方式加载,用于从 USART 中提取字节。我想看看从 serial [4000]
数组中提取帧的线程在增加延迟后的表现如何。
下面的代码在调试器中运行良好,我可以进入每一行,并检查变量的值。
//This callback is automatically called by the HAL when the DMA transfer is completed
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
// read 50 bytes of raw data to the raw_serial buffer
HAL_UART_Receive_DMA (huart, raw_serial, 50);
//osDelay(10);
//HAL_Delay(10);
// add raw_serial to the serial[4000]
AppendSerial(raw_serial,size);
}
使用这些延迟之一:
osDelay(10);
HAL_Delay(10);
导致程序执行陷入倒计时循环之一,并阻止我到达位于等待语句之后的断点。
阅读本文 post 在我看来 osDelay
在使用 FreeRTOS 时更合适。
我能想到的唯一原因是 ST Link 缺乏兼容性或驱动程序,或者无法在中断触发的回调函数中包含延迟。
感谢您的帮助。
您不能从中断处理程序中调用延迟函数。请记住,中断处理程序的目的是尽快执行,以便程序可以 return 正常执行,延迟与该概念不兼容。
与ST-Link无关。
默认情况下,延迟函数通过监视在定时器中断中递增的变量来工作。如果该定时器中断被阻塞,则变量不会递增,延迟函数将永远不会完成。有几种解决方法。
让定时器中断抢占串行中断处理程序
确保定时器中断的优先级高于串口中断。默认情况下,HAL 在 stm32f4xx_hal_conf.h
#define TICK_INT_PRIORITY 0x0FU /*!< tick interrupt priority */
将其更改为较低的值(较高的优先级),并将 UART 中断的优先级设置为较高的值(较低的优先级)。现在,HAL_Delay()
即使在 UART 中断处理程序中也可以工作。
使 HAL_Delay()
不间断地工作
HAL_Delay()
通过重复调用 HAL_GetTick()
直到延迟时间结束。 HAL_GetTick()
应该 return 自启动以来经过的时间(以毫秒为单位)作为 32 位无符号值。您可以提供自己的 HAL_GetTick()
实现,它使用 32 位硬件计时器来确定当前时间。
有两个32位定时器,TIM2
和TIM5
,选一个。将重载值设置为 APB1 时钟频率除以 1000 减 1(默认时钟设置为 83999),开始向上计数。现在HAL_GetTick()
可以简单地return定时器计数寄存器。
uint32_t HAL_GetTick(void) {
return TIM2->CNT; // or TIM5->CNT
}
编写自己的延迟函数
例如,您可以使用 for
循环来进行近似延迟,启动一次性计时器并等待完成等。