同步不同的消息
Synchronizing different messages
我认为这是一个普遍的软件范式问题,所以它与嵌入式软件关系不大。
我在不同的时间片收到了 3 条消息,这三条消息是
Odo,速度,gps。每个都有时间片 20 毫秒、1 秒和 1 秒。
我的问题是,只有当三个消息都已获取时,我如何才能同步并获得完整的消息。
我目前的方法是拥有三个循环队列,并放置三个布尔变量并检查它们是否全部同步,但是如果例如具有 20 毫秒时间片的 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;
}
您创建一个 bit-field,并为每个收到的消息类型设置一个位。
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;
...
}
虽然存储队列看起来很可疑。作为 real-time 总线的 CAN 的正常程序是您只保留最新的有效包并丢弃其余包。特别是在处理传感器和控制功能时。
您可以只使用每次收到的最后一个值。所以你可以收到一堆里程表更新,但只有 "latch" 它是在最后一个 gps/velocity 被收集时(选择一个同步到)。如果您从定期和可预测地向您发送消息的系统中获取它们,那很容易。你甚至不需要队列,除了最终值(如果你想 see/use 趋势历史)。
如果您关心同步和准确,您可以插入速度。对里程表执行与上述相同的操作,并在收集到 GPS 后停止保存。收集 2 个速度值(GPS 收集之前和之后)。插值速度(线性)以生成 GPS 收集时间的速度值。然后报告出来。这将在每次收集速度时生成一个同步且准确的值,延迟了 velocity/GPS 收集时间戳之间的偏移量。
我认为这是一个普遍的软件范式问题,所以它与嵌入式软件关系不大。
我在不同的时间片收到了 3 条消息,这三条消息是 Odo,速度,gps。每个都有时间片 20 毫秒、1 秒和 1 秒。
我的问题是,只有当三个消息都已获取时,我如何才能同步并获得完整的消息。
我目前的方法是拥有三个循环队列,并放置三个布尔变量并检查它们是否全部同步,但是如果例如具有 20 毫秒时间片的 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;
}
您创建一个 bit-field,并为每个收到的消息类型设置一个位。
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;
...
}
虽然存储队列看起来很可疑。作为 real-time 总线的 CAN 的正常程序是您只保留最新的有效包并丢弃其余包。特别是在处理传感器和控制功能时。
您可以只使用每次收到的最后一个值。所以你可以收到一堆里程表更新,但只有 "latch" 它是在最后一个 gps/velocity 被收集时(选择一个同步到)。如果您从定期和可预测地向您发送消息的系统中获取它们,那很容易。你甚至不需要队列,除了最终值(如果你想 see/use 趋势历史)。
如果您关心同步和准确,您可以插入速度。对里程表执行与上述相同的操作,并在收集到 GPS 后停止保存。收集 2 个速度值(GPS 收集之前和之后)。插值速度(线性)以生成 GPS 收集时间的速度值。然后报告出来。这将在每次收集速度时生成一个同步且准确的值,延迟了 velocity/GPS 收集时间戳之间的偏移量。