我在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 时,在使用FreeRTOS时,osDelay
似乎更合适。
我只能想到的原因是ST Link缺乏兼容性或驱动程序,或者无法在中断触发的回调函数中包含延迟。
感谢您的帮助。
答案 0 :(得分:2)
与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()
应该以32位无符号值返回自启动以来经过的时间(以毫秒为单位)。您可以提供自己的HAL_GetTick()
实现,该实现使用32位硬件计时器来确定当前时间。
有两个32位计时器TIM2
和TIM5
,请选择其中一个。将重载值设置为APB1时钟频率除以1000减1(默认时钟设置为83999),开始递增计数。现在HAL_GetTick()
可以简单地返回计时器计数器寄存器。
uint32_t HAL_GetTick(void) {
return TIM2->CNT; // or TIM5->CNT
}
编写您自己的延迟功能
例如,您可以使用cycle counter来缩短延迟,或者使用空的for
循环来获得近似的延迟,启动单次计时器并等待直到完成,等等。
答案 1 :(得分:0)
您不能从中断处理程序中调用延迟函数。请记住,中断处理程序的目的是尽快执行,以便程序可以恢复正常执行,而延迟与该概念不兼容。