查看: 7696|回复: 5

[求助] LPC54616的CAN通信,断线之后重连数据发送不出去

[复制链接]
  • TA的每日心情
    奋斗
    2021-7-8 09:06
  • 签到天数: 27 天

    [LV.4]偶尔看看III

    18

    主题

    438

    帖子

    26

    金牌会员

    Rank: 6Rank: 6

    积分
    2209
    最后登录
    2024-3-5
    发表于 2020-5-19 16:38:22 | 显示全部楼层 |阅读模式
    本帖最后由 zmh169 于 2020-5-19 16:49 编辑

    使用LPC54616的CAN外设,无阻断的中断发送模式,用连接电脑的一个CAN-USB适配器做接收节点。当我把连接线断了之后再重新连接,CAN就不能发送数据了。必须重启MCU才能再次发送。程序参考了NXP的 SDK 2.7 官方例程。类似的代码,用SDK 2.6没有问题。请问是什么原因。新版本BUG?附上代码。

    最佳答案

    提供一个猜测,做参考。是否是因为等待CAN设备的ACK?如果只有两个CAN节点,脱开一个之后,发送的报文没有ACK会发送失败,在错误过多的情况下,会主动关闭CAN收发器。 ...

    mcan_interrupt_transfer.zip

    4.65 MB, 下载次数: 34, 下载积分: 威望 1

    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    该用户从未签到

    655

    主题

    6311

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    19927
    最后登录
    2024-4-19
    发表于 2020-5-20 09:04:35 | 显示全部楼层
    当连接线断了后,调试过程中有发现代码进入loop或者中断吗?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-4-9 17:01
  • 签到天数: 1478 天

    [LV.10]以坛为家III

    203

    主题

    2万

    帖子

    64

    超级版主

    Rank: 8Rank: 8

    积分
    92609
    最后登录
    2024-4-9
    发表于 2020-5-20 19:57:17 | 显示全部楼层
    提供一个猜测,做参考。是否是因为等待CAN设备的ACK?如果只有两个CAN节点,脱开一个之后,发送的报文没有ACK会发送失败,在错误过多的情况下,会主动关闭CAN收发器。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2021-7-8 09:06
  • 签到天数: 27 天

    [LV.4]偶尔看看III

    18

    主题

    438

    帖子

    26

    金牌会员

    Rank: 6Rank: 6

    积分
    2209
    最后登录
    2024-3-5
     楼主| 发表于 2020-5-21 09:06:36 | 显示全部楼层
    小恩GG 发表于 2020-5-20 09:04
    当连接线断了后,调试过程中有发现代码进入loop或者中断吗?

    断线重连,就一直卡死在“while (!txComplete){}”循环等待中了,SDK2.6没这问题。不改SDK的情况下,可能在循环中加个超时退出是个办法。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2021-7-8 09:06
  • 签到天数: 27 天

    [LV.4]偶尔看看III

    18

    主题

    438

    帖子

    26

    金牌会员

    Rank: 6Rank: 6

    积分
    2209
    最后登录
    2024-3-5
     楼主| 发表于 2020-5-21 12:50:58 | 显示全部楼层
    stm1024 发表于 2020-5-20 19:57
    提供一个猜测,做参考。是否是因为等待CAN设备的ACK?如果只有两个CAN节点,脱开一个之后,发送的报文没有A ...

    打断点然后对比SDK2.6和SDK2.7的CAN寄存器值,发现寄存器值都一样,不是CAN配置的问题。最后通过替换两个版本的函数,发现问题在中断处理函数上,SDK2.7的CAN中断处理函数比SDK2.6复杂了不少,还没想好如何修改。
    void MCAN_TransferHandleIRQ(CAN_Type *base, mcan_handle_t *handle)
    SDK2.6的代码如下:
    1.     /* Assertion. */
    2.     assert(handle);

    3.     status_t status = kStatus_MCAN_UnHandled;
    4.     uint32_t result;

    5.     /* Store Current MCAN Module Error and Status. */
    6.     result = base->IR;

    7.     do
    8.     {
    9.         /* Solve Rx FIFO, Tx interrupt. */
    10.         if (result & kMCAN_TxTransmitCompleteFlag)
    11.         {
    12.             status = kStatus_MCAN_TxIdle;
    13.             MCAN_TransferAbortSend(base, handle, handle->txbufferIdx);
    14.         }
    15.         else if (result & kMCAN_RxFifo0NewFlag)
    16.         {
    17.             MCAN_ReadRxFifo(base, 0, handle->rxFifoFrameBuf);
    18.             status = kStatus_MCAN_RxFifo0Idle;
    19.             MCAN_TransferAbortReceiveFifo(base, 0, handle);
    20.         }
    21.         else if (result & kMCAN_RxFifo0LostFlag)
    22.         {
    23.             status = kStatus_MCAN_RxFifo0Lost;
    24.         }
    25.         else if (result & kMCAN_RxFifo1NewFlag)
    26.         {
    27.             MCAN_ReadRxFifo(base, 1, handle->rxFifoFrameBuf);
    28.             status = kStatus_MCAN_RxFifo1Idle;
    29.             MCAN_TransferAbortReceiveFifo(base, 1, handle);
    30.         }
    31.         else if (result & kMCAN_RxFifo1LostFlag)
    32.         {
    33.             status = kStatus_MCAN_RxFifo0Lost;
    34.         }
    35.         else
    36.         {
    37.             ;
    38.         }

    39.         /* Clear resolved Rx FIFO, Tx Buffer IRQ. */
    40.         MCAN_ClearStatusFlag(base, result);

    41.         /* Calling Callback Function if has one. */
    42.         if (handle->callback != NULL)
    43.         {
    44.             handle->callback(base, handle, status, result, handle->userData);
    45.         }

    46.         /* Reset return status */
    47.         status = kStatus_MCAN_UnHandled;

    48.         /* Store Current MCAN Module Error and Status. */
    49.         result = base->IR;
    50.     } while ((0 != MCAN_GetStatusFlag(base, 0xFFFFFFFFU)) ||
    51.              (0 != (result & (kMCAN_ErrorWarningIntFlag | kMCAN_BusOffIntFlag | kMCAN_ErrorPassiveIntFlag))));
    复制代码

    SDK2.7的代码如下:
    1.     /* Assertion. */
    2.     assert(NULL != handle);

    3.     status_t status = kStatus_MCAN_UnHandled;
    4.     uint32_t valueIR;
    5.     uint32_t result;

    6.     /* Store Current MCAN Module Error and Status. */
    7.     valueIR = base->IR;

    8.     do
    9.     {
    10.         if (0U != (valueIR & ((uint32_t)kMCAN_ErrorWarningIntFlag | (uint32_t)kMCAN_ErrorPassiveIntFlag |
    11.                               (uint32_t)kMCAN_BusOffIntFlag)))
    12.         {
    13.             /* Solve error. */
    14.             result = (uint32_t)kMCAN_ErrorWarningIntFlag | (uint32_t)kMCAN_ErrorPassiveIntFlag |
    15.                      (uint32_t)kMCAN_BusOffIntFlag;
    16.             status = kStatus_MCAN_ErrorStatus;
    17.         }
    18.         else if (0U != (valueIR & (uint32_t)kMCAN_TxTransmitCompleteFlag))
    19.         {
    20.             /* Solve Tx interrupt. */
    21.             result = (uint32_t)kMCAN_TxTransmitCompleteFlag;
    22.             status = kStatus_MCAN_TxIdle;
    23.             MCAN_TransferAbortSend(base, handle, handle->txbufferIdx);
    24.         }
    25.         else if (0U != (valueIR & (uint32_t)kMCAN_RxFifo0NewFlag))
    26.         {
    27.             (void)MCAN_ReadRxFifo(base, 0U, handle->rxFifoFrameBuf);
    28.             result = (uint32_t)kMCAN_RxFifo0NewFlag;
    29.             status = kStatus_MCAN_RxFifo0Idle;
    30.             MCAN_TransferAbortReceiveFifo(base, 0U, handle);
    31.         }
    32.         else if (0U != (valueIR & (uint32_t)kMCAN_RxFifo0LostFlag))
    33.         {
    34.             result = (uint32_t)kMCAN_RxFifo0LostFlag;
    35.             status = kStatus_MCAN_RxFifo0Lost;
    36.         }
    37.         else if (0U != (valueIR & (uint32_t)kMCAN_RxFifo1NewFlag))
    38.         {
    39.             (void)MCAN_ReadRxFifo(base, 1U, handle->rxFifoFrameBuf);
    40.             result = (uint32_t)kMCAN_RxFifo1NewFlag;
    41.             status = kStatus_MCAN_RxFifo1Idle;
    42.             MCAN_TransferAbortReceiveFifo(base, 1U, handle);
    43.         }
    44.         else if (0U != (valueIR & (uint32_t)kMCAN_RxFifo1LostFlag))
    45.         {
    46.             result = (uint32_t)kMCAN_RxFifo1LostFlag;
    47.             status = kStatus_MCAN_RxFifo0Lost;
    48.         }
    49.         else
    50.         {
    51.             /* Handle the interrupt flag unsupported in current version of MCAN driver.
    52.              * User can get these unsupported interrupt flags by callback function,
    53.              * we can clear directly in the handler to prevent endless loop.
    54.              */
    55.             result = valueIR;
    56.             result &= ~((uint32_t)kMCAN_ErrorWarningIntFlag | (uint32_t)kMCAN_ErrorPassiveIntFlag |
    57.                         (uint32_t)kMCAN_BusOffIntFlag | (uint32_t)kMCAN_TxTransmitCompleteFlag |
    58.                         (uint32_t)kMCAN_RxFifo0NewFlag | (uint32_t)kMCAN_RxFifo0LostFlag |
    59.                         (uint32_t)kMCAN_RxFifo1NewFlag | (uint32_t)kMCAN_RxFifo1LostFlag);
    60.         }

    61.         /* Clear Error interrupt, resolved Rx FIFO, Tx Buffer IRQ and other unsupported interrupt flags. */
    62.         MCAN_ClearStatusFlag(base, result);

    63.         /* Calling Callback Function if has one. */
    64.         if (handle->callback != NULL)
    65.         {
    66.             handle->callback(base, handle, status, result, handle->userData);
    67.         }

    68.         /* Reset return status */
    69.         status = kStatus_MCAN_UnHandled;

    70.         /* Store Current MCAN Module Error and Status. */
    71.         valueIR = base->IR;
    72.     } while (0U != valueIR);
    复制代码


    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2021-7-8 09:06
  • 签到天数: 27 天

    [LV.4]偶尔看看III

    18

    主题

    438

    帖子

    26

    金牌会员

    Rank: 6Rank: 6

    积分
    2209
    最后登录
    2024-3-5
     楼主| 发表于 2020-5-21 14:16:59 | 显示全部楼层
    本帖最后由 zmh169 于 2020-5-21 14:32 编辑

    问题已解决:
    错误标志的处理要放在最后一个else if中,否则断线后就反复处理错误,重连也从错误状态跳不出来。修改后的void MCAN_TransferHandleIRQ(CAN_Type *base, mcan_handle_t *handle)函数代码如下:
    1.     /* Assertion. */
    2.     assert(NULL != handle);

    3.     status_t status = kStatus_MCAN_UnHandled;
    4.     uint32_t valueIR;
    5.     uint32_t result;

    6.     /* Store Current MCAN Module Error and Status. */
    7.     valueIR = base->IR;

    8.     do
    9.     {
    10.         if (0U != (valueIR & (uint32_t)kMCAN_TxTransmitCompleteFlag))
    11.         {
    12.             /* Solve Tx interrupt. */
    13.             result = (uint32_t)kMCAN_TxTransmitCompleteFlag;
    14.             status = kStatus_MCAN_TxIdle;
    15.             MCAN_TransferAbortSend(base, handle, handle->txbufferIdx);
    16.         }
    17.         else if (0U != (valueIR & (uint32_t)kMCAN_RxFifo0NewFlag))
    18.         {
    19.             (void)MCAN_ReadRxFifo(base, 0U, handle->rxFifoFrameBuf);
    20.             result = (uint32_t)kMCAN_RxFifo0NewFlag;
    21.             status = kStatus_MCAN_RxFifo0Idle;
    22.             MCAN_TransferAbortReceiveFifo(base, 0U, handle);
    23.         }
    24.         else if (0U != (valueIR & (uint32_t)kMCAN_RxFifo0LostFlag))
    25.         {
    26.             result = (uint32_t)kMCAN_RxFifo0LostFlag;
    27.             status = kStatus_MCAN_RxFifo0Lost;
    28.         }
    29.         else if (0U != (valueIR & (uint32_t)kMCAN_RxFifo1NewFlag))
    30.         {
    31.             (void)MCAN_ReadRxFifo(base, 1U, handle->rxFifoFrameBuf);
    32.             result = (uint32_t)kMCAN_RxFifo1NewFlag;
    33.             status = kStatus_MCAN_RxFifo1Idle;
    34.             MCAN_TransferAbortReceiveFifo(base, 1U, handle);
    35.         }
    36.         else if (0U != (valueIR & (uint32_t)kMCAN_RxFifo1LostFlag))
    37.         {
    38.             result = (uint32_t)kMCAN_RxFifo1LostFlag;
    39.             status = kStatus_MCAN_RxFifo0Lost;
    40.         }
    41.         // 出错标志需在最后一个else if 中后处理,否则断线后重连CAN不能自动恢复
    42.         else if (0U != (valueIR & ((uint32_t)kMCAN_ErrorWarningIntFlag |
    43.                         (uint32_t)kMCAN_ErrorPassiveIntFlag |(uint32_t)kMCAN_BusOffIntFlag)))
    44.         {
    45.                 /* Solve error. */
    46.                 result = (uint32_t)kMCAN_ErrorWarningIntFlag | (uint32_t)kMCAN_ErrorPassiveIntFlag |
    47.                                 (uint32_t)kMCAN_BusOffIntFlag;
    48.                 status = kStatus_MCAN_ErrorStatus;
    49.         }
    50.         else
    51.         {
    52.             /* Handle the interrupt flag unsupported in current version of MCAN driver.
    53.              * User can get these unsupported interrupt flags by callback function,
    54.              * we can clear directly in the handler to prevent endless loop.
    55.              */
    56.             result = valueIR;
    57.             result &= ~((uint32_t)kMCAN_ErrorWarningIntFlag | (uint32_t)kMCAN_ErrorPassiveIntFlag |
    58.                         (uint32_t)kMCAN_BusOffIntFlag | (uint32_t)kMCAN_TxTransmitCompleteFlag |
    59.                         (uint32_t)kMCAN_RxFifo0NewFlag | (uint32_t)kMCAN_RxFifo0LostFlag |
    60.                         (uint32_t)kMCAN_RxFifo1NewFlag | (uint32_t)kMCAN_RxFifo1LostFlag);
    61.         }

    62.         /* Clear Error interrupt, resolved Rx FIFO, Tx Buffer IRQ and other unsupported interrupt flags. */
    63.         MCAN_ClearStatusFlag(base, result);

    64.         /* Calling Callback Function if has one. */
    65.         if (handle->callback != NULL)
    66.         {
    67.             handle->callback(base, handle, status, result, handle->userData);
    68.         }

    69.         /* Reset return status */
    70.         status = kStatus_MCAN_UnHandled;

    71.         /* Store Current MCAN Module Error and Status. */
    72.         valueIR = base->IR;
    73.     } while (0U != valueIR);
    复制代码



    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-19 16:41 , Processed in 0.128008 second(s), 27 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表