Add CAN inputs for drivetrain display values with DBC and bench evidence

This commit is contained in:
shenlefengnai-rgb
2026-10-03 18:53:17 +08:00
parent ceb88a90a5
commit dade0e5d3a
51 changed files with 7084 additions and 51 deletions
+2 -2
View File
@@ -50,7 +50,7 @@ FDCAN1.IPParameters=AutoRetransmission,CalculateTimeQuantumNominal,CalculateTime
FDCAN1.NominalPrescaler=8
FDCAN1.NominalTimeSeg1=13
FDCAN1.NominalTimeSeg2=2
FDCAN1.StdFiltersNbr=3
FDCAN1.StdFiltersNbr=4
FDCAN1.ExtFiltersNbr=1
FDCAN2.AutoRetransmission=ENABLE
FDCAN2.CalculateBaudRateNominal=250000
@@ -63,7 +63,7 @@ FDCAN2.IPParameters=AutoRetransmission,CalculateTimeQuantumNominal,CalculateTime
FDCAN2.NominalPrescaler=16
FDCAN2.NominalTimeSeg1=13
FDCAN2.NominalTimeSeg2=2
FDCAN2.StdFiltersNbr=3
FDCAN2.StdFiltersNbr=4
FDCAN2.ExtFiltersNbr=1
File.Version=6
GPIO.groupedBy=Group By Peripherals
+3 -1
View File
@@ -1,7 +1,8 @@
#ifndef AMI_PROTOCOL_H
#define AMI_PROTOCOL_H
/* Both CAN ports use the same 500 kbit/s protocol and the same IDs. */
/* CAN1 is 500 kbit/s; CAN2 is 250 kbit/s. Both share IDs and parsing. */
#define AMI_CAN_ID_DRIVETRAIN_DISPLAY 0x182U
#define AMI_CAN_ID_SDC_HEARTBEAT 0x6A0U
#define AMI_CAN_ID_SDC_ADC 0x6A1U
#define AMI_CAN_ID_SDC_FREQUENCY 0x6A2U
@@ -17,6 +18,7 @@
#define AMI_CAN_DATA_TIMEOUT_MS 500U
#define AMI_ADC_TIMEOUT_MS 1500U
#define AMI_BMS_TIMEOUT_MS 2000U
#define AMI_DRIVETRAIN_TIMEOUT_MS 2000U
#define AMI_SCREEN_BOOT_DELAY_MS 800U
#define AMI_SCREEN_RESYNC_MS 5000U
+39
View File
@@ -41,6 +41,7 @@ static volatile uint32_t debug_last_rx_ms;
static volatile uint32_t adc_last_rx_ms;
static volatile uint32_t bms_status_last_rx_ms;
static volatile uint32_t bms_temperature_last_rx_ms;
static volatile uint32_t drivetrain_last_rx_ms;
/* Preserve the exact source units even where the HMI has integer controls. */
static volatile uint16_t sdc_adc_mv;
static volatile uint16_t sdc_frequency_hz[4];
@@ -88,6 +89,12 @@ static int32_t RoundTenths(int32_t value)
return (value >= 0) ? ((value + 5) / 10) : ((value - 5) / 10);
}
static int32_t ReadLeS16(const uint8_t *data)
{
uint32_t raw = ReadLeU16(data);
return (raw & 0x8000U) ? ((int32_t)raw - 65536) : (int32_t)raw;
}
static size_t AppendUnsigned(char *dst, uint32_t value)
{
char reversed[10];
@@ -245,6 +252,27 @@ static bool DecodeCan(uint32_t identifier, uint32_t id_type,
uint32_t now = HAL_GetTick();
if (id_type == FDCAN_STANDARD_ID)
{
if (identifier == AMI_CAN_ID_DRIVETRAIN_DISPLAY)
{
/* Version 1 display input only; no motor actuation is performed. */
if ((length != 8U) || (data[7] != 1U) || ((data[6] & 0xF8U) != 0U))
{
return false;
}
int32_t torque = ReadLeS16(data);
if ((data[6] & 1U) && (torque >= -1000) && (torque <= 1000))
{
SetDashValue(2U, torque);
}
else { SetDashValid(2U, false); }
if (data[6] & 2U) { SetDashValue(4U, RoundTenths(ReadLeS16(&data[2]))); }
else { SetDashValid(4U, false); }
if (data[6] & 4U) { SetDashValue(5U, RoundTenths(ReadLeS16(&data[4]))); }
else { SetDashValid(5U, false); }
drivetrain_last_rx_ms = now;
dash_last_rx_ms = now;
return true;
}
if ((identifier == AMI_CAN_ID_SDC_ADC) && (length == 2U))
{
sdc_adc_mv = (uint16_t)ReadLeU16(data);
@@ -350,6 +378,10 @@ static void ConfigureCanPort(FDCAN_HandleTypeDef *hfdcan)
filter.FilterID1 = AMI_CAN_ID_BMS_TEMPERATURE;
if (HAL_FDCAN_ConfigFilter(hfdcan, &filter) != HAL_OK) { Error_Handler(); }
filter.FilterIndex = 3U;
filter.FilterID1 = AMI_CAN_ID_DRIVETRAIN_DISPLAY;
if (HAL_FDCAN_ConfigFilter(hfdcan, &filter) != HAL_OK) { Error_Handler(); }
filter.IdType = FDCAN_EXTENDED_ID;
filter.FilterIndex = 0U;
filter.FilterType = FDCAN_FILTER_DUAL;
@@ -489,6 +521,13 @@ static void UpdateTimeoutsAndLeds(void)
{
SetDashValid(6U, false);
}
if ((drivetrain_last_rx_ms == 0U) ||
((now - drivetrain_last_rx_ms) > AMI_DRIVETRAIN_TIMEOUT_MS))
{
SetDashValid(2U, false);
SetDashValid(4U, false);
SetDashValid(5U, false);
}
__enable_irq();
if (debug_timeout && !debug_timeout_applied)
+2 -2
View File
@@ -53,7 +53,7 @@ void MX_FDCAN1_Init(void)
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 13;
hfdcan1.Init.DataTimeSeg2 = 2;
hfdcan1.Init.StdFiltersNbr = 3;
hfdcan1.Init.StdFiltersNbr = 4;
hfdcan1.Init.ExtFiltersNbr = 1;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
@@ -91,7 +91,7 @@ void MX_FDCAN2_Init(void)
hfdcan2.Init.DataSyncJumpWidth = 1;
hfdcan2.Init.DataTimeSeg1 = 13;
hfdcan2.Init.DataTimeSeg2 = 2;
hfdcan2.Init.StdFiltersNbr = 3;
hfdcan2.Init.StdFiltersNbr = 4;
hfdcan2.Init.ExtFiltersNbr = 1;
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
+3 -2
View File
@@ -21,7 +21,8 @@ CAN1 为 500 kbit/s、CAN2 为 250 kbit/s。FDCAN 时钟为 64 MHz,两路 Cloc
## 数据路径
- FDCAN1、FDCAN2 使用相同的三条标准过滤器和一条扩展过滤器,接收 SDC 0x6A0..0x6A6 与 BMS 0x140 / 0x156 / 0x186040F3 / 0x186140F3。
- FDCAN1、FDCAN2 使用相同的四条标准过滤器和一条扩展过滤器,接收自定义显示 0x182、SDC 0x6A0..0x6A6 与 BMS 0x140 / 0x156 / 0x186040F3 / 0x186140F3。
- 标准 0x182 / DLC 8:小端 int16 扭矩千分、0.1℃ 电机温度、0.1℃ MCU 温度;有效标志及版本校验见 [DBC 说明](../docs/AMI_CAN_DBC说明.md)。设置 dash.mct / djwd / mcuwd,独立超时 2000 ms。
- SDC ADC 为低压电池电压;BMS 总压、偏置电流和最高有效实际温度按源协议解码。旧 0x180 / 0x181 / 0x280 不再接收。
- 主循环通过 USART2 TX DMA 一次发送一条完整 TJC 指令,末尾为三个真实字节 `FF FF FF`。
- 仅变化后的数值排队,字段轮转和 DMA 合并最新值,避免刷新饥饿;白色为有效数值,灰色为未知/失效,ADC 和 BMS 各自计时。
@@ -57,4 +58,4 @@ CubeMX 配置源为 `AMI_Controller.ioc`。重新生成时保留 USER CODE 区
4. 下载 `AMI.HMI` 后逐条验证仪表数值、16 路 debug 状态及 6 个任务按钮。
5. 2026-10-03 已完成 v2.1 CAN1 500K 与 CAN2 250K 分别到 MCU / USART2 / COM4 / 官方 HMI 调试器的联调;物理屏幕、真实节点、两路同时接入和 LED 极性尚未实测。见 [双 CAN 测试报告](../docs/CAN1_CAN2_v2.1测试报告.md)。
此前两路均为 500K 的 v2.0 历史证据仍保留。当前 v2.1 BIN 已烧录并完整回读比对通过,两路各六个任务确认和六个取消通过;CAN2 测试仅注入 BMS 数据,未将 SDC 改成 250K。
当前 v2.2 BIN 已烧录并完整回读比对;新 0x182 在 CAN2 250K 实测,见 [显示 CAN 测试报告](../docs/AMI自定义显示CAN测试报告.md)。v2.1 的双 CAN 分别联调和两路均为 500K 的 v2.0 历史证据及 BIN 保留;SDC 仍为 500K。