Add CAN1 100 ms heartbeat with verified firmware and updated protocol PDF

This commit is contained in:
shenlefengnai-rgb
2026-10-04 19:00:32 +08:00
parent 1e7b2e7f96
commit dba8aa5ea9
21 changed files with 1398 additions and 28 deletions
+2
View File
@@ -15,6 +15,8 @@
#define AMI_CAN_ID_BMS_EXTREMES_EXT 0x186140F3UL
/* AMI task requests are not ASSI commands; no SDC mapping is defined. */
#define AMI_CAN_ID_TASK_REQUEST 0x300U
#define AMI_CAN_ID_HEARTBEAT 0x301U
#define AMI_HEARTBEAT_PERIOD_MS 100U
#define AMI_CAN_DATA_TIMEOUT_MS 500U
#define AMI_ADC_TIMEOUT_MS 1500U
+42
View File
@@ -537,6 +537,47 @@ static void SendPendingTask(void)
}
}
static void SendHeartbeat(void)
{
static uint32_t last_tx_ms;
static uint16_t sequence;
uint32_t now = HAL_GetTick();
FDCAN_TxHeaderTypeDef header = {0};
uint8_t data[8];
if ((uint32_t)(now - last_tx_ms) < AMI_HEARTBEAT_PERIOD_MS)
{
return;
}
/* Skip missed periods instead of generating a catch-up burst. */
last_tx_ms = now;
data[0] = 1U; /* Protocol version. */
data[1] = 0U; /* Reserved. */
data[2] = (uint8_t)sequence;
data[3] = (uint8_t)(sequence >> 8);
data[4] = (uint8_t)now;
data[5] = (uint8_t)(now >> 8);
data[6] = (uint8_t)(now >> 16);
data[7] = (uint8_t)(now >> 24);
++sequence;
header.Identifier = AMI_CAN_ID_HEARTBEAT;
header.IdType = FDCAN_STANDARD_ID;
header.TxFrameType = FDCAN_DATA_FRAME;
header.DataLength = FDCAN_DLC_BYTES_8;
header.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
header.BitRateSwitch = FDCAN_BRS_OFF;
header.FDFormat = FDCAN_CLASSIC_CAN;
header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
/* CAN1 (500 kbit/s) only; reserve one FIFO slot for task requests.
A busy port skips this period; no software backlog or blocking retry. */
if (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) > 1U)
{
(void)HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &header, data);
}
}
static void UpdateTimeoutsAndLeds(void)
{
static uint32_t last_heartbeat_ms;
@@ -720,6 +761,7 @@ void AMI_App_Service(void)
uint32_t now = HAL_GetTick();
SendPendingTask();
SendHeartbeat();
UpdateTimeoutsAndLeds();
/* The HMI may reboot/reconnect after the MCU has already sent its state. */
if ((now - last_screen_sync_ms) >= AMI_SCREEN_RESYNC_MS)