Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Работа с COM портом


Автор: theworldcreator 6.11.2007, 02:42
Вот программка, взятая сдесь же, с форума. Запустил для проверки, и не работает! Проверил вольтметром - некоторый ножки имею напряжение порядка 11 волт(причем как это ни странно вольтметор дает отрицательной напряжение как если бы я "-" с "+" перепутал, но "-" - это 5 ножка, вот распиновка http://www.radiomaster.ru/spravka/papa_mama/com.php)
Код

#include <stdio.h>
int main(int argc, char *argv[])
{
    FILE *com = fopen("/dev/ttyS0", "rw"); //открываешь порт
    fprintf(com, "%s", 0x00); //записываем строку в ..
    return 0;
}

Автор: Lohmatii 6.11.2007, 03:54
1. А под Рутом прогу запускаешь?
2. Порпробуй вместо "rw" O_RDWR
3. Лучше не надо fprintf для СОМа, во всех примерах что я видел был write.

С open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY) write у меня нормально пишет.

Автор: theworldcreator 6.11.2007, 14:35
Код

FILE *com = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
write(com, 0x00);

Так? Я что то не где не смог найти описание функции write.
В таком виде компилятор ругается на необъявленные константы.

Код

user@debian:~/Desktop/p$ gcc new.c -o new.o
new.c: In function ‘main’:
new.c:4: error: ‘O_RDWR’ undeclared (first use in this function)
new.c:4: error: (Each undeclared identifier is reported only once
new.c:4: error: for each function it appears in.)
new.c:4: error: ‘O_NOCTTY’ undeclared (first use in this function)
new.c:4: error: ‘O_NDELAY’ undeclared (first use in this function)
new.c:4: warning: initialization makes pointer from integer without a cast

Автор: Dude03 6.11.2007, 18:34
Цитата(theworldcreator @  6.11.2007,  14:35 Найти цитируемый пост)

Так? Я что то не где не смог найти описание функции write.

=) man write

Автор: theworldcreator 6.11.2007, 19:02
Насколько я понимаю, функция write() языка C и команда набранная в терминале - это разные вещи. На запрос "man write" говорит что это команда для посылки сообщений другим пользователям.
Цитата

write - send a message to another user

Автор: MAKCim 6.11.2007, 20:51
theworldcreator,
man 2 write
 smile  

Автор: theworldcreator 6.11.2007, 20:59
Извиняюсь, был не прав.
Но ошибки с не объявленными константами остались
P.S. Вот полный код:
Код

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    FILE *com = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); //открываешь порт
    write(com, 0x00, 1); //записываем строку в ..
    return 0;
}


Добавлено через 3 минуты и 41 секунду
Вот вывод ошибок:
Код

user@debian:~/Desktop/p$ gcc new.c -o new2.o
new.c: In function ‘main’:
new.c:5: error: ‘O_RDWR’ undeclared (first use in this function)
new.c:5: error: (Each undeclared identifier is reported only once
new.c:5: error: for each function it appears in.)
new.c:5: error: ‘O_NOCTTY’ undeclared (first use in this function)
new.c:5: error: ‘O_NDELAY’ undeclared (first use in this function)
new.c:5: warning: initialization makes pointer from integer without a cast
new.c:6: warning: passing argument 1 of ‘write’ makes integer from pointer without a cast

Автор: theworldcreator 8.11.2007, 23:34
Почитав руководства, и книжку по C, переписал немного:
Код

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>


int main(int argc, char *argv[])
{
      int buf=0x11;
      int com = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); //открываешь порт
      write(com, &buf, 1); //записываем строку в ..


    return 0;
}


Теперь warning's не выдает, только ошибке о константах: 
Код

user@debian:~/Desktop/пульт_c_prog$ gcc new.c -o new.o
new.c: In function ‘main’:
new.c:11: error: ‘O_RDWR’ undeclared (first use in this function)
new.c:11: error: (Each undeclared identifier is reported only once
new.c:11: error: for each function it appears in.)
new.c:11: error: ‘O_NOCTTY’ undeclared (first use in this function)
new.c:11: error: ‘O_NDELAY’ undeclared (first use in this function)


Добавлено @ 23:39
Если взять константы в кавычки
Код

int com = open("/dev/ttyS0", "O_RDWR | O_NOCTTY | O_NDELAY"); //открываешь порт

компилирует без ошибок, но не работает

