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);
我正在使用 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);