STM32 CAN收发问题

1.想要实现can发送多条报文,且每条报文都有自己的周期。例如:ID为100,循环发送周期50ms。ID为200,循环发送周期为50ms。每条报文按自己的周期循环。
2.试过了在while 1里面,加上循环,但是这样每条报文的周期会叠加。

要实现CAN发送多条报文,并且每条报文都有自己的周期,你可以使用定时器来控制发送的周期。以下是一种可能的实现方法:

  1. 配置CAN通信和定时器:

    • 首先,确保你已经正确地配置了CAN总线和相关的GPIO引脚。
    • 然后,配置一个定时器(比如TIM2)来控制发送的周期。选择一个适当的定时器时钟频率和预分频值,以获得所需的时间基准。
  2. 创建报文发送队列:

    • 定义一个结构体来表示每个报文的属性,包括ID、数据、周期等信息。
    • 创建一个数组,用于存储要发送的报文队列。
  3. 初始化报文队列:

    • 在代码中创建一个包含所有要发送报文的数组。
    • 为每个报文设置相应的ID、数据和周期。
  4. 设置定时器中断:

    • 在定时器的中断回调函数中,触发CAN报文的发送。
    • 在中断回调函数中,遍历报文队列并检查每个报文的周期是否满足发送条件。
    • 如果周期满足发送条件,通过CAN发送报文。
  5. 更新报文周期:

    • 在发送报文后,更新报文的周期以便下次发送。
    • 可以通过增加一个计数器或使用时间戳的方式来实现。

下面是一个简单的示例代码,可以帮助你更好地理解上述的实现方法:

// 报文属性结构体
typedef struct {
  uint32_t id;
  uint8_t data[8];
  uint32_t period;
  uint32_t timestamp;
} CAN_Message;

// 报文队列
CAN_Message messageQueue[] = {
  {100, {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22}, 50, 0},  // 报文1,周期50ms
  {200, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, 100, 0}  // 报文2,周期100ms
};

int queueSize = sizeof(messageQueue) / sizeof(CAN_Message);

// 定时器中断回调函数
void TIM2_IRQHandler() {
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
    // 遍历报文队列
    for (int i = 0; i < queueSize; i++) {
      // 检查报文的周期是否满足发送条件
      if (HAL_GetTick() - messageQueue[i].timestamp >= messageQueue[i].period) {
        // 更新报文的时间戳
        messageQueue[i].timestamp = HAL_GetTick();
        
        // 使用CAN发送报文
        CAN_TxHeaderTypeDef txHeader;
        txHeader.StdId = messageQueue[i].id;
        txHeader.IDE = CAN_ID_STD;
        txHeader.RTR =

 CAN_RTR_DATA;
        txHeader.DLC = 8;
        txHeader.TransmitGlobalTime = DISABLE;
        
        uint32_t txMailbox;
        HAL_CAN_AddTxMessage(&hcan, &txHeader, messageQueue[i].data, &txMailbox);
      }
    }
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  }
}

int main() {
  // 初始化CAN和定时器等相关配置
  
  // 启动定时器
  HAL_TIM_Base_Start_IT(&htim2);
  
  while (1) {
    // 主循环
  }
}

上述代码假设你已经正确配置了CAN总线和定时器,并在代码中使用了适当的函数和变量来实现相关的功能。记得根据你的具体硬件平台和使用的STM32系列进行适当的调整。

请注意,以上代码只是一个示例,具体的实现方式可能因为硬件平台、使用的库和设备的不同而有所不同。你可能需要根据自己的需求进行适当的调整和修改。

  • 这篇博客: STM32 CAN通讯过滤器使用总结及代码分析中的 CAN ID值的结构分析(非常重要) 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • ISO11898的定义,如下图:

    如上图,基本格式不存在扩展ID,而扩展格式中ID0~ID17为Extension ID,而ID18~ID28为Base ID.

    因此CAN ID值0x1800f001用二进制表示为:0b 0001 1000 0000 0000 1111 0000 0000 0001,用括号分别区别为:0b 000[1 1000 0000 00][00 1111 0000 0000 0001],红色部分为扩展ID,蓝色部分为基本ID。

    举例:0x35e    二进制:0000 0011 0101 1110     需要左移两位与上图基本ID位对齐,还需左移三位与下图寄存器位对齐。

    扩展ID0x0187  相对简单,本身与上图扩展ID位对齐,只需要左移三位即可与下面寄存器位对齐。(自己理解了好久,唉)