Пишете и след това четете на сериен порт в C

Имам USB към сериен адаптер, свързан към /dev/ttyUSB0, който се свързва към ротационен етап. Мога да комуникирам с този етап на ротация, като просто изпратя ASCII команди през серийния порт. т.е. да поискате текущата позиция на този етап на въртене просто:

  1. в прозорец 1: echo -e "1tp\r" > /dev/ttyUSB
  2. в прозорец 2: cat /dev/ttyUSB, който връща текущата позиция: "1TP-0.00000"

Сега искам да мога да правя точно това при определен тригер в C програма.

Прегледах този удивителен архив и намерих няколко примера за това как може да се направи. Например

Така че въз основа на тях написах този много грозен код, за да опитам просто да напиша "1tp\r" на серийния порт и след това да прочета върнатата стойност (позицията на етапа на въртене) обратно. Ето кода по-долу.

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

int main(int argc, char *argv[])
{
  char line[1024];
  int chkin;
  int chkout;
  char input[1024];
  char msg[1024];
  char serport[24];

  // argv[1] - serial port

  sprintf(serport, "%s", argv[1]);

  int file= open(serport, O_RDWR | O_NOCTTY | O_NDELAY);
  printf("file descriptor: %d\n",file);

  if (file == 0)
    {
      sprintf(msg, "open_port: Unable to open %s.\n", serport);
      perror(msg);
    }
  else
    fcntl(file, F_SETFL, FNDELAY); //fcntl(file, F_SETFL, 0);

  while (1)
    {

      usleep (1000000);
      // printf("enter input data:\n");
      //scanf("%s",&input[0]);
      // printf("You entered %s\n",&input);

      //input= "1tp\r";
      chkin = write(file,"1tp\r",5);
      printf("chkin: %d\n",chkin);

      if (chkin<0)
    {
          printf("cannot write to port\n");
    }
      fcntl(file, F_SETFL, FNDELAY);
      //chkin=read(file,line,sizeof line);
      usleep (100000);

      //while ((chkin=read(file,line,sizeof line))>=0)
      //printf("chkin: %d\n",chkin);
      chkout = read(file, line ,sizeof line);
      //{
       if (chkout<0)
     {
       printf("cannot read from port\n");
     }
       else
     {
       printf("bytes: %d, line=%s\n",chkout, line);
     }
       //}

      /*CODE TO EXIT THE LOOP GOES HERE*/
      if (input[0] == 'q') break;
    }

  close(file);
  return 0;
}

Е, не става. Когато го стартирам като: ./sertest /dev/ttyUSB0, просто получавам грешката "cannot read from port". В действителност проблемът изглежда е, че низът "1tp\r" не изглежда да се записва на серийния порт. Освен това, след като приключа с това, настройките на серийния порт изглежда са объркани, защото изобщо не мога да комуникирам със сцената чрез прости терминални команди и трябва да нулирам серийния порт с помощта на minicom.

Трябва също да отбележа, че знам, че мога успешно да прочета нещо от серийния порт с втората част от този код, защото успях да изпратя низа "1tp\r" с терминална команда и просто прочетох изхода на етапа със съответния кодов фрагмент в примера по-долу.

И така, ще оценя някои приноси за това как успешно да напиша този прост низ "1tp\r" (или подобен) на серийния порт и да го заменя с четене на серийния порт.

Не съм програмист, така че се извинявам предварително за лошия стил на частта от код тук.


person Denis Barkats    schedule 21.07.2015    source източник
comment
Има само 4 знака за писане. \r е един знак, въпреки че изглежда като два. По-конкретно \r е връщане на каретка, шестнадесетична стойност 0x0D.   -  person user3386109    schedule 22.07.2015
comment
Освен това командата echo може да добавя безвъзмезден символ за подаване на ред в края на съобщението. Ако случаят е такъв, кодът трябва да изпраща "1tp\r\n", което всъщност е 5 знака.   -  person user3386109    schedule 22.07.2015
comment
Обадете се на perror веднага след извикването на write, за да ви даде по-точна индикация каква е грешката.   -  person kaylum    schedule 22.07.2015
comment
Или използвайте errno. Проверихте ли дали имате разрешение за писане?   -  person Iharob Al Asimi    schedule 22.07.2015
comment
точно. Поправих низа да записва в 1tp\r\n и размерът му е правилно 5. Кой аргумент обаче трябва да бъде в грешка? Забравих да кажа, че правя това като root, така че да, имам разрешения да пиша в /dev/ttyUSB0 (или в командния ред, или в C кода.   -  person Denis Barkats    schedule 22.07.2015
comment
Не използвайте perror() опитайте това fprintf(stderr, "error(%d): %s\n", errno, strerror(errno));. вместо това трябва да включите errno.h   -  person Iharob Al Asimi    schedule 22.07.2015
comment
Вашият тест на командния ред пише в /dev/ttyUSB, но вашият тест на код пише в /dev/ttyUSB0. Може би трябва да опитате вашия код с /dev/ttyUSB   -  person cup    schedule 22.07.2015