2017-02-06 23 views
1

私はLinux上でシリアル通信(RS232 < - > USB)で接続されたKeithley 6485ピコアンメータから現在の値を読み出す簡単なアプリケーションを作成しようとしています。Cでのシリアル通信

現在、このような値は、デバイスの必要な初期化をすべて行い、 "READ?"それに:echo "READ?" > /dev/ttyUSB0。次にcat /dev/ttyUSB0が聞いていた場合、次の出力が得られます:-2.250416E-14A,+8.320175E+03,+0.000000E+00、そのうち最初の数字が希望の値です。

私はtermiosのライブラリを使用して、次のコードを使用した値を出力することができるようにする:

/*====================================================================================================*/ 
    /* Serial Port Programming in C (Serial Port Read)             */ 
/* Non Cannonical mode                    */ 
/*----------------------------------------------------------------------------------------------------*/ 
    /* Program reads a string from the serial port at 9600 bps 8N1 format         */ 
/* Baudrate - 9600                     */ 
/* Stop bits -1                      */ 
/* No Parity                       */ 
    /*----------------------------------------------------------------------------------------------------*/ 
/* Compiler/IDE : gcc 4.6.3                   */ 
/* Library  :                     */ 
/* Commands  : gcc -o serialport_read serialport_read.c           */ 
/* OS   : Linux(x86) (Linux Mint 13 Maya)(Linux Kernel 3.x.x)        */        
/* Programmer : Rahul.S                   */ 
/* Date   : 21-December-2014                 */ 
/*====================================================================================================*/ 

/*====================================================================================================*/ 
/* www.xanthium.in           */ 
/* Copyright (C) 2014 Rahul.S                   */ 
/*====================================================================================================*/ 

/*====================================================================================================*/ 
/* Running the executable                    */ 
/* ---------------------------------------------------------------------------------------------------*/ 
/* 1) Compile the serialport_read.c file using gcc on the terminal (without quotes)     */ 
    /*                         */ 
/* " gcc -o serialport_read serialport_read.c "             */ 
/*                         */ 
    /* 2) Linux will not allow you to access the serial port from user space,you have to be root.So use */ 
    /* "sudo" command to execute the compiled binary as super user.         */ 
    /*                         */ 
    /*  "sudo ./serialport_read"                  */ 
/*                         */ 
/*====================================================================================================*/ 

/*====================================================================================================*/ 
/* Sellecting the Serial port Number on Linux               */ 
/* ---------------------------------------------------------------------------------------------------*/ 
/* /dev/ttyUSBx - when using USB to Serial Converter, where x can be 0,1,2...etc      */ 
/* /dev/ttySx - for PC hardware based Serial ports, where x can be 0,1,2...etc      */ 
    /*====================================================================================================*/ 

/*-------------------------------------------------------------*/ 
    /* termios structure - /usr/include/asm-generic/termbits.h */ 
/* use "man termios" to get more info about termios structure */ 
/*-------------------------------------------------------------*/ 

    #include <stdio.h> 
    #include <fcntl.h> /* File Control Definitions   */ 
    #include <termios.h> /* POSIX Terminal Control Definitions */ 
    #include <unistd.h> /* UNIX Standard Definitions  */ 
    #include <errno.h> /* ERROR Number Definitions   */ 