Автор: Lohmatii 9.11.2007, 02:57
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>

в каком-то из этих хедеров все будет smile

Автор: theworldcreator 10.11.2007, 01:29
Теперь компилируется без ошибок, но все равно не работает! smile 

Автор: theworldcreator 10.11.2007, 19:51
Ура, заработало!
Ключевой была идея(друг посоветовал) засунуть запись единичек в бесконечный цикл, а то вольтметр не успевал снять показания.
Хотя результаты оказались несколько странные - уровень изменяется только на ножке номер 3(TxD: входной)
При записи 0x00 на  ножке появляется примерно 9 вольт, а 0x11 давало примерно 5 вольт.
Вот код;
Код

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>


int main(int argc, char *argv[])
{
      int buf=0x00;
      int com = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); //открываешь порт
      while(1){
            write(com, &buf, 1); //записываем строку в ..
      }
//    read(com, &val, 1);
    return 0;
}


Сейчас начну экспериментировать с чтением. Я так понимаю, чтобы записать на ножку 0(в физическом плане), надо замкнуть ее на ножку ground?

Автор: niccom 12.11.2007, 13:57
Цитата(theworldcreator @ 10.11.2007,  19:51)
Сейчас начну экспериментировать с чтением. Я так понимаю, чтобы записать на ножку 0(в физическом плане), надо замкнуть ее на ножку ground?




Не нужно ничего замыкать на землю.

Организуй лучше петлю связи.
RX  замкни с TX - затем пиши данные
в порт и читай их сразу же.

Автор: theworldcreator 13.11.2007, 18:23
Замкнул по вашему совету 2 и 3 ножку.
Теперь read возвращает все время(независимо от записываемого значения)
�� ����� ���)����E�t1��֍�
(кодировка UTF-8)
Код программы:
Код

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>


int main(int argc, char *argv[])
{
      int val;
//      int i;
      int buf=0x00;
      int com = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); //открываешь порт
//      while(1){
//      for(i=0;i!=100000;i++){
      write(com, &buf, 1); //записываем строку в ..
//      }

      read(com, &val, 1);
      printf(val);
      printf("\n");

    close(com); //закрываем порт
    return 0;
}

Ошибки возвращаемые компилятором:
Код

user@debian:~/Desktop/пульт_c_prog$ gcc new.c -o new.o
new.c: In function ‘main’:
new.c:24: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast

Если передать функции printf() параметр &val, компилятор возвращает:
Код

user@debian:~/Desktop/пульт_c_prog$ gcc new.c -o new.o
new.c: In function ‘main’:
new.c:24: warning: passing argument 1 of ‘printf’ from incompatible pointer type

А сама программа:
i�

Автор: JackYF 13.11.2007, 18:39
Цитата(theworldcreator @  13.11.2007,  18:23 Найти цитируемый пост)
printf(val);

printf("%d", val);

Автор: theworldcreator 13.11.2007, 19:40
Теперь все время возвращает "134514025", не зависимо от записанного в порт значения
Пробовал использовать другие типы переменной val, и записывать/считывать большее количество байт. Тип double и чтение 8 байт выдает все время "1"; тип unsigned long int и чтение 4 байт дает то же "134514025"
Имел ввиду:
Код

unsigned long int val;
write(com, &buf, 4); 
read(com, &val, 4);

Автор: xvr 14.11.2007, 16:52
Цитата(theworldcreator @ 13.11.2007,  19:40)
Теперь все время возвращает "134514025", не зависимо от записанного в порт значения
Пробовал использовать другие типы переменной val, и записывать/считывать большее количество байт. Тип double и чтение 8 байт выдает все время "1"; тип unsigned long int и чтение 4 байт дает то же "134514025"
Имел ввиду:
Код

unsigned long int val;
write(com, &buf, 4); 
read(com, &val, 4);

А топором ее не пробовал smile ?

