Dev #1

Merged
Mikhail merged 2 commits from Dev into main 2026-07-08 16:48:58 -04:00
2 changed files with 149 additions and 0 deletions
Showing only changes of commit 6c49d70161 - Show all commits
+23
View File
@@ -0,0 +1,23 @@
#ifndef __DS_Accord_8_F-CAN_H
#define __DS_Accord_8_F-CAN_H
#include "main.h"
// Структура описания CAN-пакета для диспетчера задач (Scheduler)
typedef struct {
uint16_t id; // CAN ID пакета
uint8_t dlc; // Длина кадра (DLC)
uint32_t period; // Период отправки в миллисекундах (мс)
uint32_t last_time; // Таймер последнего запуска (GetTick)
uint8_t alive_cnt; // Текущий шаг Alive Counter (0..3)
uint32_t start_phase; // Сдвиг запуска в миллисекундах
uint8_t data[8]; // ПОЛЕЗНАЯ НАГРУЗКА:
} CanTaskTypeDef;
/* Прототипы функций для вызова в основном проекте */
void run_honda_simulation(void);
uint8_t calc_honda_halfbyte_checksum(uint16_t id, uint8_t *data, uint8_t dlc, uint8_t alive_val);
extern volatile CanTaskTypeDef tasks[];
#endif /* __DS_Accord_8_F-CAN_H */
+126
View File
@@ -0,0 +1,126 @@
#include "DS_Accord_8_F-CAN.h"
// Внешний дескриптор CAN из main.c
extern CAN_HandleTypeDef hcan;
// Массив пакетов симуляции
volatile CanTaskTypeDef tasks[] = {
// ID, DLC, Period, Alive, Last_Time, Start_Phase, { Исходные данные DATA[8] }
{0x158, 8, 10, 0, 0, 0, {0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00}}, // ECU Скорость
{0x17C, 8, 10, 0, 0, 2, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, //
{0x1A4, 8, 20, 0, 0, 4, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, // ABS/VSA Тормоза
{0x324, 8, 20, 0, 0, 6, {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, // MICU Кузов
// {0x490, 8, 20, 0, 0, 6, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x491, 8, 20, 0, 0, 6, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x492, 8, 20, 0, 0, 8, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x493, 8, 20, 0, 0, 8, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x494, 8, 20, 0, 0, 9, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x495, 8, 20, 0, 0, 9, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x496, 8, 20, 0, 0, 1, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x497, 8, 20, 0, 0, 9, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x498, 8, 20, 0, 0, 3, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x499, 8, 20, 0, 0, 3, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x49A, 8, 20, 0, 0, 5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x49B, 8, 20, 0, 0, 5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x49C, 8, 20, 0, 0, 7, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x49D, 8, 20, 0, 0, 7, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x49E, 8, 20, 0, 0, 3, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
// {0x49F, 8, 20, 0, 0, 3, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}}
};
static const uint8_t num_tasks = sizeof(tasks) / sizeof(tasks[0]);
static const uint8_t alive_seq[] = {0, 1, 2, 3};
/**
* @brief Главный диспетчер циклической симуляции пакетов для Honda Accord 8
* @note Должен вызываться в основном бесконечном цикле while(1) в main.c
*/
void run_honda_simulation(void)
{
uint32_t current_tick = HAL_GetTick();
CAN_TxHeaderTypeDef tx_header;
uint8_t tx_data[8]; // Временный буфер для формирования финального кадра
uint32_t tx_mailbox;
for (uint8_t i = 0; i < num_tasks; i++)
{
// Настройка стартовой фазы при первом запуске
if (tasks[i].last_time == 0)
{
tasks[i].last_time = current_tick + tasks[i].start_phase;
}
// Проверка временной сетки
if (current_tick < tasks[i].last_time)
{
continue;
}
// Проверка свободного места в Mailbox пула
if (HAL_CAN_GetTxMailboxesFreeLevel(&hcan) == 0)
{
continue;
}
// Сдвигаем временную метку на период вперед
tasks[i].last_time += tasks[i].period;
// Копируем текущие данные из структуры во временный буфер отправки
for (uint8_t b = 0; b < 8; b++)
{
tx_data[b] = tasks[i].data[b];
}
// Конфигурируем заголовок CAN
tx_header.StdId = tasks[i].id;
tx_header.DLC = tasks[i].dlc;
tx_header.RTR = CAN_RTR_DATA;
tx_header.IDE = CAN_ID_STD;
tx_header.TransmitGlobalTime = DISABLE;
// Расчитываем динамическую контрольную сумму Honda на основе текущих данных
uint8_t current_alive = alive_seq[tasks[i].alive_cnt];
uint8_t checksum_nibble = calc_honda_halfbyte_checksum(tx_header.StdId, tx_data, tx_header.DLC, current_alive);
// Внедряем Alive счетчик и чексумму в самый последний байт пакета
tx_data[tx_header.DLC - 1] = (uint8_t)((current_alive << 4) | checksum_nibble);
// Отправляем пакет в пул Mailbox
if (HAL_CAN_AddTxMessage(&hcan, &tx_header, tx_data, &tx_mailbox) == HAL_OK)
{
tasks[i].alive_cnt = (tasks[i].alive_cnt + 1) % 4;
}
}
}
/**
* @brief Математически выверенный алгоритм подсчета Check Byte для Accord 8 (Сумма полубайт + DLC)
*/
uint8_t calc_honda_halfbyte_checksum(uint16_t id, uint8_t *data, uint8_t dlc, uint8_t alive_val)
{
uint32_t sum = 0;
// 1. Складываем полубайты 11-битного CAN ID
sum += (id >> 8) & 0x0F;
sum += (id >> 4) & 0x0F;
sum += id & 0x0F;
// 2. Складываем полубайты тела пакета (все, кроме последнего контрольного байта)
for (int i = 0; i < (dlc - 1); i++)
{
sum += (data[i] >> 4) & 0x0F;
sum += data[i] & 0x0F;
}
// 3. Добавляем длину пакета и шаг циклического счетчика
sum += dlc & 0x0F;
sum += alive_val & 0x0F;
// 4. Реализация правила дополнения до нуля (вычитание накопленного остатка из 16)
return (uint8_t)((0x10 - (sum & 0x0F)) & 0x0F);
}