STM32 上 bxCAN i/f 的重要示例代码?

Non trivial example code for the bxCAN i/f on the STM32?

我正在使用 STM 外设库来设置和使用 CANBus。问题是我必须在 Tx 数据包之间放置一个延迟,否则我会开始丢弃数据包。放入读取状态循环等似乎没有任何效果。有没有人有一个不包括添加幻数延迟的工作示例?

这并非特定于 CAN 或 STM32,而是关于控制微控制器中某事发生的频率。

有几种方法可以解决这个问题:

1) 使用计时器

设置一个定时器,使其以您希望的传输速率产生中断。 (即每 10 毫秒)使用中断来触发您的传输代码。请注意,您的中断服务程序应尽可能短;它可以简单地设置主循环检查的 "go" 标志,当它被设置时,清除标志,传输,然后等待它再次被设置。

2) 使用实时操作系统,例如FreeRTOS

RTOS 通常与上面的定时器方法类似,但抽象细节并以稳健的方式进行。如果需要,您可以创建多个按不同计划运行的任务。例如,您可能需要每 10 毫秒传输一次数据,但仅每 200 毫秒更新一次指示。

我正在使用 STM32 + HAL + FreeRTOS

你需要放魔法#延迟意味着你已经用完了所有 3x 邮箱。所以你需要一些队列来保存额外的数据。我就是这样解决问题的

  • 我有一个任务,接受以下事件

    • 传输完成 IRQ
    • 传输请求
  • 任务结构如下

    • Busy/idle 3x 邮箱状态
    • 保存要传输数据的本地队列
  • 根据传输请求,将数据放入本地队列,并调用transmission()

  • 传输完成IRQ后,将相应的邮箱标记为空闲,并调用transmission()
  • transmission()的伪代码
    • 如果没有免费邮箱,就return
    • 查找空闲邮箱[n],将邮箱[n]标记为忙,并与其进行传输

仔细查看 SPL CAN_Transmit() return 值:

  • @retval The number of the mailbox that is used for transmission or CAN_TxStatus_NoMailBox if there is no empty mailbox.

因此您可以执行某种检查:

    uint8_t retry_count = RETRY_COUNT;
    while(retry_count && CAN_Transmit(CAN1, &TxMessage) == CAN_TxStatus_NoMailBox)
    {
        // <-- still you could delay here
        retry_count--;
    }

或者只是

while(CAN_Transmit(CAN1, &TxMessage) == CAN_TxStatus_NoMailBox);