C 同步不同的消息

C 同步不同的消息,c,stm32,can-bus,C,Stm32,Can Bus,我认为这是一个通用的软件范例问题,所以它与嵌入式软件没有太大关系 我在不同的时间段收到3条消息,这三条消息是 奥多,速度,gps。每个都有20ms、1秒和1秒的时间片 我的问题是,只有当这三条消息已经被获取时,我如何才能同步并获得完整的消息 我目前的方法是使用三个循环队列,放置三个布尔变量并检查它们是否都同步,但如果例如具有20ms时间片的odo在没有其他消息的情况下被反复拉取,则这不起作用 以下是我正在做的: void HAL_CAN_RxFifo0MsgPendingCallback(CAN

我认为这是一个通用的软件范例问题,所以它与嵌入式软件没有太大关系

我在不同的时间段收到3条消息,这三条消息是 奥多,速度,gps。每个都有20ms、1秒和1秒的时间片

我的问题是,只有当这三条消息已经被获取时,我如何才能同步并获得完整的消息

我目前的方法是使用三个循环队列,放置三个布尔变量并检查它们是否都同步,但如果例如具有20ms时间片的odo在没有其他消息的情况下被反复拉取,则这不起作用

以下是我正在做的:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{

  HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxMessage, RxData);
  static bool t1 = 0, t2=0, t3 =0;

  if (RxMessage.StdId == 0x098)
  {
    insertCirQueue(&q_velocity, 0x098);
    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
    t1=1;
  }
  else if (RxMessage.StdId == 0x309)
  {
    /* Rx message Error */
    insertCirQueue(&q_Odo, 0x309);
    t2=1;
    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13);
  }
  else if (RxMessage.StdId == 0x3EB)
  {
    /* Rx message Error */
    insertCirQueue(&q_Gps, 0x3EB);
    t3=1;
    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14);
  }

  if (t1 && t2 && t3)
  {
    t2 = t3 = t1 = 0;
    isSynced = true;
  }
}
并在主循环中

 if (isSynced)
      {
        isSynced = false;

        int vel[8] = {0}, gps[8] = {0}, odo[8] = {0};
        int counter = 0;
        while (!isEmpty(&q_velocity))
        {
          if (deleteCirQueue(&q_velocity, &vel[counter++]) == -1)
              break;
        }

        counter = 0;
        while (!isEmpty(&q_Gps))
        {
          if(deleteCirQueue(&q_Gps, &gps[counter++]) == -1)
              break;
        }

        counter = 0;
        while (!isEmpty(&q_Odo))
        {

          if(deleteCirQueue(&q_Odo, &odo[counter++]) == -1)
             break;
        }

创建一个位字段,并为每个接收的消息类型设置一个位

typedef enum
{
  RECEIVED_NONE = 0x00,
  RECEIVED_ODO  = 0x01,
  RECEIVED_VELO = 0x02,
  RECEIVED_GPS  = 0x04,
  RECEIVED_ALL  = RECEIVED_ODO | RECEIVED_VELO | RECEIVED_GPS,
} can_received_t;



can_received_t can_received = RECEIVED_NONE;

if(/* received odo */)
{
  can_received |= RECEIVED_ODO;
}

...

if(can_received == RECEIVED_ALL)
{
  can_received = RECEIVED_NONE;
  ...
}

不过,存储队列似乎有些可疑。作为实时总线,CAN的正常过程是只保留最新的有效包,而丢弃其余的包。尤其是在处理传感器和控制功能时。

您可以只使用每次收到的最后一个值。因此,您可以收到里程表的一系列更新,但只有在收集到最后一个gps/速度时才能“锁定”里程表(选择一个进行同步)。如果你是从一个定期和可预测地向你发送消息的系统中获取它们,那就很容易了。除了最终确定的值(如果您想查看/使用趋势历史记录),您甚至不需要队列


如果你关心的是同步和准确,你可以插值你的速度。对里程表执行与上述相同的操作,并在收集GPS后停止保存里程表。采集2个速度值(GPS采集之前和之后)。插值速度(线性)以在GPS采集时生成速度值。然后报告出来。这将在每次采集速度时生成一个同步且准确的值,延迟速度/GPS采集时间戳之间的偏移量。

当您说时间片时,是指当时的单个数据点吗,或者你的意思是点块?@yhyrcanus single datapoint当时我也对检索接收到的数据感兴趣,我应该使用什么类型的存储。。这就是为什么我用了一个循环queue@andreahmed您应该只需要存储最新消息,因此对于标准CAN,每个消息类型将是一个8字节的数组。@andreahmed是否只声明一个每个消息类型8字节的数组<代码>uint8_t foo[8]。它可以被包装在结构中,但显然ST的“HAL”正在返回带有数据负载的原始阵列。