Обмен данными по com порту

Рейтинг: 0Ответов: 1Опубликовано: 12.02.2023

В учебных целях хочу передавать и считывать данные на com-порт.

Есть фискальный регистратор, который принимает пакетные сообщения по ком порту. В официальной документации касательно передачи данных описано не много:

Тип протокола - Master (ПК) / Slave (фискальный регистратор). Фискальный регистратор выполняет команды, переданные ему от ПК, и возвращает сообщение, зависящие от результата выполнения. Фискальный регистратор не может инициировать сеанс связи с ПК. Сообщения в протоколе - это пакеты или одиночные байты. Фискальный регистратор поддерживает связь по интерфейсу RS 232 со скоростью 1200, 2400, 4800, 9600, 19200, 38400, 57600 и 115200 bps, 8N1.

В поисках ответов на свои вопросы, я понял что это протокол modbus.Путем декомпиляции софта производителя написанного на c# прояснилось много деталей. Свою реализацию пишу на с++, поэтому сделал функцию формирования массива байт, который содержит в себе команду для регистратора, пытаюсь его отправить на com-порт.

Вот мой код:

void init_tty(int fd)
{
    struct termios ter;
    tcgetattr(fd, &ter);
    ter.c_cflag &= ~PARENB; 
    ter.c_cflag &= ~CSIZE;
    ter.c_cflag |= CS8;
    ter.c_iflag &= ~(IXON | IXOFF | IXANY);
    ter.c_oflag &= ~OPOST;
    ter.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    ter.c_cflag     |=  CREAD | CLOCAL;     
    ter.c_cflag     &=  ~CRTSCTS;
    cfsetispeed(&ter, B115200);
    cfsetospeed(&ter, B115200);
    tcsetattr(fd, TCSANOW, &ter);

}
int main() {
int fd = open("/dev/ttyS0", O_RDWR);
init_tty(fd);
int len;
ushort *arr = CommandFormation(122,"N,",len);
int nw;
    nw = write(fd, arr, len);
    if ( nw <= 0)
    {
        std::cout << "Error: " << strerror(errno) << " from write" << std::endl;
        return 0;
    }
    cout << "Отправлено байт " << nw << endl;

Порт открывается корректно, функция write() возвращает именно столько, сколько я и отправлял. Однако устройство не выполняет команду.

Некорректность пакетного сообщения вероятнее всего исключается, так как метод в коде производителя возвращает точно такой же массив байт, как и моя реализация. Что я делаю не правильно, возможно я не корректно настраиваю структуру termios?

Ответы

▲ 0Принят

Проблема была решена просто, благодаря подсказке @mbo. Действительно, по скольку я работаю в Linux мне было немного проще реализовать "перехват" того что посылает ПО производителя. В параметрах порта я указал свой псевдо-терминал и отправил на него команду. Таким образом, получив пакет данных от ПО производителя, я смог разобраться почему мой код не работал. Фискальный регистратор не выполняет команды если ее порядковый номер повторяется с предыдущей.