IOT ENTERPRISE ©
ESP32 использование TJA1050 для работы с CAN шиной автомобиля
#include <driver/twai.h>
// Конфигурация пинов
#define CAN_TX_GPIO_NUM GPIO_NUM_5
#define CAN_RX_GPIO_NUM GPIO_NUM_4
#define CAN_SPEED TWAI_TIMING_CONFIG_500KBITS
// Статистика
uint32_t totalMessages = 0;
uint32_t messagesPerSecond = 0;
unsigned long lastStatsTime = 0;
void setup() {
Serial.begin(115200);
Serial.println("Advanced CAN Reader for ESP32");
Serial.println("==============================");
initializeCAN();
// Запуск задачи для мониторинга CAN в фоне
xTaskCreatePinnedToCore(canMonitorTask, "CAN Monitor", 4096, NULL, 1, NULL, 0);
}
void initializeCAN() {
twai_general_config_t g_config = {
.mode = TWAI_MODE_NORMAL,
.tx_io = CAN_TX_GPIO_NUM,
.rx_io = CAN_RX_GPIO_NUM,
.clkout_io = TWAI_IO_UNUSED,
.bus_off_io = TWAI_IO_UNUSED,
.tx_queue_len = 5,
.rx_queue_len = 20,
.alerts_enabled = TWAI_ALERT_ALL,
.clkout_divider = 0
};
twai_timing_config_t t_config = CAN_SPEED;
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
esp_err_t result = twai_driver_install(&g_config, &t_config, &f_config);
if (result != ESP_OK) {
Serial.printf("CAN driver install failed: 0x%X\n", result);
while(1);
}
result = twai_start();
if (result != ESP_OK) {
Serial.printf("CAN start failed: 0x%X\n", result);
while(1);
}
Serial.println("CAN controller initialized");
}
void loop() {
// Основной цикл может использоваться для других задач
delay(1000);
// Вывод статистики каждую секунду
printStatistics();
}
void canMonitorTask(void *pvParameters) {
twai_message_t message;
while (1) {
esp_err_t result = twai_receive(&message, portMAX_DELAY);
if (result == ESP_OK) {
processCANMessage(message);
totalMessages++;
messagesPerSecond++;
}
// Проверка статуса каждые 100 сообщений
if (totalMessages % 100 == 0) {
checkCANStatus();
}
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
void processCANMessage(twai_message_t &message) {
// Базовый вывод
Serial.printf("[%lu] ID:0x%03X %s%s DLC:%d Data:",
millis(), message.identifier,
message.extd ? "EXT" : "STD",
message.rtr ? " RTR" : "",
message.data_length_code);
// HEX данные
for (int i = 0; i < message.data_length_code; i++) {
Serial.printf("%02X", message.data[i]);
if (i < message.data_length_code - 1) Serial.print(" ");
}
// Дополнительная информация
Serial.printf(" | Timestamp:%lu", message.timestamp);
// Расшифровка некоторых стандартных ID
decodeCommonCANIDs(message);
Serial.println();
}
void decodeCommonCANIDs(twai_message_t &message) {
// Примеры расшифровки распространенных CAN ID
switch (message.identifier) {
case 0x7E8: // OBD Response
Serial.print(" | OBD Response");
break;
case 0x7DF: // OBD Request
Serial.print(" | OBD Request");
break;
case 0x100...0x1FF:
Serial.print(" | Engine Data");
break;
case 0x200...0x2FF:
Serial.print(" | Transmission");
break;
case 0x300...0x3FF:
Serial.print(" | Chassis");
break;
case 0x400...0x4FF:
Serial.print(" | Body");
break;
case 0x500...0x5FF:
Serial.print(" | Network");
break;
}
// Расшифровка данных для известных ID
if (message.identifier == 0x7E8 && message.data_length_code >= 3) {
Serial.printf(" | PID: 0x%02X", message.data[2]);
}
}
void printStatistics() {
unsigned long currentTime = millis();
if (currentTime - lastStatsTime >= 1000) {
Serial.printf("\n=== Statistics ===\n");
Serial.printf("Total messages: %lu\n", totalMessages);
Serial.printf("Messages/sec: %lu\n", messagesPerSecond);
Serial.printf("Uptime: %lu seconds\n", currentTime / 1000);
Serial.println("==================\n");
messagesPerSecond = 0;
lastStatsTime = currentTime;
}
}
void checkCANStatus() {
twai_status_info_t status;
twai_get_status_info(&status);
if (status.state != TWAI_STATE_RUNNING) {
Serial.printf("CAN state: %d\n", status.state);
}
if (status.tx_error_counter > 0 || status.rx_error_counter > 0) {
Serial.printf("Error counters - TX: %d, RX: %d\n",
status.tx_error_counter, status.rx_error_counter);
}
}