1. Переменную val рекомендуется инициализировать (например нулем)
2. Убери O_NDELAY из open - у тебя порт открывается в асинхронном режиме, т.е. write возвращается когда реальные данные еще не передались, и соотвественно read'у еще нечего читать. При этом read так же возвращается немедленно (но с ошибкой), ничего не прочтя и не присваивая никаких данных в переданную ему память, т.е. в переменной val у тебя мусор.
3. Почитай какой нибудь букварь по работе с COM портом, там все не так просто :(


Автор: theworldcreator 14.11.2007, 20:54
Букварь сейчас поищу.
Теперь(после выполнения ваших, xvr, советов) программка стопорится на чтение(я перед каждым действием поставил вывод на экран, например "Writing...", а после "OK\n") на неопределенный срок(уже минут пять висит).

Автор: xvr 14.11.2007, 22:55
Цитата(theworldcreator @ 14.11.2007,  20:54)
Букварь сейчас поищу.
Теперь(после выполнения ваших, xvr, советов) программка стопорится на чтение(я перед каждым действием поставил вывод на экран, например "Writing...", а после "OK\n") на неопределенный срок(уже минут пять висит).

И будет висеть и дальше smile Либо включено аппаратное управление потоком (в таком случае порт не будет принимать данные пока на соотвествующих линиях не будут установленны соотвествующие состояния), либо полностью выключенна буферизация (в таком случае данные пришли ДО вызова read, и были потеряны). И то и другое настраивается через ioctl (какие именно я наизусть не помню)

Автор: theworldcreator 15.11.2007, 17:53
Блин, что то ни букваря, ни включения буферизации не могу найти:( Лучшее что обнаружил, это вот это руководство: http://www.opennet.ru/docs/RUS/serial_guide/
И вот этот кусок кода:
Код

      struct termios options;
      tcgetattr(com, &options);
      cfsetispeed(&options, B4800);
      cfsetospeed(&options, B4800);
      options.c_cflag |= CS8 | CLOCAL | CREAD;
      tcsetattr(com, TCSANOW, &options);

Но все равно не смог прочесть значение((

Автор: xvr 15.11.2007, 21:57
Цитата(theworldcreator @ 15.11.2007,  17:53)
Блин, что то ни букваря, ни включения буферизации не могу найти:( Лучшее что обнаружил, это вот это руководство: http://www.opennet.ru/docs/RUS/serial_guide/
И вот этот кусок кода:
Код

      struct termios options;
      tcgetattr(com, &options);
      cfsetispeed(&options, B4800);
      cfsetospeed(&options, B4800);
      options.c_cflag |= CS8 | CLOCAL | CREAD;
      tcsetattr(com, TCSANOW, &options);

Но все равно не смог прочесть значение((

Добавь
Код

options.c_cflag &= ~CNEW_RTSCTS;
options.c_iflag &= ~(IXON|IXOFF|IXANY);

так же можно попробовать вернуть O_NDELAY в открытие порта и добавить код
Код

fcntl(com, F_SETFL, 0);

Автор: theworldcreator 15.11.2007, 23:45
На строчку
Код

options.c_cflag &= ~CNEW_RTSCTS;

ругается следующим образом
Код

main.c: In function ‘main’:
main.c:25: error: ‘CNEW_RTSCTS’ undeclared (first use in this function)
main.c:25: error: (Each undeclared identifier is reported only once
main.c:25: error: for each function it appears in.)

Если ее закоментить, то компилятор молчит, но значение не читает.

Автор: xvr 16.11.2007, 15:37
Цитата(theworldcreator @ 15.11.2007,  23:45)
На строчку
Код

options.c_cflag &= ~CNEW_RTSCTS;

ругается следующим образом
Код

main.c: In function ‘main’:
main.c:25: error: ‘CNEW_RTSCTS’ undeclared (first use in this function)
main.c:25: error: (Each undeclared identifier is reported only once
main.c:25: error: for each function it appears in.)

Если ее закоментить, то компилятор молчит, но значение не читает.

А порт вообще работает (с соединенными ногами 2 и 3)? Попробуй подключиться к нему каким-нибудь терминалом и попечатай - должно быть эхо (в терминале надо выключить аппаратный handshake и эхо).
Если работает, то дай текущую версию твоего кода - будем смотреть дальше.

Автор: xvr 16.11.2007, 16:03
Цитата(theworldcreator @ 15.11.2007,  23:45)
На строчку
Код

options.c_cflag &= ~CNEW_RTSCTS;

ругается следующим образом
Код

main.c: In function ‘main’:
main.c:25: error: ‘CNEW_RTSCTS’ undeclared (first use in this function)
main.c:25: error: (Each undeclared identifier is reported only once
main.c:25: error: for each function it appears in.)

Если ее закоментить, то компилятор молчит, но значение не читает.

Еще попробуй CRTSCTS вместо CNEW_RTSCTS

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)