Перейти к содержанию
Материалы раздела

MCP2515

Модуль управляет внешним CAN-контроллером MCP2515 через интерфейс SPI.

MCP2515 поддерживает CAN 2.0B и позволяет подключить шину CAN к ESP32 через внешний модуль.

mcp2515.init(spi_unit, cs_pin, [speed_khz])

Инициализация MCP2515 контроллера.

Аргументы:

  • spi_unit: номер SPI шины (2 для HSPI, 3 для VSPI)
  • cs_pin: номер GPIO пина для Chip Select
  • speed_khz (опционально): скорость SPI в кГц, по умолчанию 1000 (1 МГц)

Возвращает: true в случае успеха, иначе ошибку.

-- Инициализация на SPI2, CS на GPIO25
mcp2515.init(2, 25)

-- Инициализация на SPI3, CS на GPIO5, скорость SPI 2 МГц
mcp2515.init(3, 5, 2000)

mcp2515.send(id, data, [extended])

Отправка CAN сообщения.

Аргументы:

  • id: идентификатор CAN сообщения (11 бит для стандартного, 29 бит для расширенного)
  • data: строка с данными (до 8 байт)
  • extended (опционально): true для расширенного идентификатора (29 бит), по умолчанию false

Возвращает: true в случае успеха, или nil и сообщение об ошибке.

-- Отправка стандартного сообщения (11-bit ID)
mcp2515.send(0x123, "\x01\x02\x03\x04")

-- Отправка расширенного сообщения (29-bit ID)
mcp2515.send(0x18FEF100, "\xAA\xBB\xCC", true)

-- Отправка с использованием string.char
mcp2515.send(0x7DF, string.char(0x02, 0x01, 0x00))

mcp2515.recv([timeout_ms])

Приём CAN сообщения.

Аргументы:

  • timeout_ms (опционально): таймаут ожидания в миллисекундах, по умолчанию 1000

Возвращает:

  • При успехе: id, data, extended (идентификатор, данные как строка, флаг расширенного ID)
  • При таймауте: nil
