这就是我所拥有的:具有输入的PCA9555芯片,如果输入上的信号状态发生变化,中断信号就会被发送。然后我可以通过I2C读取芯片来检查输入。
我需要什么-当一个引脚改变状态时,我需要读取芯片,检查哪个引脚改变了状态并通知我的应用程序。
所以我有一个中断,中断处理程序不能阻止MCU。
我明显的选择是使用HAL_I2C_Mem_Read_IT(),对吗?
我做了完整的代码,测试了它。好像成功了..。一段时间。
直到我增加了每100毫秒读一次芯片。
代码仍然工作,但我看到闪烁的东西结结巴巴,停止闪烁超过一秒,甚至2。因此,很明显,HAL_I2C_Mem_Read_IT()阻止我的中断,使单片机冻结。
我查了一下HAL的资料,发现如下:
static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
uint32_t Tickstart)
{
I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
/* Wait until TXIS flag is set */
if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
{
return HAL_ERROR;
}
/* If Memory address size is 8Bit */
if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
{
/* Send Memory Address */
hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
}
/* If Memory address size is 16Bit */
else
{
/* Send MSB of Memory Address */
hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
/* Wait until TXIS flag is set */
if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
{
return HAL_ERROR;
}
/* Send LSB of Memory Address */
hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
}
/* Wait until TC flag is set */
if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, Tickstart) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}
正如I2C_WaitOnTXISFlagUntilTimeout()
这个名字所暗示的,它等待着。是的,它是一个while
循环,它阻止正在执行的线程,直到设置了标志:
static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status,
uint32_t Timeout, uint32_t Tickstart)
{
while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)
{
/* Check for the Timeout */
if (Timeout != HAL_MAX_DELAY)
{
if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
{
hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
hi2c->State = HAL_I2C_STATE_READY;
hi2c->Mode = HAL_I2C_MODE_NONE;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_ERROR;
}
}
}
return HAL_OK;
}
这些滞后函数有3个。
对于我的应用程序,这是一个节目停止。它只是不起作用,因为它依赖于实时处理事件。此外,它还有一个GUI,当中断处理程序阻塞时,它会冻结。
有什么快速的解决办法吗?是HAL司机的窃听器吗?
我必须实现自己的非阻塞功能吗?这看起来像是很多很多小时的编码,因为这个函数并不简单,并且与模块的其余部分紧密耦合。
我的想法是重写它,用我的非阻塞延迟函数替换while
循环,该函数使用计时器中断在一段时间后继续工作。为了使其变得更重要,每个回调都必须接收必要的状态数据才能继续。然后是状态机,以确定我们在I2C_RequestMemoryRead_
进程中的位置。最后,我只需拨打注册电话就可以了。它应该能正常工作.
但我还有最后期限。能做得更快吗?HAL "_IT“函数怎么可能用while
循环阻塞线程呢?这是错的!它违背了“中断模式函数”的全部目的。如果它阻塞,那么已经有了一个更简单的阻塞版本。
发布于 2022-07-03 14:20:59
我解决了黑客攻击原HAL司机的问题。
https://gist.github.com/HTD/e36fb68488742f27a737a5d096170623
在将文件添加到项目之后,需要像stm32h7xx_hal_i2c_nb.h注释中所描述的那样修改原始HAL驱动程序。
为了与STM32CubeIDE一起使用,最好将修改后的驱动程序文件移动到不同的位置,以防止IDE覆盖它。
我将其他*IT函数保持不变,但很容易将类似的修改添加到其余的所有函数中。
在我的STM32H747I-Diso板上用PCA9555 16位I/O扩展器测试了被黑客攻击的驱动程序。
对于测试,我垃圾输入随机噪声信号,刚刚崩溃了原来的驱动器。在这里,它可以工作,不会阻塞其他线程,GUI可以全速工作。
https://stackoverflow.com/questions/72840119
复制相似问题