Шина LIN
LIN — однопроводная шина автомобиля для недорогих узлов: один ведущий опрашивает по расписанию до пятнадцати ведомых на скорости до 20 кбит/с. Ниже — кадр и его поля, физический уровень с подтяжками и порогами, расписание, сон и диагностика по спецификации LIN 2.2A, подключение трансивера MCP2003B и реализация на UART микроконтроллера.
Обновлено Редакция GAW
LIN (Local Interconnect Network) — последовательная шина для мехатронных узлов автомобиля: датчиков, кнопок, исполнительных механизмов. Спецификация называет её дополнением к другим сетям автомобиля там, где не нужны пропускная способность и гибкость CAN: узел LIN — это обычный UART, недорогой трансивер и генератор без кварца, а вся шина — один провод и масса. Один ведущий узел опрашивает ведомых по расписанию, поэтому время доставки каждого сигнала известно заранее.
Все числа в статье — из спецификации LIN 2.2A (декабрь 2010 года), даташитов Microchip на трансивер MCP2003B и микроконтроллер ATtiny167 и справочного руководства RM0008 на STM32F1. Где расчёт наш, это сказано прямо.
Коротко
- Линии: одна сигнальная линия LIN и масса. В покое линия подтянута к напряжению аккумулятора: у ведущего — 1 кОм с диодом, у ведомых — 30 кОм с диодом.
- Узлы: один ведущий и ведомые, всего не больше 16; длина шины — до 40 м.
- Скорость: от 1 до 20 кбит/с. Ведомые обходятся без кварца: до синхронизации их частота может отличаться от номинальной до 14 %.
- Кадр: заголовок от ведущего (break не короче 13 бит, sync 0x55, PID) и ответ от одного узла: 1–8 байт данных и контрольная сумма.
- Уровни: доминант (логический 0) — ниже 40 % напряжения питания приёмника, рецессив (логическая 1) — выше 60 %.
- Стандарты: спецификации LIN 1.3–2.2A консорциума LIN, с 2016 года — международная серия ISO 17987; в США — рекомендации SAE J2602.
Как устроена сеть LIN
Сеть LIN (в спецификации — кластер) состоит из одной ведущей задачи и нескольких ведомых. Ведущая задача работает в ведущем узле, который содержит ещё и ведомую задачу; остальные узлы содержат только ведомую. Ведущая задача решает, какой кадр и когда идёт по шине: она передаёт заголовок с идентификатором. Ведомая задача, которая публикует этот идентификатор, отвечает данными. Отвечать может любой узел, включая сам ведущий, а принимают ответ все узлы, которым он нужен, — подписчики.
Отсюда главные свойства LIN:
- Нет арбитража. Передатчик ответа назначен заранее, и два узла не начнут передачу одновременно. Исключение — кадры по событию, где конфликт возможен и разрешается отдельным расписанием (о них ниже).
- Предсказуемое время. Ведущий проходит таблицу расписания по кругу, поэтому период обновления каждого сигнала известен на этапе проектирования.
- Дешёвые ведомые. Байт синхронизации в каждом заголовке позволяет ведомым работать от встроенного RC-генератора, а кадр передаётся обычным UART с одним стоп-битом.
Узлы описываются файлами: описание сети (LDF, LIN Description File) задаёт скорость, кадры, сигналы и расписания, а файл возможностей узла (NCF) — свойства готового ведомого. По LDF генерируется программа ведущего, поэтому ведомые от разных производителей собираются в одну сеть без переделки.
Версии LIN и стандарты
LIN 1.0 вышел в июле 1999 года, в ноябре 2000 года — LIN 1.2, в ноябре 2002-го — LIN 1.3, в котором поправили физический уровень ради совместимости узлов разных производителей. LIN 2.0 (2003) переработал спецификацию: добавил расширенную контрольную сумму с PID, стандартные диагностику и настройку узлов, файлы возможностей узлов и автоматическое определение скорости. LIN 2.1 вышел в 2006 году, LIN 2.2 собрал исправления, а LIN 2.2A (декабрь 2010) поправил сигнал пробуждения. Её выпустили уже после закрытия консорциума LIN, и она остаётся одной из самых распространённых версий.
С 2016 года LIN — международный стандарт серии ISO 17987 из восьми частей: от протокола и транспортного уровня до физического уровня 12/24 В, тестов на соответствие и LIN по линии питания. В редакции 2025 года ведущий и ведомый называются commander и responder. В США рекомендации по применению LIN выпускает SAE: серия J2602 впервые опубликована в 2004 году, обновлена в 2012-м и основана на LIN 2.0.
Ведущий LIN 2.x работает с ведомыми LIN 1.3 в одной сети: он просто не просит у них расширенную сумму, диагностику, определение скорости и сигнал ошибки. Обратное неверно: ведущий LIN 1.3 не знает расширенной суммы, и ведомые LIN 2.x с ним не работают.
Физический уровень
Физический уровень LIN основан на стандарте ISO 9141 (K-линия диагностики) с доработками для меньших помех. Линия LIN — один провод относительно массы автомобиля. Каждый узел подключён к ней выходом с открытым коллектором: передатчик может только прижать линию к массе или отпустить её. Отпущенную линию к напряжению аккумулятора тянут подтягивающие резисторы с последовательными диодами: 1 кОм у ведущего и 30 кОм внутри трансивера каждого ведомого. Диоды обязательны: при обрыве питания узла ток с шины иначе питал бы его электронику через подтяжку.
Отсюда два состояния линии. Рецессивное — линия отпущена, напряжение близко к питанию, это логическая 1 и состояние покоя. Доминантное — хотя бы один узел прижал линию, напряжение близко к массе, это логический 0. Если один узел передаёт 1, а другой 0, на линии будет 0 — доминант побеждает.
Пороги отсчитываются не от напряжения аккумулятора, а от питания приёмника VSUP: оно ниже на падение напряжения на диодах и проводах, а масса узлов в автомобиле может «гулять» до 11,5 % напряжения аккумулятора. Основные параметры физического уровня по таблицам 6.6, 6.7 и 6.11 спецификации:
| Параметр | Значение |
|---|---|
| Напряжение аккумулятора, при котором узел работает (VBAT) | 8–18 В |
| Питание трансивера (VSUP) | 7,0–18 В |
| Порог доминанта на входе приёмника | не выше 0,4 VSUP |
| Порог рецессива на входе приёмника | не ниже 0,6 VSUP |
| Гистерезис приёмника | не больше 0,175 VSUP |
| Ток ограничения передатчика в доминанте | 40–200 мА |
| Подтяжка ведущего, с последовательным диодом | 900–1100 Ом, номинал 1 кОм |
| Подтяжка ведомого, с последовательным диодом | 20–60 кОм, номинал 30 кОм |
| Длина шины | до 40 м |
| Ёмкость шины вместе с узлами | 1–10 нФ |
| Постоянная времени шины τ | 1–5 мкс |
| Ёмкость узла ведущего / ведомого | 220 пФ / 220 пФ, не больше 250 пФ |
| Погонная ёмкость провода | 100 пФ/м, не больше 150 пФ/м |
| Число узлов | не больше 16 |
Ограничения на длину и число узлов связаны через постоянную времени: , где , а — все подтяжки параллельно. Наш расчёт по типовым значениям для ведущего и 15 ведомых на 40 м: пФ, Ом, мкс — ровно верхняя граница. Поэтому спецификация и советует не больше 16 узлов: каждый следующий снижает сопротивление шины ещё примерно на 3 %.
Скорость фронтов спецификация не задаёт в вольтах на микросекунду: вместо этого она нормирует коэффициенты заполнения D1–D4 — долю рецессива в периоде из двух бит при чередовании 0 и 1, измеренную по заданным порогам приёмника при худших нагрузках шины (1 нФ и 1 кОм, 6,8 нФ и 660 Ом, 10 нФ и 500 Ом). Трансиверы формируют пологие фронты с ограничением скорости нарастания: так меньше помех. Для скоростей 10,4 кбит/с и ниже ради лучшей ЭМС действуют свои нормы — D3 и D4. Ещё два требования: узел не должен повреждаться при замыкании линии на массу или на плюс аккумулятора до 26,5 В, а при потере своей массы или питания — мешать остальной сети.
Скорость и синхронизация
Скорость шины LIN — от 1 до 20 кбит/с; конкретное значение (номинальную скорость) задаёт описание сети. В примере описания из спецификации — 19,2 кбит/с.
Генератор ведущего должен быть точным, а ведомым точность не обязательна: они подстраиваются по байту sync в начале каждого кадра. В байте 0x55 со старт- и стоп-битом уровни чередуются, и спады идут через 2, 4, 6 и 8 битовых интервалов от начала старт-бита. Измерив время между ними, ведомый вычисляет длительность бита ведущего и держит её до конца кадра. Допуски скорости по таблицам 6.1–6.3:
| Узел | Допуск |
|---|---|
| Ведущий, относительно номинальной скорости | меньше ±0,5 % |
| Ведомый без синхронизации, относительно номинальной | меньше ±1,5 % |
| Ведомый с синхронизацией — до неё, относительно номинальной | меньше ±14 % |
| Ведомый с синхронизацией — после неё, относительно ведущего | меньше ±2 % |
| Два ведомых между собой | меньше 2 % |
±14 % — точность, которой встроенный генератор достигает с заводской калибровкой. Её хватает, чтобы узнать break, а дальше синхронизация по байту 0x55 подгоняет скорость до ±2 %.
Каждый байт синхронизируется по спаду своего старт-бита. Спецификация допускает любую схему выборки, если первая выборка бита сделана не раньше 7/16, а последняя — не позже битового интервала, где — точность обнаружения спада старт-бита, не хуже 2/16 бита. Если выборок несколько, бит определяется большинством. Пример из спецификации — UART с 16 тактами на бит: спад старт-бита обнаруживается с точностью 1/16 бита, а выборки делаются с 7/16 до 9/16 бита.
Кадр LIN
Кадр состоит из заголовка, который передаёт ведущий, и ответа от узла-издателя:
- Break — не меньше 13 битовых интервалов доминанта и разделитель не короче одного бита. Break нарушает формат байта, и ведомый узнаёт начало кадра в любой момент, даже посреди приёма. Порог обнаружения у ведомого — 11 своих битовых интервалов, у ведомого с кварцем или керамическим резонатором — 9,5.
- Sync — байт 0x55 для подстройки скорости.
- PID — защищённый идентификатор: 6 бит ID и два бита чётности.
- Данные — от 1 до 8 байт. Число байтов для каждого ID заранее известно издателю и подписчикам; многобайтные величины передаются младшим байтом вперёд.
- Контрольная сумма — последний байт ответа.
Каждое поле, кроме break, — байт UART: старт-бит 0, восемь бит данных младшим вперёд, стоп-бит 1. Между байтами могут быть паузы, а между заголовком и ответом — пауза для ответа, обе неотрицательные.
Собрать кадр из своих ID и данных или проверить байты с логического анализатора можно прямо здесь. Тот же калькулятор с таблицами и пояснениями — на странице «Кадр LIN по байтам».
Исходные данные
6 бит: от 00 до 3F; 3C и 3D — диагностические кадры
4A 55 93 E5, 0x4A,0x55 или 4A5593E5
Результат
- Байты после break
- 55 50 4A 55 93 E5 96
- sync, PID, данные, контрольная сумма
- Защищённый идентификатор (PID)
- 0x50P1 = 0, P0 = 1, ID = 010000 — кадр сигналов (обычные данные)
- Контрольная сумма, расширенная
- 0x96по PID и данным
- Заголовок
- 1,771 мс34 бита; с допуском 40 % — до 2,479 мс
- Ответ
- 2,604 мс50 бит; до 3,646 мс
- Кадр
- 4,375 мсслот в расписании — не меньше 6,125 мс
Кадр на шине
Break — не меньше 13 бит в доминантном (низком) уровне, затем разделитель и байтовые поля: старт-бит, 8 бит данных младшим вперёд, стоп-бит.
| Байт | Сумма | Перенос |
|---|---|---|
| 0x50 | 0x50 | — |
| 0x4A | 0x9A | — |
| 0x55 | 0xEF | — |
| 0x93 | 0x83 | был: вычли 0xFF |
| 0xE5 | 0x69 | был: вычли 0xFF |
| инверсия | 0x96 | контрольная сумма |
Защищённый идентификатор
Идентификатор — 6 бит, значения от 0 до 63. Чтобы искажённый ID не приняли за другой, к нему добавлены два бита чётности:
занимает разряд 6, — разряд 7 байта PID. Каждый бит ID входит хотя бы в одно уравнение, поэтому ошибка в любом одном бите PID обнаруживается. Все 64 значения:
| ID | +0 | +1 | +2 | +3 | +4 | +5 | +6 | +7 |
|---|---|---|---|---|---|---|---|---|
| 00 | 80 | C1 | 42 | 03 | C4 | 85 | 06 | 47 |
| 08 | 08 | 49 | CA | 8B | 4C | 0D | 8E | CF |
| 10 | 50 | 11 | 92 | D3 | 14 | 55 | D6 | 97 |
| 18 | D8 | 99 | 1A | 5B | 9C | DD | 5E | 1F |
| 20 | 20 | 61 | E2 | A3 | 64 | 25 | A6 | E7 |
| 28 | A8 | E9 | 6A | 2B | EC | AD | 2E | 6F |
| 30 | F0 | B1 | 32 | 73 | B4 | F5 | 76 | 37 |
| 38 | 78 | 39 | BA | FB | 3C | 7D | FE | BF |
Строка — старшие разряды ID, столбец — прибавка к ним. Идентификаторы делятся на три группы:
| ID | Назначение |
|---|---|
| 0x00–0x3B (0–59) | кадры с сигналами |
| 0x3C (60) | запрос ведущего (master request): диагностика и настройка |
| 0x3D (61) | ответ ведомого (slave response): диагностика и настройка |
| 0x3E, 0x3F (62, 63) | зарезервированы, в сетях LIN 2.x не используются |
В LIN 1.x длина ответа кодировалась прямо в идентификаторе. Например, в регистре идентификатора контроллера LIN у ATtiny167 для режима LIN 1.3 разряды ID5 и ID4 задают 2 байта (00 и 01), 4 байта (10) или 8 байт (11). В LIN 2.x длина в ID не передаётся, её задаёт описание сети.
Контрольная сумма
Контрольная сумма — инвертированная восьмибитная сумма с переносом: байты складываются, и каждый раз, когда сумма достигает 256, из неё вычитают 255. Классическая сумма считается только по данным — так считали все кадры в версиях до LIN 1.3 включительно. Расширенная, введённая в LIN 2.0, начинает с PID, поэтому защищает и идентификатор. Какую сумму использовать, ведущий знает для каждого ID: классическую — с ведомыми LIN 1.x, расширенную — с LIN 2.x. Диагностические кадры 0x3C и 0x3D всегда используют классическую сумму.
Пример из спецификации, данные 4A 55 93 E5: 0x4A + 0x55 = 0x9F; + 0x93 = 0x132, после переноса 0x33; + 0xE5 = 0x118, после переноса 0x19; инверсия даёт 0xE6. Приёмник складывает тем же способом все байты вместе с контрольной суммой и должен получить 0xFF. Расширенная сумма для того же кадра с ID 0x10 (PID 0x50) — 0x96.
/* LIN checksum: the enhanced model starts with the PID, the classic one sums the data only. */
uint8_t lin_checksum(uint8_t pid, const uint8_t *data, uint8_t n, int enhanced)
{
uint16_t sum = enhanced ? pid : 0;
for (uint8_t i = 0; i < n; i++) {
sum += data[i];
if (sum > 0xFF)
sum -= 0xFF;
}
return (uint8_t)~sum;
}
Длина кадра и расписание
Номинальное время кадра — его биты без пауз: break с разделителем — 14 бит, sync и PID — по 10, каждый байт ответа — тоже 10:
где — число байт данных. Паузы между байтами разрешены, но всё вместе не должно удлинять заголовок и ответ больше чем на 40 %: . Узлы обязаны принимать кадр без пауз, а соблюдение максимума проверяют инструменты и тесты; приёмник принимает ответ до следующего break, даже если тот затянулся.
| Байт данных | Бит в кадре | 19 200 бит/с | 10 400 бит/с | 9 600 бит/с |
|---|---|---|---|---|
| 1 | 54 | 2,81 мсдо 3,94 мс | 5,19 мсдо 7,27 мс | 5,63 мсдо 7,88 мс |
| 2 | 64 | 3,33 мсдо 4,67 мс | 6,15 мсдо 8,62 мс | 6,67 мсдо 9,33 мс |
| 3 | 74 | 3,85 мсдо 5,4 мс | 7,12 мсдо 9,96 мс | 7,71 мсдо 10,8 мс |
| 4 | 84 | 4,38 мсдо 6,13 мс | 8,08 мсдо 11,3 мс | 8,75 мсдо 12,3 мс |
| 5 | 94 | 4,9 мсдо 6,85 мс | 9,04 мсдо 12,7 мс | 9,79 мсдо 13,7 мс |
| 6 | 104 | 5,42 мсдо 7,58 мс | 10 мсдо 14 мс | 10,8 мсдо 15,2 мс |
| 7 | 114 | 5,94 мсдо 8,31 мс | 11 мсдо 15,3 мс | 11,9 мсдо 16,6 мс |
| 8 | 124 | 6,46 мсдо 9,04 мс | 11,9 мсдо 16,7 мс | 12,9 мсдо 18,1 мс |
Время ведущий отмеряет базовыми интервалами — обычно 5 или 10 мс. Каждый кадр занимает в таблице расписания слот из целого числа таких интервалов, и слот должен вмещать максимальное время кадра вместе с задержкой начала заголовка от такта (джиттером):
Кадр с 8 байтами на 19 200 бит/с длится до 9,04 мс, поэтому в слот 10 мс он помещается, если джиттер ведущего меньше 0,96 мс (наш расчёт). Сменить расписание ведущий может только в начале слота. Новые значения сигналов ведомый должен успеть записать до приёма идентификатора своего кадра, а принятые получает сразу после проверки контрольной суммы.
Типы кадров
- Безусловный кадр (ID 0–59) — основной: заголовок передаётся в каждом своём слоте, издатель отвечает всегда.
- Кадр по событию (event triggered) — общий заголовок для нескольких ведомых, каждый отвечает, только если его сигналы изменились. Первый байт данных такого ответа — PID собственного безусловного кадра узла, чтобы ведущий знал, от кого пришли данные. Если ответили двое, ответы столкнутся. Тогда ведущий сам переключается на расписание разрешения конфликта и опрашивает узлы по отдельности. Пример из спецификации — кнопки замков четырёх дверей: нажимают их редко, и опрашивать каждую в каждом цикле расточительно.
- Спорадический кадр — несколько кадров ведущего делят один слот: передаётся тот, чьи сигналы изменились, а если не изменилось ничего, слот пустует.
- Диагностические кадры — запрос ведущего 0x3C и ответ ведомого 0x3D, всегда по 8 байт данных и с классической суммой. Заголовок 0x3D ведущий посылает безусловно, а отвечает на него ведомый, которому есть что ответить на предыдущий запрос.
Сигналы внутри кадров — скаляры от 1 до 16 бит или массивы от 1 до 8 байт, передаются младшим битом вперёд и могут пересекать границы байтов. Неиспользуемые биты кадра передаются единицами. Кроме того, каждый ведомый LIN 2.x публикует в одном из своих кадров однобитный сигнал response_error: он выставляется, если в ответе кадра, который узел передавал или принимал, была ошибка, и сбрасывается после успешной передачи. Так ведущий узнаёт о сбоях, которые видит только ведомый.
Сон и пробуждение
Ведущий усыпляет сеть командой: кадр запроса ведущего 0x3C с первым байтом данных 0x00 и остальными 0xFF. Его классическая контрольная сумма — 0x00 (наш расчёт). Ведомый засыпает и сам, если шина не меняла уровень от 4 до 10 с.
Разбудить сеть может любой узел: он переводит линию в доминант на время от 250 мкс до 5 мс. Остальные узлы должны распознать доминантный импульс длиннее 150 мкс с последующим подъёмом и быть готовы к работе через 100 мс. Если за 150–250 мс после сигнала ведущий так и не начал опрос, узел повторяет сигнал; после трёх неудачных попыток он ждёт не меньше 1,5 с перед четвёртой. Ведущий может будить сеть просто заголовком — break сам по себе работает как сигнал пробуждения, но ответа на первый заголовок ждать не стоит.
Диагностика и настройка узлов
Диагностические кадры несут транспортный уровень: блок из 8 байт начинается с адреса узла NAD и байта PCI, за ними идут номер службы SID и данные. Короткое сообщение помещается в один кадр, длинное передаётся первым кадром и продолжениями — всего до 4095 байт. Незаполненные байты передаются как 0xFF.
| NAD | Назначение |
|---|---|
| 0x00 | зарезервирован для команды сна |
| 0x01–0x7D (1–125) | адреса ведомых |
| 0x7E | функциональный адрес, только для диагностики |
| 0x7F | широковещательный адрес |
| 0x80–0xFF | свободное использование |
Службы с SID 0xB0–0xB7 настраивают узлы: присвоить NAD (0xB0), прочитать идентификацию узла (Read by Identifier, 0xB2, обязательная), сохранить настройку (0xB6), назначить PID кадрам узла (Assign frame identifier range, 0xB7, обязательная). Положительный ответ приходит с RSID = SID + 0x40. Так одинаковые готовые ведомые от разных производителей получают свои идентификаторы в конкретной сети.
Трансивер LIN: MCP2003B
Трансивер переводит логические уровни UART микроконтроллера в уровни шины и обратно. Пример — Microchip MCP2003B: совместим с LIN 1.3–2.2, SAE J2602 и ISO 17987, работает на скоростях до 20 кбит/с, питается от 5,5 до 30 В и защищён от сброса нагрузки до 60 В. Подтяжка шины к питанию 30 кОм (20–60 кОм) с диодом встроена и включается только в рабочем режиме.
- TXD и RXD. Низкий уровень на TXD — доминант на шине, высокий — рецессив. RXD повторяет состояние шины, поэтому микроконтроллер слышит и свои собственные байты. Выход RXD — с открытым стоком, и подтяжка к питанию логики обязательна: трансивер проверяет, что RXD в единице при рецессивной шине, и без подтяжки не перейдёт в рабочий режим.
- CS включает передатчик. Внутри — подтяжка к массе, поэтому пока микроконтроллер стартует, передатчик выключен и мусор на шину не уходит. Держать CS в единице постоянно производитель не советует.
- Защита от зависания. Если TXD или сама шина в доминанте дольше примерно 25 мс, передатчик отключается, чтобы неисправный узел не заблокировал сеть.
- VBB и VREN. Питание трансивера — от аккумулятора через диод защиты от переполюсовки. Выход VREN включает стабилизатор узла во всех режимах, кроме режима сна, поэтому узел может полностью обесточиваться и просыпаться от активности на шине или по входу WAKE.
- Шина. На выводе LBUS — конденсатор 220 пФ на массу. Ведущий узел добавляет подтяжку 1 кОм от VBAT через диод.
У предшественников MCP2003 и MCP2004 максимальное сопротивление встроенной подтяжки — 47 кОм вместо 60, а сам производитель советует для новых разработок MCP2003B или ATA663211.
LIN на микроконтроллере
Кадр LIN — это байты UART в формате 8N1, поэтому узел строится на любом UART. Отдельного внимания требуют только break и синхронизация у ведомого.
STM32: режим LIN в USART
USART в STM32F1 переходит в режим LIN битом LINEN регистра USART_CR2. В этом режиме бит SBK посылает break из 13 нулевых бит и единичный бит за ним, а приёмник обнаруживает break длиной 10 или 11 бит (бит LBDL) независимо от приёма данных и выставляет флаг LBD. В HAL это функции HAL_LIN_Init() и HAL_LIN_SendBreak(). Последняя только выставляет SBK и не ждёт конца break, поэтому перед передачей байтов ждём, пока аппаратура сбросит бит:
#include <string.h>
#include "stm32f1xx_hal.h"
/* Protected identifier: P0 = ID0^ID1^ID2^ID4, P1 = !(ID1^ID3^ID4^ID5). */
static uint8_t lin_pid(uint8_t id)
{
uint8_t b0 = id & 1, b1 = (id >> 1) & 1, b2 = (id >> 2) & 1;
uint8_t b3 = (id >> 3) & 1, b4 = (id >> 4) & 1, b5 = (id >> 5) & 1;
uint8_t p0 = b0 ^ b1 ^ b2 ^ b4;
uint8_t p1 = !(b1 ^ b3 ^ b4 ^ b5);
return (uint8_t)((id & 0x3F) | (p0 << 6) | (p1 << 7));
}
/* Master publishes a frame: break, sync, PID, data and checksum. */
void lin_master_send(UART_HandleTypeDef *huart, uint8_t id, const uint8_t *data, uint8_t n)
{
uint8_t buf[11];
uint8_t pid = lin_pid(id);
int enhanced = id != 0x3C && id != 0x3D;
buf[0] = 0x55;
buf[1] = pid;
memcpy(&buf[2], data, n);
buf[2 + n] = lin_checksum(pid, data, n, enhanced);
HAL_LIN_SendBreak(huart);
while (READ_BIT(huart->Instance->CR1, USART_CR1_SBK)) {
/* SBK is cleared by hardware during the stop bit of the break */
}
HAL_UART_Transmit(huart, buf, 3 + n, 10);
}
Функция lin_checksum() — из примера выше. USART настраивается вызовом HAL_LIN_Init(&huart1, UART_LINBREAKDETECTLENGTH_11B) на скорость шины, 8 бит без чётности. Чтобы запросить данные у ведомого, ведущий передаёт только break, 0x55 и PID, а затем принимает N + 1 байт ответа. Не забудьте, что через трансивер на RX вернутся и собственные байты заголовка.
AVR: аппаратный LIN в ATtiny167 и программный в остальных
У ATtiny87 и ATtiny167 есть контроллер LIN/UART, который выполняет LIN 2.1 и 1.3 аппаратно: формирует и принимает заголовок, считает контрольную сумму, следит за временем кадра и сообщает об ошибках флагами. Break он принимает длиной от 10,5 до 28 бит, а в роли ведомого подстраивает скорость по байту 0x55: допускает отклонение генератора до ±20 % и выравнивает скорость с точностью ±2 %.
У остальных AVR и у Arduino только обычный UART, который не умеет посылать break. Простой приём (наш расчёт): передать байт 0x00 на скорости . Старт-бит и восемь нулей — 9 бит доминанта на пониженной скорости — длятся ровно 13 номинальных битовых интервалов, а стоп-бит на той же скорости даёт разделитель около 1,44 бита. На 19 200 бит/с это скорость 13 292 бит/с; после байта UART возвращают на номинальную скорость и передают остальные байты заголовка. Ведомому на AVR без кварца нужно ещё подстроить делитель UART: измерить таймером спады байта 0x55 после break.
LIN и CAN
| LIN | CAN | |
|---|---|---|
| Линии | одна линия и масса | дифференциальная пара CAN_H и CAN_L |
| Доступ к шине | один ведущий, расписание | все узлы равноправны, побитовый арбитраж |
| Скорость | 1–20 кбит/с | до 1 Мбит/с у классического CAN |
| Данные в кадре | 1–8 байт | до 8 байт, у CAN FD — до 64 |
| Защита данных | контрольная сумма из 8 бит | CRC из 15 бит, подтверждение приёма |
| Генератор ведомого | RC без кварца, подстройка по sync | кварц или точный генератор |
| Узлов и длина | до 16, до 40 м | десятки узлов, длина зависит от скорости |
LIN не конкурирует с CAN, а дополняет его: спецификация отводит LIN нижний уровень иерархической сети автомобиля — там, где не нужны пропускная способность и гибкость CAN. Узлу LIN хватает UART, трансивера и встроенного генератора, тогда как узлу CAN нужны контроллер CAN и кварц.
Типичные ошибки и отладка
- Не та контрольная сумма. Узел LIN 2.x ждёт расширенную сумму, а программа считает классическую, или наоборот — для диагностических кадров 0x3C и 0x3D. Калькулятор кадра в режиме проверки покажет, с какой суммой совпал байт.
- ID вместо PID. В заголовке передают 6-битный ID без битов чётности, и ведомые не узнают свой кадр. Для ID 0x10 на шину должен уйти байт 0x50.
- Нет подтяжки ведущего. Без 1 кОм у ведущего шину тянут только 30 кОм ведомых: постоянная времени шины уходит далеко за 5 мкс, фронты подъёма затягиваются, и на высоких скоростях приёмники начинают ошибаться.
- Трансивер не включается. У MCP2003B нет подтяжки на RXD или CS в нуле: передатчик выключен, а микроконтроллер видит только тишину.
- Короткий break. UART без функции break передаёт 0x00 — это лишь 9 бит доминанта, меньше порога 11 бит у ведомого.
- Масса. Сигнал LIN отсчитывается от массы каждого узла, поэтому плохая масса сдвигает пороги приёмника. Проверяйте разницу масс узлов под нагрузкой.
- Логический анализатор. Подключайте его к выводам RXD и TXD трансивера, а не к шине на 12 В, и используйте декодер LIN (например, декодер sigrok в PulseView): он показывает break, PID с проверкой чётности, данные и контрольную сумму.
Частые вопросы
Что такое шина LIN и где её применяют?
LIN (Local Interconnect Network) — последовательная однопроводная шина для мехатронных узлов автомобиля: датчиков, кнопок, исполнительных механизмов. Один ведущий узел опрашивает ведомых по заранее составленному расписанию, скорость — от 1 до 20 кбит/с. Узлы строятся на обычном UART и дешёвом трансивере, а ведомым не нужен кварц: они подстраиваются под ведущего по байту синхронизации в каждом кадре. Спецификация называет LIN дополнением к другим сетям автомобиля для тех мест, где не нужны пропускная способность и гибкость CAN.
Чем LIN отличается от CAN?
LIN — один провод и масса, скорость до 20 кбит/с, один ведущий, который решает, кто и когда передаёт, поэтому арбитраж не нужен. CAN — дифференциальная пара, скорости до 1 Мбит/с у классического CAN, все узлы равноправны и делят шину побитовым арбитражем. LIN дешевле: узел — это UART, трансивер и RC-генератор без кварца. Поэтому LIN дополняет CAN там, где его скорость и гибкость не нужны, а не заменяет его.
Какая скорость у шины LIN?
Спецификация LIN 2.2A разрешает любую скорость от 1 до 20 кбит/с, конкретное значение задаётся в описании сети. В примере описания сети из спецификации — 19,2 кбит/с; для скоростей 10,4 кбит/с и ниже спецификация задаёт драйверу отдельные нормы скважности ради лучшей ЭМС. Кадр из 8 байт на 19 200 бит/с длится 6,46 мс номинально и до 9,04 мс с паузами между байтами.
Зачем у ведущего LIN резистор 1 кОм и диод?
Линия LIN в покое подтянута к напряжению аккумулятора: у каждого ведомого внутри трансивера — 30 кОм с диодом, у ведущего — внешние 1 кОм с диодом. Сильная подтяжка ведущего задаёт постоянную времени шины, то есть скорость подъёма фронта при ёмкости линии до 10 нФ. Диод обязателен: без него при обрыве питания узла ток с шины питал бы его электронику.
Как посчитать контрольную сумму LIN?
Сложите байты с переносом: каждый раз, когда сумма превышает 255, вычитайте 255. В конце инвертируйте результат. Для LIN 2.x (расширенная сумма) первым слагаемым идёт PID, для LIN 1.x и диагностических кадров 0x3C и 0x3D (классическая) — только данные. Данные 4A 55 93 E5 дают классическую сумму 0xE6, а с PID 0x50 — расширенную 0x96. Посчитать любую сумму можно в калькуляторе кадра LIN.
Как подключить микроконтроллер или Arduino к шине LIN?
Через трансивер LIN, например MCP2003B: вывод TX микроконтроллера — на TXD, RXD трансивера — на RX с подтягивающим резистором 4,7 кОм к питанию логики, свободный вывод — на CS, питание VBB — от аккумулятора через диод. Ведущему узлу нужна ещё подтяжка 1 кОм с диодом. Программно кадр формирует обычный UART: break, байт 0x55, PID, данные, контрольная сумма. В STM32 USART умеет посылать break из 13 бит сам, а на UART без такой функции break получают, передав 0x00 на пониженной скорости.
Источники
- LIN Consortium. LIN Specification Package, Revision 2.2A, 31 December 2010 — разд. 1.1.2 и 1.1.5 — свойства шины, ведущий и ведомые задачи; 1.1.7 — история версий и совместимость с LIN 1.3; 2.3.1 — структура кадра, break, sync, PID, данные, контрольная сумма; 2.3.2 — длина кадра; 2.3.3 — типы кадров; 2.4 — расписание и базовое время; 2.6 — сон и пробуждение; 2.7 — сигнал response_error; 2.8.3 и табл. 2.3–2.5; 3.2 и 4.2 — транспортный уровень, NAD и команды настройки; 6.3 — скорости и допуски, табл. 6.1–6.3; 6.4 — синхронизация и выборка битов, табл. 6.4; 6.5 — физический уровень, рис. 6.3–6.4, табл. 6.6–6.11
- CAN in Automation. LIN standards and specifications — история версий LIN, серия ISO 17987 (с 2016 года, обновление 2025 года с терминами commander и responder), рекомендации SAE J2602
- Microchip. MCP2003B LIN Transceiver, DS20005463C, 2016 — разд. 1.0 — назначение и нагрузка шины; 1.3 — режимы работы; 1.4, пример 1-1 — типовая схема узла; 1.5 — выводы: RXD с открытым стоком и контролем уровня, CS, WAKE, TXD, тайм-аут доминанта около 25 мс; 2.3 и 2.4 — пороги шины, RSLAVE 20/30/60 кОм, tSLOPE, коэффициенты заполнения
- Microchip. MCP2003/4/3A/4A LIN J2602 Transceiver, DS20002230G, 2016 — предшественник MCP2003B, не рекомендован для новых разработок; RSLAVE 20/30/47 кОм
- Microchip. ATtiny87/ATtiny167 Data Sheet, DS40002167A, 2020 — гл. 15 «LIN / UART»: аппаратный LIN 2.1 и 1.3, приём break длиной 10,5–28 бит, подстройка скорости по байту 0x55, флаги ошибок, длина ответа в идентификаторе LIN 1.3 (регистр LINIDR)
- STMicroelectronics. RM0008 Reference manual STM32F101xx–STM32F107xx, Rev 21, 2021 — разд. 27.3.8 — режим LIN в USART: бит LINEN, break из 13 нулевых бит по биту SBK, обнаружение break длиной 10 или 11 бит (бит LBDL), флаг LBD
- STMicroelectronics. STM32F1 HAL, драйвер stm32f1xx_hal_uart.c — HAL_LIN_Init с параметром длины обнаружения break, HAL_LIN_SendBreak устанавливает бит SBK и не ждёт окончания break
- sigrok project. sigrok-test: decoder/test/lin — расшифровки кадров LIN 2 декодером sigrok: ID 0x01 и 0x23, данные и расширенные контрольные суммы
Смотрите также
- Кадр LIN по байтамPID, классическая и расширенная контрольная сумма, биты и время кадра
- CANCAN_H и CAN_L, терминаторы, кадр, арбитраж, ошибки, тайминг, MCP2515
- UARTКадр 8N1, скорость и допуск, TX и RX, уровни, USB–UART, AVR и STM32
- Кадр UART по битамБиты кадра, чётность, время символа, разбор и расхождение скоростей
- ИнтерфейсыUART, RS-232, RS-485, I²C, SPI, CAN: уровни, схемы, выбор
- AVRATmega, ATtiny, AVR Dx/Ex: семейства, прошивка, инструменты