-- Приём с таймаутом 1 секунда
local id, data, extended = mcp2515.recv(1000)
if id then
    print("ID: " .. string.format("0x%X", id))
    print("Data: " .. #data .. " bytes")
    print("Extended: " .. tostring(extended))

    -- Вывод байтов данных
    for i = 1, #data do
        print(string.format("  byte %d: 0x%02X", i, data:byte(i)))
    end
else
    print("Таймаут приёма")
end
-- Бесконечное ожидание
local id, data = mcp2515.recv(0xFFFFFFFF)

mcp2515.setBitrate(bitrate)

Установка скорости CAN шины.

Аргументы:

  • bitrate: скорость в бит/с или кбит/с

Поддерживаемые скорости: 10000, 25000, 50000, 100000, 125000, 250000, 500000, 1000000 бит/с

Возвращает: true в случае успеха, или nil и сообщение об ошибке.

-- Установка 250 кбит/с
mcp2515.setBitrate(250000)

-- Или используя константы
mcp2515.setBitrate(mcp2515.SPEED_250K)

-- Можно указывать в кбит/с
mcp2515.setBitrate(500)  -- будет интерпретировано как 500000

mcp2515.status()

Получение статуса контроллера.

Аргументы: нет

Возвращает: таблицу со следующими полями:

  • mode: текущий режим работы (“normal”, “sleep”, “loopback”, “listen”, “config”)
  • rx0_pending: true если есть сообщение в буфере RX0
  • rx1_pending: true если есть сообщение в буфере RX1
  • rx0_overflow: true если было переполнение буфера RX0
  • rx1_overflow: true если было переполнение буфера RX1
  • bus_off: true если контроллер в состоянии Bus Off
  • tx_passive: true если контроллер в состоянии TX Passive
  • rx_passive: true если контроллер в состоянии RX Passive
  • tx_errors: счётчик ошибок передачи
  • rx_errors: счётчик ошибок приёма
  • bitrate: текущая скорость CAN шины
local st = mcp2515.status()
print("Режим: " .. st.mode)
print("Скорость: " .. st.bitrate .. " бит/с")
print("Ошибки TX: " .. st.tx_errors)
print("Ошибки RX: " .. st.rx_errors)

if st.bus_off then
    print("ВНИМАНИЕ: Bus Off!")
end

mcp2515.reset()

Сброс контроллера MCP2515.

Аргументы: нет

Возвращает: true в случае успеха, или nil и сообщение об ошибке.

-- Сброс контроллера
mcp2515.reset()

mcp2515.setFilter(index, filter_id, mask, [extended])

Установка фильтра приёма сообщений.

MCP2515 имеет 6 фильтров (0-5):

  • Фильтры 0-2 работают с буфером RX0
  • Фильтры 3-5 работают с буфером RX1

Аргументы:

  • index: номер фильтра (0-5)
  • filter_id: идентификатор для фильтрации
  • mask: маска фильтра (биты установленные в 1 должны совпадать)
  • extended (опционально): true для расширенного идентификатора, по умолчанию false

Возвращает: true в случае успеха.

-- Принимать только сообщения с ID 0x123
mcp2515.setFilter(0, 0x123, 0x7FF)

-- Принимать сообщения с ID 0x100-0x1FF (маска игнорирует младшие 8 бит)
mcp2515.setFilter(0, 0x100, 0x700)

-- Фильтр для расширенного ID
mcp2515.setFilter(0, 0x18FEF100, 0x1FFFFFFF, true)

mcp2515.clearFilters()

Сброс всех фильтров. После вызова контроллер будет принимать все сообщения.

Аргументы: нет

Возвращает: true в случае успеха.

-- Принимать все сообщения
mcp2515.clearFilters()

Константы

Модуль предоставляет константы для удобной установки скорости:

КонстантаЗначение
mcp2515.SPEED_10K10000
mcp2515.SPEED_25K25000
mcp2515.SPEED_50K50000
mcp2515.SPEED_100K100000
mcp2515.SPEED_125K125000
mcp2515.SPEED_250K250000
mcp2515.SPEED_500K500000
mcp2515.SPEED_1M1000000

Примеры

Простой обмен данными

-- Инициализация
mcp2515.init(2, 25)
mcp2515.setBitrate(mcp2515.SPEED_250K)

-- Отправка
mcp2515.send(0x123, string.char(0x01, 0x02, 0x03))

-- Приём
while true do
    local id, data = mcp2515.recv(100)
    if id then
        print(string.format("Получено: ID=0x%X, %d байт", id, #data))
    end
end

Мониторинг CAN шины

mcp2515.init(2, 25)
mcp2515.setBitrate(mcp2515.SPEED_500K)
mcp2515.clearFilters()  -- принимать все сообщения

print("Мониторинг CAN шины...")
while true do
    local id, data, ext = mcp2515.recv(1000)
    if id then
        local hex = ""
        for i = 1, #data do
            hex = hex .. string.format("%02X ", data:byte(i))
        end
        print(string.format("%s 0x%08X [%d] %s",
            ext and "EXT" or "STD", id, #data, hex))
    end

    -- Проверка ошибок
    local st = mcp2515.status()
    if st.tx_errors > 0 or st.rx_errors > 0 then
        print(string.format("Ошибки: TX=%d RX=%d", st.tx_errors, st.rx_errors))
    end
end

Фильтрация сообщений OBD-II

mcp2515.init(2, 25)
mcp2515.setBitrate(mcp2515.SPEED_500K)

-- Принимать только ответы OBD-II (0x7E8-0x7EF)
mcp2515.setFilter(0, 0x7E8, 0x7F8)

-- Запрос RPM двигателя
mcp2515.send(0x7DF, string.char(0x02, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00))

local id, data = mcp2515.recv(1000)
if id and #data >= 4 then
    local rpm = (data:byte(3) * 256 + data:byte(4)) / 4
    print("RPM: " .. rpm)
end

Подключение модуля MCP2515

Типовая схема подключения модуля MCP2515 к ESP32:

MCP2515ESP32 (SPI2)ESP32 (SPI3)
VCC3.3V3.3V
GNDGNDGND
CSGPIO25 (любой)GPIO5 (любой)
SCKGPIO14GPIO18
MOSIGPIO13GPIO23
MISOGPIO12GPIO19
INTопциональноопционально

Начальные назначения SCK, MOSI и MISO зависят от модели устройства. Проверьте их функцией spi.pins() и при необходимости задайте другие выводы через spi.setpins() до вызова mcp2515.init().