我认为这是一个通用的软件范例问题,因此它与嵌入式软件关系不大。
我有3条在不同时间段收到的消息,这3条消息分别是 Odo,速度,gps。每个都有20ms,1sec和1sec的时间片。
我的问题是,只有当这三个文件都已被提取时,我如何才能同步并获得完整的消息。
我当前的方法是有三个循环队列,并放入三个布尔变量并检查它们是否全部同步,但是如果例如具有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;
}
答案 0 :(得分:1)
您创建一个位字段,并为每种接收到的消息类型设置一个位。
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作为实时总线的正常过程是,您只保留最新的有效软件包,而丢弃其余的软件包。尤其是在处理传感器和控制功能时。
答案 1 :(得分:0)
您可以只使用每次收到的最后一个值。因此,您可能会收到里程表的大量更新,但是只有在收集到最后的gps /速度时才“锁存”它(选择一个同步)。如果要从定期且可预测地向您发送消息的系统中获取消息,那很容易。除了最终值(如果您想查看/使用趋势历史记录),您甚至都不需要队列。
如果您希望同步和准确无误,则可以内插速度。对里程表执行与上述相同的操作,并在收集GPS后停止保存。收集2个速度值(在GPS收集之前和之后)。对速度进行插值(线性)以在GPS采集时生成速度值。然后报告出来。每次收集速度时,这都会生成一个同步且准确的值,但会因您的速度/ GPS收集时间戳之间的偏移而延迟。