void main(void) 
    { 
     int fd;/*File Descriptor*/ 

    printf("\n +----------------------------------+"); 
    printf("\n |  Serial Port Read   |"); 
    printf("\n +----------------------------------+"); 

    /*------------------------------- Opening the Serial Port -------------------------------*/ 

    /* Change /dev/ttyUSB0 to the one corresponding to your system */ 

     fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY); /* ttyUSB0 is the FT232 based USB2SERIAL Converter */ 
    // fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY | O_NDELAY); /* ttyUSB0 is the FT232 based USB2SERIAL Converter */ 
          /* O_RDWR - Read/Write access to serial port  */ 
          /* O_NOCTTY - No terminal will control the process */ 
          /* Open in blocking mode,read will wait    */ 



     if(fd == -1)      /* Error Checking */ 
       printf("\n Error! in Opening ttyUSB0 "); 
     else 
       printf("\n ttyUSB0 Opened Successfully "); 


    /*---------- Setting the Attributes of the serial port using termios structure --------- */ 

    struct termios SerialPortSettings; /* Create the structure       */ 

    tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */ 

    /* Setting the Baud rate */ 
    cfsetispeed(&SerialPortSettings,B19200); /* Set Read Speed as 19200      */ 
    cfsetospeed(&SerialPortSettings,B19200); /* Set Write Speed as 19200      */ 

    /* 8N1 Mode */ 
    SerialPortSettings.c_cflag &= ~PARENB; /* Disables the Parity Enable bit(PARENB),So No Parity */ 
    SerialPortSettings.c_cflag &= ~CSTOPB; /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */ 
    SerialPortSettings.c_cflag &= ~CSIZE; /* Clears the mask for setting the data size    */ 
    SerialPortSettings.c_cflag |= CS8;  /* Set the data bits = 8         */ 

    SerialPortSettings.c_cflag &= ~CRTSCTS;  /* No Hardware flow Control       */ 
    SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines  */ 


    SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);   /* Disable XON/XOFF flow control both i/p and o/p */ 
    SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode       */ 

    SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/ 

    /* Setting Time outs */ 
    SerialPortSettings.c_cc[VMIN] = 13; /* Read at least 10 characters */ 
    SerialPortSettings.c_cc[VTIME] = 0; /* Wait indefinetly */ 


    if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/ 
     printf("\n ERROR ! in Setting attributes"); 
    else 
       printf("\n BaudRate = 19200 \n StopBits = 1 \n Parity = none"); 

     /*------------------------------- Read data from serial port -----------------------------*/ 

    char read_buffer[32]; /* Buffer to store the data received    */ 
    int bytes_read = 0; /* Number of bytes read by the read() system call */ 
    int i = 0; 

    tcflush(fd, TCIFLUSH); /* Discards old data in the rx buffer   */ 

    bytes_read = read(fd,&read_buffer,32); /* Read the data     */ 

    printf("\n\n Bytes Rxed -%d", bytes_read); /* Print the number of bytes read */ 
    printf("\n\n "); 
    for(i=0;i<13;i++) /*printing only the needed bytes*/ 
     printf("%c",read_buffer[i]); 

    printf("\n +----------------------------------+\n\n\n"); 

    close(fd); /* Close the serial port */ 

    } 

出力:

+----------------------------------+ 
|  Serial Port Read   | 
+----------------------------------+ 
    ttyUSB0 Opened Successfully 
    BaudRate = 19200 
    StopBits = 1 
    Parity = none 

    Bytes Rxed -13 

    -2.864104E-14 
+----------------------------------+ 

をしかし、値を読み取ることができるようにするために、私は「READ?」をエコーする必要があります。コマンドを実行するか(またはwrite()関数を使用してデバイスに書き込む)、値を知りたいときはいつでも。

現在、read()関数はデバイスから何かが来るのを待っているので、最も優雅な方法で同じアプリケーションに書き込みと読み取りの両方を行うことができます「READ?」を送信できません。同じCコードからのコマンドですか?


EDIT:どうやら私の書き込み手順が正常に動作していないよう:

ポート設定:

struct termios SerialPortSettings; /* Create the structure       */ 

    tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */ 

    cfsetispeed(&SerialPortSettings,(speed_t)B19200); /* Set Read Speed as 19200      */ 
    cfsetospeed(&SerialPortSettings,(speed_t)B19200); /* Set Write Speed as 19200      */ 

    SerialPortSettings.c_cflag &= ~PARENB; /* Disables the Parity Enable bit(PARENB),So No Parity */ 
    SerialPortSettings.c_cflag &= ~CSTOPB; /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */ 
    SerialPortSettings.c_cflag &= ~CSIZE; /* Clears the mask for setting the data size    */ 
    SerialPortSettings.c_cflag |= CS8;  /* Set the data bits = 8         */ 

    SerialPortSettings.c_cflag = ~CRTSCTS;  /* No Hardware flow Control       */ 
    SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines  */ 


cfmakeraw(&SerialPortSettings); 

tcflush(fd,TCIFLUSH); 

    SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);   // Disable XON/XOFF flow control both i/p and o/p 
    SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Non Cannonical mode       
    SerialPortSettings.c_oflag &= ~OPOST;//No Output Processing 

執筆:

char write_buffer[] = "READ?"; /* Buffer containing characters to write into port  */ 
    int bytes_written = 0; /* Value for storing the number of bytes written to the port */ 

    bytes_written = write(fd,&write_buffer,sizeof(write_buffer) -1); 
printf("%s written to ttyUSB0 \n",write_buffer); 
    printf("%d Bytes written to ttyUSB0 \n", bytes_written); 
    printf("+----------------------------------+\n\n"); 

    close(fd);/* Close the Serial port */ 

