2016-11-01 4 views
0

シリアル経由でXbeeからデータを読み取ろうとしています。 xbee_init()を呼び出してポートを初期化すると、xbee_read()が呼び出されます。何らかの理由で、常にデータが読み込まれず、-1のエラーが発生します。しかし、私はgtktermやArduinoのシリアルモニタのようなサードパーティのプログラムを使ってポートを見ると、突然私のプログラムからデータを読み始めます。私のプログラムを終了して再起動するまで、それは正常に動作します。サードパーティのプログラムによってポートが開かれていない限りシリアルデータを読み取ることができません

これはなぜ起こっているのでしょうか?私はXbeeとArduinoの両方でこれをテストしました。これは同じ動作です。私はより大きなC++プログラムからこれらの関数を呼び出しています。ありがとう!

#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <errno.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <fcntl.h> 
#include <termios.h> 
#include "../include/m545_wireless_communication/readXbee.h" 

int xbee_init (char *port, struct termios *tty) { 

    int fd=open(port,O_RDWR | O_NOCTTY | O_NONBLOCK); 

    if(fd == -1){return 0;} 
    else { 
     if(tcgetattr(fd, tty)!=0){return 0;} 
     else{ 
       cfsetospeed(tty, B57600); 
       cfsetispeed(tty, B57600); 

       tty->c_cflag &= ~PARENB; 
       tty->c_cflag &= ~CSTOPB; 
       tty->c_cflag &= ~CSIZE; 
       tty->c_cflag |= CS8; 
       tty->c_cflag &= ~CRTSCTS; 
       tty->c_cflag |= CLOCAL | CREAD; 

       tty->c_iflag |= IGNPAR | IGNCR; 
       tty->c_iflag &= ~(IXON | IXOFF | IXANY); 
       tty->c_lflag |= ICANON; 
       tty->c_oflag &= ~OPOST; 
       tcsetattr(fd, TCSANOW, tty); 

       } 
      } 

    return fd; 
} 


char* xbee_read (int fd, char *buffer) { 

    if(fd){ 
     int n=read(fd,buffer,11); 
     printf("%d\n", n); 
     return buffer; 
    }else{ 
     return NULL; 
    } 
} 

void xbee_close(int fd){ 
    close(fd); 
} 

私のxbee関数を呼び出す主な関数は次のとおりです。これはROSプロジェクトの一部であり、このノードはシリアル経由でxbeeからデータを読み込み、10Hzで/ xbeeトピックに公開するように設計されています。

#include "ros/ros.h" 
#include "std_msgs/String.h" 
#include <sstream> 
#include <termios.h> 
#include "m545_wireless_communication/readXbee.h" 


int main(int argc, char **argv) 
{ 

    ros::init(argc, argv, "Broadcaster"); 

    ros::NodeHandle broadcasterHandle; 
    ros::Publisher broadPub = broadcasterHandle.advertise<std_msgs::String>("xbee", 1); 

    char *port = "/dev/ttyUSB1"; 
    struct termios tty; 
    char buffer[11]; 

    int fd = xbee_init(port,&tty); 

    ros::Rate loop_rate(10); 

    while (ros::ok()) 
    { 
    char *message = xbee_read(fd, buffer); 

    std_msgs::String msg; 

    std::stringstream ss; 
    ss << message; 
    msg.data = ss.str(); 

    ROS_INFO("I heard: %s", msg.data.c_str()); 

    broadPub.publish(msg); 

    ros::spinOnce(); 

    loop_rate.sleep(); 
    } 

    ROS_INFO("Closing Port"); 
    xbee_close(fd); 

    return 0; 
} 
+0

1)注意:コードの 'c_cflag'フィールドが' unsigned'より広い場合、 '&=〜various_int_constants;'が問題になる可能性があります。 'tty-> c_cflag | = PARENB; tty-> c_cflag^= PARENB;はまれな問題を回避します。 2) 'xbee_read()'と他の2つの関数を呼び出します。 – chux

+0

ありがとう@chuxすべてのc_cflagsをダブルチェックするパスに私を入れてください – raab

+1

* "私はいつもデータを読み込まず-1のエラーを取得します。" * - グローバル変数** errno **にアクセスする必要がありますエラー状態の詳細を取得します。根本的な問題は、非ブロックモードを使用していることです。 http://stackoverflow.com/questions/1613916/linux-serial-port-read-returning-eagain – sawdust

答えて

0

私はc_cflagsをどのように宣言していたのかがわかりました。 Xbeeはrawモードで読み込む必要があるので、フラッグを自分で設定するのではなく、cfmakeraw()を使用しました。しかし、私は正確に何が間違っているのか、サードパーティ製のプログラムでポートを開くことがどのように接続を助けていたのかまだ分かりません。

int xbee_init (char *port, struct termios *tty) { 

    int fd=open(port,O_RDWR | O_NOCTTY | O_NONBLOCK); 

    if(fd == -1){return 0;}//should be something better 
    else { 
     if(tcgetattr(fd, tty)!=0){return 0;} 
     else{ 
       // cfsetospeed(tty, B57600); 
       // cfsetispeed(tty, B57600); 

       // tty->c_cflag &= ~PARENB; 
       // tty->c_cflag &= ~CSTOPB; 
       // tty->c_cflag &= ~CSIZE; 
       // tty->c_cflag |= CS8; 
       // tty->c_cflag &= ~CRTSCTS; 
       // tty->c_cflag |= CLOCAL | CREAD; 
       // // tty->c_cflag |= PARENB; 
       // // tty->c_cflag ^= PARENB; 

       // tty->c_iflag |= IGNPAR | IGNCR; 
       // tty->c_iflag &= ~(IXON | IXOFF | IXANY); 
       // tty->c_lflag |= ICANON; 
       // tty->c_oflag &= ~OPOST; 

       cfmakeraw(&tty); 
       cfsetispeed(&tty, B57600); 

       tcsetattr(fd, TCSANOW, &tty); 

       } 
      } 

    return fd; 
} 
+1

を参照してください。根本的な問題のみを隠しており、不完全なtermios設定があります。サンプルコードについては、http://stackoverflow.com/questions/12437593/how-to-read-a-binary-data-over-serial-terminal-in-c-program/12457195#12457195を参照してください。それ以外の場合は[POSIXオペレーティングシステム用シリアルプログラミングガイド](http://www.cmrr.umn.edu/~strupp/serial.html) – sawdust

関連する問題