2

简而言之,手动复位 SLEEP 位时,SLAK 位不会复位。详细说明:

在尝试建立网络之前,我正在尝试以环回模式成功传输。经过大量文档阅读后,我让它在某个时候工作,但现在我遇到了一个新问题。(遗憾的是我不记得我改变了什么,也许是在玩时间)

在将外设设置为环回并提供一致的位时序值(所以我可能已经使用它们但它们恢复正常)后,我使用 Cube 生成代码。这意味着流程应该首先退出睡眠模式,进入初始化模式,进行设置,退出初始化模式,然后启动正常模式。根据参考手册:

如果在 bxCAN 处于休眠模式时软件通过设置 INRQ 位来请求进入初始化模式,它还必须清除 SLEEP 位。[...] 清除 SLEEP 位后,一旦 bxCAN与 CAN 总线同步,就会退出休眠模式[...]。一旦SLAK 位被硬件清零,就退出休眠模式

为了同步,bxCAN 一直等到 CAN 总线空闲,这意味着在 CANRX上已经监视了11 个连续的隐性位。

根据维基

0 数据位编码显性状态,而1 数据位编码隐性状态

所以

检查 Cube 生成的代码,这正是正在发生的事情。我在这里粘贴了 stm32f4xx_hal_can.c 的重要部分:

HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan)
{
  [...]

  /* Exit from sleep mode */
  CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);

  /* Get tick */
  tickstart = HAL_GetTick();

  /* Check Sleep mode leave acknowledge */
  while ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U)
  {
    if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
    {
      [...]
      /*Error*/
    }
  }

  /* Request initialisation */
  SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ);

  /* Get tick */
  tickstart = HAL_GetTick();

  /* Wait initialisation acknowledge */
  while ((hcan->Instance->MSR & CAN_MSR_INAK) == 0U)
  {
    if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
    {
      [...]
      /*Error*/
    }

CAN_MSR 的 SLEEP 位被复位并等待来自 CAN_MSR 的 SLAK 位被硬件复位。CAN_TIMEOUT_VALUE 设置为 10,基本上是给 11 个隐性位稳定下来的时间。

这就是我卡住的地方。SLACK 不会重置...我试图移除if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE),以便 MCU 无限期地等待 SLAK 重置。没有帮助。

查看 CAN_MSR RX 寄存器,给出 RX 上的当前值,同时等待 SLACK 变化,我注意到它始终为 0。所以我尝试将 GPIO 设置为 RX 和 TX 的上拉和下拉,但是我认为它没有效果,因为在环回模式下,bxCAN 的 RX 与 GPIO 隔离 :) 这也意味着,问题不应该出现在硬件方面(如布线和东西,外部事物,而不是内部硬件)。让我相信在全局 HAL_Init() 或 MX_GPIO_Init() 或其他东西期间出了点问题,但由于它是由 Cube 生成的,我没有改变任何东西,我看不出它如何对 SLAK 产生影响离开。

我的想法可能是在某事上进行软件重置,但我不知道这条路将把我带到哪里,因为关闭电源并在芯片上不能解决问题......

4

0 回答 0