これを実行するたびに、I gら:

+----------------------------------+ 
|  Serial Port Write   | 
+----------------------------------+ 
ttyUSB0 Opened Successfully 
Attributes set 
READ? written to ttyUSB0 
5 Bytes written to ttyUSB0 
+----------------------------------+ 

しかしcat /dev/ttyUSB0は何がデバイスから見ていないようです。私はで同様の質問をチェックしています

Linux C Serial Port Reading/Writing

やコードに大きな違いを見つけることができません - それは間違ったポート設定のサインだろうか、私は何かが足りないのですか?

+0

可能な複製(http://stackoverflow.com/questions/18108932/linux-c-serial-port-reading-writing) – LPs

+1

なぜあなたは呼び出すことはできません答えを読むために 'read'を呼び出す前に、クエリを送る' write'? –

+1

'write'が' read'の前に呼び出された場合、その値は 'read'によってアクセスできません - バッファからではなくリアルタイムでバイト単位で読み込むことになります。 – vastas

答えて

1

問題が修正されました。

明らかに、デバイスは、それがそのようなコマンドを受信したときにそのため、バスは「ハング」なるchar write_buffer[] = "READ?";

に使用できませんでしたエンドラインターミネータ、およびそれが再びいずれかを動作させるために待っていましたもう一度ポートを開けなければならないだろう。

これはまた、echo "READ?" > /dev/ttyUSB0コマンドがなぜ機能するのかを説明します。これは、エンド・ライン・ターミネータを自動的に出力するためです。

私は以下の作業コードを添付しています - あなたのコミッションと親切な助けに皆に感謝します!

int fd;   //device file id 
//------------------------------- Opening the Serial Port ------------------------------- 
    fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY); // ttyUSB0 is the FT232 based USB2SERIAL Converter 
    if(fd == -1)      // Error Checking 
    printf("Error while opening the device\n"); 
//---------- Setting the Attributes of the serial port using termios structure --------- 
    struct termios SerialPortSettings; // Create the structure       
    tcgetattr(fd, &SerialPortSettings); // Get the current attributes of the Serial port 
// Setting the Baud rate 
    cfsetispeed(&SerialPortSettings,B19200); // Set Read Speed as 19200      
    cfsetospeed(&SerialPortSettings,B19200); // Set Write Speed as 19200      

    SerialPortSettings.c_cflag &= ~PARENB; // Disables the Parity Enable bit(PARENB),So No Parity 
    SerialPortSettings.c_cflag &= ~CSTOPB; // CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit 
    SerialPortSettings.c_cflag &= ~CSIZE; // Clears the mask for setting the data size    
    SerialPortSettings.c_cflag |= CS8;  // Set the data bits = 8         
    SerialPortSettings.c_cflag &= ~CRTSCTS;  // No Hardware flow Control       
    SerialPortSettings.c_cflag |= CREAD | CLOCAL; // Enable receiver,Ignore Modem Control lines   
    SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable XON/XOFF flow control both i/p and o/p 
    SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Non Cannonical mode 
    SerialPortSettings.c_oflag &= ~OPOST;//No Output Processing 
// Setting Time outs 
    SerialPortSettings.c_cc[VMIN] = 13; // Read at least 10 characters 
    SerialPortSettings.c_cc[VTIME] = 0; // Wait indefinetly 

    if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) // Set the attributes to the termios structure 
    printf("Error while setting attributes \n"); 
    //------------------------------- Read data from serial port ----------------------------- 

    char read_buffer[32]; // Buffer to store the data received    
    int bytes_read = 0; // Number of bytes read by the read() system call 
    int bytes_written = 0; // Number of bytes written 
    int i = 0; 

    tcflush(fd, TCIFLUSH); // Discards old data in the rx buffer    
//Device intialization 

    char write_buffer[]="READ? \n "; 
    bytes_written=write(fd,&write_buffer,sizeof(write_buffer)); 


    bytes_read = read(fd,&read_buffer,32); // Read the data     

    for(i=0;i<13;i++) //printing only the needed characters 
    printf("%c",read_buffer[i]); 
    close(fd); // Close the serial port 
[LinuxのCシリアルポートの読み取り/書き込み]の
+0

ありがとうございました – achoora

0

データが利用可能かどうかを確認する前にselect()またはpoll()を使用してください。データが利用できない場合は、 "READ?"コマンド。