Пишу программу по передаче данных через com порт. Для отладки использую один комп, порты ttyS0 и ttyS1 соединены нуль модемным кабелем. Оба порта открываю одним и тем же способом. В целом, передача данных проходит без проблем, но возникает проблема всего с одним символом. При передаче символа с кодом 13 с ttyS0, второй порт ttyS1 упорно принимает символ с кодом 10. В обратном направлении возникает та же проблема. С другими символами проблем не возникает, если передаешь символ 10, то и принимаешь символ 10. Подскажите возможную причину проблемы здесь или вышлите на мыло witek@yandex.ruФункции открытия порта, передачи и приема символов порта прилагаю.
Открытие:
int TComPortFunctions::OpenPort()
{
struct termios options;
printf("Bus System communication device name: %s\n",devicename) ;
printf("Befor open: handle = %d\n",handle) ;
if(handle != -1) return -1; // Порт уже открыт нашей программой
/* open the port */
handle = open(devicename, O_RDWR | O_NOCTTY| O_NDELAY);
printf("After open: handle = %d\n",handle) ;
if(handle < 0) return -2; // Какая-то другая проблема
fcntl(handle, F_SETFL, 0);/* get the current options */
tcgetattr(handle, &options);
/* Устанавливаем скорость приема и предачи */
cfsetispeed(&options, B9600); // Установили скорость приема сообщений
cfsetospeed(&options, B9600); // Установили скорость отправки сообщений
/* set raw input, 1 second timeout */
options.c_cflag |= (CLOCAL | CREAD);
//No parity (8N1)
options.c_cflag &=~PARENB;
options.c_cflag &=~CSTOPB;
options.c_cflag &=~CSIZE;
options.c_cflag |=CS8;
//Установка аппаратного контроля передачи данныхoptions.c_cflag |=CRTSCTS;
options.c_iflag &=~(IXON|IXOFF|IXANY);
// Программное управление передачей данных
// options.c_cflag &=~CRTSCTS;
// options.c_iflag |=(IXON|IXOFF|IXANY);//Устанавливаем RAW INPUT
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_cc[VMIN] = 0; // Минимальное количество символов для чтения
options.c_cc[VTIME] = timeout; //Время ожидания
/* set the options */
tcsetattr(handle, TCSANOW, &options);
ioctl(handle,TCFLSH,2); // Сбарываем очереди ввода вывода
return 0;
}Функция передачи символов
//---------------------------------------------------------------------------
long TComPortFunctions::Write(unsigned char *answer, long len)
{
if (handle==-1) return -1;
if (write(handle, answer, len)!=len) return -2;
printf("Write len: %d\n",len);
return 0;
}
Функция чтения символовvoid TComPortFunctions::ReadToScreen()
{unsigned char block_from;
block_len=1;while (block_len!=0)
{
block_len=read(handle, &block_from, block_len);
if (block_len>0) printf("Resutlt: %d\n",block_from);}
}
man termios - какие есть флаги
man stty - какие стоят на порту по умолчанию.Проблема в установке/сбросе флагов. Смотреть какие флаги установлены, какие нет.
OCRNL к примеру :)
Снятие флага
[SRC c++]options.c_oflag &= ~OPOST;[/SRC]
убирает возможность обработанного вывода, т.е. никаких замен не производится. На всякий случай устанавливал и снимал флажки INLCR,ONLCR, OCRNL - как и положено никаких замен не происходило. Мой символ 13 в любом случае меняется на 10.
>Снятие флага
>[SRC c++]options.c_oflag &= ~OPOST;[/SRC]
>убирает возможность обработанного вывода, т.е. никаких замен не производится. На всякий случай
>устанавливал и снимал флажки INLCR,ONLCR, OCRNL - как и положено никаких
>замен не происходило. Мой символ 13 в любом случае меняется на
>10.угу, видимо на входе транслируется, может быть:
CR
Special character on input, which is recognized if the ICANON flag is set; it is the carriage-return character. When ICANON and ICRNL are set and IGNCR is not set, this character shall be translated into an NL, and shall have the same effect as an NL character.В любом случае дело во флагах.
Есть такая практика (не факт что верная) - в начале работы с портом считываются параметры порта и запоминаются, затем структура обнуляется и выставляются только нужные флаги. по окончанию работы с портом или по вылету из программы восстанавливаются те значения что были сохранены.
Разобрался. Проблема возникала из-за поднятого флага icrnl. После его снятия передача символа13 началась без проблем.
Почему-то из моей программы флаг не снимался (запускаю под root)
options.c_cflag &=~ICRNL;Если знаете почему это может происходить, скажите.
Флаг снимал из терминалки stty -F /dev/ttyS0 -icrnl – помогло.