2013-08-27 3 views
0

Я написал программу в c для чтения и записи последовательного порта. Но проблема в том, что я использую цикл while, и он непрерывно отправляет команду через последовательный порт.Последовательный порт Linux в C

  1. Я хочу написать какую-либо команду на последовательный порт
  2. ждать ответа
  3. написать другую команду
  4. ожидание некоторого ответа и так далее

Мой код выглядит следующим образом: -

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

int main() 

    { 
    printf("\n"); 
    printf("Please wait till serial Port is being Initialized .... \n"); 
    sleep(2); 
    printf("\n................. Initializing ................\n"); 
    sleep(2); 
    printf("\n"); 
    printf("\n\n"); 
    static int fd = 0; 
     int len; 
     char res[100]; 
     char s[100] = " Hellow World"; 


    struct termios options; 

    //================================================================== 
    //     hard coaded port ttyO3 
    //================================================================== 

     fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); 
      fcntl(fd, F_SETFL, O_NONBLOCK); 

    //================================================================== 
    //        Error Handling 
    //================================================================== 

      if (fd < 0) 
     { 
     printf("Serial open error %d %s\n", errno, strerror(errno)); 
      } 
     printf("\n"); 

    printf("\n==================================================\n"); 

    //================================================================== 
    //     Get the current options for the port... 
    //================================================================== 

    tcgetattr(fd, &options); 


     //================================================================== 
    //    Set the baud rates to 115200... 
    //================================================================== 


    cfsetispeed(&options, B115200); 
    cfsetospeed(&options, B115200); 

    //================================================================= 
    // Enable the receiver and set local mode.. 
    //================================================================== 

    options.c_cflag |= (CLOCAL | CREAD); 

//==================================================================  
// Set the new options for the port... 
//================================================================== 

    tcsetattr(fd, TCSANOW,&options); 

     while(1) 
     { 



     write(fd,s,strlen((char*)s)); 
     sleep(1); 

     len = read(fd,res,100); 
     if (len < 0) 
     { 
     if (errno == EAGAIN) 
     {   
       continue; 
     } 
     else 
     { 
      printf("read error %d %s\n", errno, strerror(errno)); 
     } 
     } 
    else 
     {     
     res[len < 100 ? len:100] ='\0'; 
     printf("read %d chars: %s\n",len, res); 
     } 
    } 
    close(fd); 
    } 

где я ошибаюсь.

Спасибо и наилучшими пожеланиями

ответ

1

Похоже дескриптор файла открывается как неблокирующая (fcntl(fd, F_SETFL, O_NONBLOCK);). У вас должна быть операция блокировки, если вы хотите дождаться чтения данных.

Вы можете сделать блокировку дескриптора файла или использовать некоторый асинхронный менеджер, например select.

1

Поскольку вы не указали свой файловый дескриптор (дважды), вы должны как система ждать между шагами. Общим способом сделать это является системный вызов select, который вы можете использовать, чтобы ждать, пока что-нибудь прочитает из дескриптора файла.

Можно сделать что-то вроде этого:

write(...); 

fd_set poll_set; 
FD_ZERO(&poll_set); 
FD_SET(fd, &poll_set); 

/* Wait, with no timeout, for something to be readable */ 
int rc = select(fd + 1, &poll_set, NULL, NULL, NULL); 
if (rc == -1) 
{ 
    perror("select"); 
} 
else 
{ 
    /* Continue to next step, where you read */ 
} 

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

+0

Я предпочел бы использовать [poll (2)] (http://man7.org/linux/man-pages/man2/poll.2.html) вместо (устаревшего) 'select' syscall. –