ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Среда
18 марта
1576640 Топик полностью
=AlexD= (Сегодня, 15:19, просмотров: 49) ответил IBAH на ХЕЛП! спасите от долбаного линукса!!!!! При приеме бинарных данных по сом порту (ttyUSB0) система меняет байт 0x0D на 0х0А!!!! Символ возврата каретки на символ перевода строки!!!!!
БОЛВАН отвечает. Не долбаный Linux, а его терминальное поведение, которое по умолчанию делает "невидимую" трансляцию символов, считая, что ты работаешь с терминалом, а не с бинарным устройством. 

Когда ты принимаешь данные через последовательный порт (`ttyUSB0`), драйвер терминала Linux по умолчанию преобразует **возврат каретки (`0x0D`, CR) в перевод строки (`0x0A`, LF)**. Это управляется флагом `ICRNL` в структуре `termios` .

Для бинарной передачи тебе нужно отключить эту "магию" и перевести порт в "сырой" (raw) режим.

### Вот твой план спасения (нужно сделать ДО начала приема данных):

Тебе нужно настроть структуру `struct termios`. Если ты открываешь порт через `open()`, тебе необходимо:

1. **Получить текущие настройки** с помощью `tcgetattr()`.

2. **Изменить флаги** (самое главное — сбросить `ICRNL`).

3. **Применить настройки** с помощью `tcsetattr()`.

### Ключевые флаги, которые нужно выключить:

Вот таблица "вражеских" флагов, которые ломают бинарные данные:

| Флаг | Описание | Почему мешает |

| :--- | :--- | :--- |

| **`ICRNL`** | Map CR to NL on input | **Твоя основная боль.** Именно он меняет 0x0D на 0x0A . |

| `INLCR` | Map NL to CR on input | Меняет 0x0A на 0x0D (тоже не нужно) . |

| `IGNCR` | Ignore CR | Просто игнорирует символ (тоже плохо) . |

| `IXON` / `IXOFF` | Software flow control (XON/XOFF) | Может "съедать" символы 0x11 и 0x13 . |

| `ICANON` | Canonical mode | Режим построчного ввода. В нем read() не вернет данные до нажатия enter. Для бинарных данных нужен неканонический режим . |

| `OPOST` | Output processing | Включает обработку вывода. Из-за него иногда 0x0A превращается в 0x0D 0x0A на отправке . |

### Пример кода (спасательный круг):

Вставь этот фрагмент в код сразу после открытия порта (`fd` - файловый дескриптор):

```c

#include <termios.h>

#include <unistd.h>

struct termios tty;

// Считываем текущие параметры

tcgetattr(fd, &tty);

// --- ОТКЛЮЧАЕМ ВРЕДНУЮ ОБРАБОТКУ ---

// Запрещаем преобразование CR->NL, NL->CR и игнорирование CR

tty.c_iflag &= ~(ICRNL | INLCR | IGNCR);

// Отключаем программное управление потоком (XON/XOFF)

tty.c_iflag &= ~(IXON | IXOFF | IXANY);

// Отключаем весь канонический режим (построчный ввод)

tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

// Отключаем обработку вывода (чтобы и на передачу ничего не преобразовывалось)

tty.c_oflag &= ~OPOST;

// --- НАСТРАИВАЕМ ТАЙМАУТЫ ДЛЯ RAW РЕЖИМА ---

tty.c_cc[VMIN] = 1; // read() вернется, когда будет хотя бы 1 байт

tty.c_cc[VTIME] = 1; // Таймаут между символами (0.1 сек)

// Применяем настройки немедленно

tcsetattr(fd, TCSANOW, &tty);

```

### Почему это произошло?

Linux унаследовал это поведение от старых UNIX-систем, где последовательные порты использовались для подключения "глупых" терминалов. Драйвер пытался быть "умным" и автоматически исправлять концы строк. Для современных устройств (Arduino, модемы, промышленные контроллеры) эта "забота" только мешает .

Если будешь открывать порт через **`fopen()`**, а не `open()`, то после `fopen()` нужно получить файловый дескриптор через `fileno()` и проделать те же манипуляции с `termios` .

**Вывод:** Linux здесь не "долбаный", он просто слишком "заботливый". Просто скажи ему: "Не надо мне тут ничего исправлять, отдай байты как есть".

Это моё личное предвзятое мнение. Любое совпадение с реальностью является случайным и непреднамеренным.