feat: add ASSI lamp control and CAN protocol docs

This commit is contained in:
shenlefengnai-rgb
2026-09-18 21:42:28 +08:00
parent 04da25e2d1
commit be4f167b83
6 changed files with 236 additions and 62 deletions
+90 -23
View File
@@ -66,12 +66,20 @@ typedef struct
#define CAN_HEARTBEAT_PERIOD_MS 1000U
#define PWM_TIMEOUT_MS 1000U
#define CAN_HEARTBEAT_STD_ID 0x100U
#define CAN_GPIO_REPORT_STD_ID 0x330U
#define CAN_ADC_REPORT_STD_ID 0x102U
#define CAN_PWM_REPORT_STD_ID 0x103U
#define CAN_DAC_CMD_STD_ID 0x321U
#define CAN_DAC_ACK_STD_ID 0x322U
#define CAN_HEARTBEAT_STD_ID 0x6A0U
#define CAN_ADC_REPORT_STD_ID 0x6A1U
#define CAN_PWM_REPORT_STD_ID 0x6A2U
#define CAN_DAC_CMD_STD_ID 0x6A3U
#define CAN_DAC_ACK_STD_ID 0x6A4U
#define CAN_ASSI_LAMP_CMD_STD_ID 0x6A5U
#define CAN_GPIO_REPORT_STD_ID 0x6A6U
#define ASSI_LAMP_FLASH_HALF_PERIOD_MS 250U
#define ASSI_STATE_OFF 0U
#define ASSI_STATE_READY 1U
#define ASSI_STATE_DRIVING 2U
#define ASSI_STATE_EMERGENCY 3U
#define ASSI_STATE_FINISHED 4U
/* USER CODE END PD */
@@ -110,7 +118,8 @@ static uint32_t adc_filter_sum;
static uint8_t adc_filter_count;
static uint8_t adc_filter_index;
static char uart_line[UART_LINE_SIZE];
static uint8_t uart_line_len;
static uint8_t uart_line_len;
static uint8_t assi_lamp_state;
/* USER CODE END PV */
@@ -133,8 +142,10 @@ static void PollCanBus(CAN_HandleTypeDef *hcan, const char *name);
static void PollCaptureChannels(void);
static void PollGpioChanges(void);
static void SendPeriodicReport(void);
static void ServiceHeartbeat(void);
static void SendCanHeartbeat(void);
static void ServiceHeartbeat(void);
static void ServiceAssiLamp(void);
static void SendCanHeartbeat(void);
static void HandleAssiLampSetRequest(const char *source, uint8_t state);
static void HandleTextCommand(const char *source, const char *line);
static void HandleDacSetRequest(const char *source, uint8_t dac_id, uint16_t millivolts);
static void UartWrite(const char *text);
@@ -221,9 +232,10 @@ int main(void)
/* USER CODE BEGIN 3 */
PollUart();
PollCanBus(&hcan1, "CAN1");
PollCanBus(&hcan2, "CAN2");
PollCaptureChannels();
PollCanBus(&hcan1, "CAN1");
PollCanBus(&hcan2, "CAN2");
ServiceAssiLamp();
PollCaptureChannels();
PollGpioChanges();
SendPeriodicReport();
ServiceHeartbeat();
@@ -666,7 +678,7 @@ static void MX_GPIO_Init(void)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11, GPIO_PIN_RESET);
/*Configure GPIO pins : PD8 PD9 PD10 PD11
PD12 PD13 PD14 PD0
@@ -687,8 +699,8 @@ static void MX_GPIO_Init(void)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PE0 PE1 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
/*Configure GPIO pins : PE0 PE1 PE9 PE10 PE11 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
@@ -753,14 +765,16 @@ static void AppInit(void)
adc_filter_sum = 0U;
adc_filter_count = 0U;
adc_filter_index = 0U;
uart_line_len = 0U;
uart_line_len = 0U;
assi_lamp_state = ASSI_STATE_OFF;
(void)DacSetMillivolts(1U, 0U);
(void)DacSetMillivolts(2U, 0U);
UartWrite("\r\nA11 F407 monitor ready\r\n");
UartWrite("UART: DAC1 1.234 or DAC2 2500\r\n");
UartWrite("CAN cmd 0x321: [dac_id][mV_L][mV_H] or ASCII text\r\n");
UartWrite("CAN cmd 0x6A3: [dac_id][mV_L][mV_H] or ASCII text\r\n");
UartWrite("CAN cmd 0x6A5: [ASSI state 0=OFF,1=READY,2=DRIVING,3=EMERGENCY,4=FINISHED]\r\n");
BroadcastGpioReport(0U, gpio_last_state);
}
@@ -810,7 +824,7 @@ static void PollCanBus(CAN_HandleTypeDef *hcan, const char *name)
continue;
}
if (rx_header.StdId == CAN_DAC_CMD_STD_ID)
if (rx_header.StdId == CAN_DAC_CMD_STD_ID)
{
if ((rx_header.DLC >= 3U) && (rx_data[0] >= 1U) && (rx_data[0] <= 2U))
{
@@ -825,8 +839,15 @@ static void PollCanBus(CAN_HandleTypeDef *hcan, const char *name)
memcpy(line, rx_data, length);
line[length] = '\0';
HandleTextCommand(name, line);
}
}
}
}
else if (rx_header.StdId == CAN_ASSI_LAMP_CMD_STD_ID)
{
if ((rx_header.DLC >= 1U) && (rx_data[0] <= ASSI_STATE_FINISHED))
{
HandleAssiLampSetRequest(name, rx_data[0]);
}
}
}
}
@@ -918,7 +939,7 @@ static void SendPeriodicReport(void)
}
}
static void ServiceHeartbeat(void)
static void ServiceHeartbeat(void)
{
uint32_t now = HAL_GetTick();
@@ -927,7 +948,53 @@ static void ServiceHeartbeat(void)
last_heartbeat_ms = now;
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_0);
}
}
}
static void ServiceAssiLamp(void)
{
GPIO_PinState red = GPIO_PIN_RESET;
GPIO_PinState green = GPIO_PIN_RESET;
GPIO_PinState blue = GPIO_PIN_RESET;
bool flash_on = ((HAL_GetTick() / ASSI_LAMP_FLASH_HALF_PERIOD_MS) & 1U) == 0U;
switch (assi_lamp_state)
{
case ASSI_STATE_READY:
red = GPIO_PIN_SET;
green = GPIO_PIN_SET;
break;
case ASSI_STATE_DRIVING:
red = flash_on ? GPIO_PIN_SET : GPIO_PIN_RESET;
green = flash_on ? GPIO_PIN_SET : GPIO_PIN_RESET;
break;
case ASSI_STATE_EMERGENCY:
blue = flash_on ? GPIO_PIN_SET : GPIO_PIN_RESET;
break;
case ASSI_STATE_FINISHED:
blue = GPIO_PIN_SET;
break;
case ASSI_STATE_OFF:
default:
break;
}
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, red);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_10, green);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_11, blue);
}
static void HandleAssiLampSetRequest(const char *source, uint8_t state)
{
char reply[64];
assi_lamp_state = state;
snprintf(reply, sizeof(reply), "OK %s ASSI state=%u\r\n", source, (unsigned int)state);
UartWrite(reply);
}
static void SendCanHeartbeat(void)
{
@@ -945,7 +1012,7 @@ static void SendCanHeartbeat(void)
can_heartbeat_sequence++;
gpio_state = ReadGpioInputState();
/* CAN ID 0x100, sent independently on CAN1 and CAN2:
/* CAN ID 0x6A0, sent independently on CAN1 and CAN2:
* [0] 0xA1 board identifier; [1] firmware protocol version 1;
* [2..3] sequence counter, little-endian; [4..7] uptime in ms, little-endian.
*/