3 сент. 2025

ESP32 использование TJA1050 для работы с CAN шиной автомобиля

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);
  }
}
Craftum Сайт создан на Craftum