Find the answer to your Linux question:
Results 1 to 10 of 10
When I'm trying to close the serial port's file descriptor from a C program, the function close(fd) doesn't always return, or it takes a long time until it does; it ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Nov 2005
    Posts
    7

    close() freezes


    When I'm trying to close the serial port's file descriptor from a C program, the function close(fd) doesn't always return, or it takes a long time until it does; it works fine for a number of times but the program eventually freezes.
    It seems it is happening only when I receive something on the serial port.
    The program runs on linux 2.4.26, glibc 2.3.2.

    I've checked errno after every read/write() and is 0-success; for some reason the program hangs when I'm calling close().
    Before calling close(), I'm opening /dev/ttyS0 (raw input&output) and send strings and binary to configure the device attached to ttyS0; during this time I'm receiving from the attached device text and binary messages.
    Any suggestion where I should look to find the cause of this behaviour?

    Thanks

    PS
    I've tried to disable RX&TX before closing but I couldn't find anything usefull in glibc. I saw it done in serial module driver, but I don't want to directly access UART registers. Any suggestion how this could be done would really help me.

  2. #2
    Linux Guru lakerdonald's Avatar
    Join Date
    Jun 2004
    Location
    St. Petersburg, FL
    Posts
    5,035
    What does lsof'ing it say:
    Code:
    sudo lsof /dev/ttyS0

  3. #3
    Just Joined!
    Join Date
    Nov 2005
    Posts
    7
    Quote Originally Posted by lakerdonald
    What does lsof'ing it say:
    Code:
    sudo lsof /dev/ttyS0
    right before freezing
    gpsconfig 4175 root 5u CHR 4,64 10158 /dev/ttyS0
    after it freezes lsof shows nothing.

    Here it is what strace gives:
    open("/dev/ttyS0", O_RDWR|O_NONBLOCK|O_NOCTTY) = 5
    ioctl(5, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 opost isig icanon echo ...}) = 0
    ioctl(5, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 opost isig icanon echo ...}) = 0
    ioctl(5, TCFLSH, 0) = 0
    ioctl(5, TCFLSH, 0) = 0
    ioctl(5, SNDCTL_TMR_START or TCSETS, {B9600 -opost -isig -icanon -echo ...}) = 0
    ioctl(5, TCFLSH, 0x2) = 0
    write(4, "\220\3\n\0\1\0\200\2\2\0\200\2\200\2\340\1\364\0N \0\210"..., 40) = 40
    write(4, "\220\3\n\0\1\0\200\2\2\0\200\2\200\2\340\1\364\0N \0%\1"..., 40) = 40
    write(5, "$PMCAG,000,6\r\n", 14) = 14
    read(5, ",N,0.0,K*2D\n\n", 254) = 13
    read(5, "$GPGGA,203252.00,4404.2587,N,079"..., 254) = 104
    read(5, "\1~\201\5SQn\0\0\27\2\1\24\353G\24 \0\340\330\230\231\31"..., 254) = 27
    write(5, "\1S\254\25\217\372\372 \0\0\0\0\0\0\0\0\201\0\0\0\0\0\0"..., 27) = 27
    read(5, "\325\7\\#y\36\'\235\350?\334\227B\316v.\366\277!\ 202xC"..., 254) = 71
    write(5, "\1Q\256\f\0\0\0\0\0\0\0\0\0\0\0\0\f\1", 18) = 18
    read(5, "\1\24\353G\24 \0\0\222333J@\3\v\325\7c#y\36\'\235\350?"..., 254) = 40
    write(5, "\1n\221\1 !\1", 7) = 7
    read(5, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Jd\351@\v-\356@#\0"..., 254) = 112
    write(5, "\1n\221\1 !\1", 7) = 7
    read(5, "$GPGGA,203252.80,4404.2588,N,079"..., 254) = 160
    write(5, "$PMCAG,005,1,GGA,005,VTG,005\r\n", 30) = 30
    read(5, ",M,-35.5,M,,*54\n\n$GPVTG,0.0,T,,,"..., 254) = 48
    write(5, "$PMCAG,005,1,GGA,999,VTG,999\r\n", 30) = 30
    read(5, "$GPGGA,203253.20,4404.2588,N,079"..., 254) = 80
    write(5, "$PMCAG,005,1,GGA,999,VTG,999\r\n", 30) = 30
    read(5, "0.0,T,,,0.0,N,0.0,K*2D\n\n", 254) = 24
    read(5, "$GPGGA,203253.40,4404.2588,N,079"..., 254) = 200
    write(4, "\220\3\n\0\1\0\200\2\2\0\200\2\200\2\340\1\364\0v \0\202"..., 40) = 40
    ioctl(5, TCFLSH, 0) = 0
    ioctl(5, SNDCTL_TMR_START or TCSETS, {B9600 opost isig icanon echo ...}) = 0
    close(5

    and here the program hangs ...
    After Ctrl+C in console continues with
    ) = 0
    --- SIGINT (Interrupt) @ 0 (0) ---
    write(4, "\220\2\2\0\3\0\200\2+\0\1\0", 12) = -1 EPIPE (Broken pipe)
    --- SIGPIPE (Broken pipe) @ 0 (0) ---


    Thanks again

  4. $spacer_open
    $spacer_close
  5. #4
    Linux Guru lakerdonald's Avatar
    Join Date
    Jun 2004
    Location
    St. Petersburg, FL
    Posts
    5,035
    While it's hanging, lsof shows nothing on it?

  6. #5
    Just Joined!
    Join Date
    Nov 2005
    Posts
    7
    Quote Originally Posted by lakerdonald
    While it's hanging, lsof shows nothing on it?
    yes, it shows nothing while hanging

  7. #6
    Linux Guru lakerdonald's Avatar
    Join Date
    Jun 2004
    Location
    St. Petersburg, FL
    Posts
    5,035
    I don't know why it would be blocking then...

  8. #7
    Linux Guru lakerdonald's Avatar
    Join Date
    Jun 2004
    Location
    St. Petersburg, FL
    Posts
    5,035
    Could you post the relevant portion of the source code?

  9. #8
    Just Joined!
    Join Date
    Nov 2005
    Posts
    7
    open/close routines
    ============================================
    void TComPort::Open(void)
    {
    char sPortName[64];
    tcflag_t BAUDRATE, DATABITS, STOPBITS, PARITY;

    try{
    if (_PortNumber<2) {
    sprintf(sPortName, "/dev/ttyS%d", _PortNumber);
    } else {
    sprintf(sPortName, "/dev/ttyUSB%d", _PortNumber-2);
    }

    Close();

    _fd = open(sPortName, O_RDWR | O_NOCTTY | O_NDELAY);
    if (_fd < 0) throw Exception(ErrMsgs[ErrIdxCom+1]);
    fcntl(_fd, F_SETFL, 0);

    tcgetattr(_fd, &oldtio);
    tcgetattr(_fd, &newtio);

    tcflush(_fd, TCIFLUSH);
    switch (_baud_rate){
    case 9600 : BAUDRATE = B9600; break;
    case 19200 : BAUDRATE = B19200; break;
    case 38400 : BAUDRATE = B38400; break;
    case 57600 : BAUDRATE = B57600; break;
    default : BAUDRATE = B38400; break;
    }

    switch (_data_bits) {
    case 5 : DATABITS = CS5; break;
    case 6 : DATABITS = CS6; break;
    case 7 : DATABITS = CS7; break;
    case 8 : DATABITS = CS8; break;
    default : DATABITS = CS8; break;
    }

    switch (_stop_bits){
    case 1 : STOPBITS = 0; break;
    case 2 : STOPBITS = CSTOPB; break;
    default : STOPBITS = 0; break;
    }

    switch (_parity){
    case 0 : PARITY = 0; break; // none
    case 1 : PARITY = PARODD; break; // odd
    case 2 : PARITY = 0; break; // even ??
    default : PARITY = 0; break; // none
    }

    newtio.c_cflag = BAUDRATE | DATABITS | STOPBITS | PARITY | CREAD | CLOCAL | HUPCL;

    newtio.c_oflag &= ~OPOST; // raw output
    newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // raw input

    newtio.c_cc[VTIME] = 0; /* inter character timer unused */
    newtio.c_cc[VMIN] = 0; /* don't block read until some chars are received */

    cfsetospeed(&newtio, BAUDRATE);
    tcflush(_fd, TCIFLUSH);
    tcsetattr(_fd, TCSANOW, &newtio);
    memset_r(inbuffer, 0, MAXBUFIN+1);
    }
    catch(Exception &e){
    e.Process("TComPort::Open()");
    }
    catch( ... ){
    throw ;
    }
    }

    void TComPort::Close(void)
    {
    try{
    if (_fd>=0){
    tcflush(_fd, TCIFLUSH);
    tcsetattr(_fd, TCSANOW, &oldtio);
    if (!close(_fd)) { <<<<<<<<< here freezes ##############################
    if (errno) printerr("%s\n", strerror(errno)); //(errno==EINTR)||
    if ((errno==EBADF)||(errno==EIO)) throw Exception(ErrMsgs[ErrIdxCom+2]);
    }
    }
    }
    catch(Exception &e){
    e.Process("TComPort::Close()");
    }
    catch( ... ){
    throw ;
    }
    }

    int TComPort::Write(char* psOutput, int len=-1)
    {
    int iOut;
    try{
    if (_fd < 1) throw Exception(ErrMsgs[ErrIdxCom+3]);
    if (len<0) len=strlen_r(psOutput);
    iOut = write(_fd, psOutput, len);
    return iOut;
    }
    catch(Exception &e){
    e.Process("TComPort::Write(char* psOutput), int len");
    }
    catch( ... ){
    throw ;
    }
    return -1; // should never reach here
    }

    ============================================
    now the troublesome routine
    ============================================
    void ConfigGPS(fgl::FGControl *)
    {
    char tstr[255]="";
    wndMain->WindowText(240,140,tstr);
    OpenCom(GpsRecCom, GpsRecBaudCurrent, GpsRecDatabits, GpsRecStopbits, GpsRecParity); // also close port before opening if open
    _com = ComPort[GpsRecCom];

    switch (GpsRecType){
    case gps_R3:
    wndMain->WindowBox(240, 50, 400, 90, wndMain->GetPaper());
    snprintf(tstr,254,"%s %d.", messages2[language][18], GpsRecCom+1);
    wndMain->WindowText(240, 50,tstr);
    Init_R3();
    break;
    case gps_R16:
    wndMain->WindowBox(240, 50, 400, 90, wndMain->GetPaper());
    snprintf(tstr,254,"%s %d.",messages2[language][19], GpsRecCom+1);
    wndMain->WindowText(240, 50,tstr);
    Init_R16();
    break;
    }
    CloseCom(GpsRecCom); <<<<<<<<<<<<< here is the function that calls TComPort::Close() ##############################
    _com=NULL;
    }

    void Init_R3()
    {
    char CommandStr[255]="";
    int BinMode, i=0;

    //change to binary first and then send a binary message to set GPS receiver
    strncpy(CommandStr, "$PMCAG,000,6\r\n", 254);
    _com->Write(CommandStr, -1);

    BinMode=CheckData(100);

    do {
    BinMode=CheckData(100);
    i++;
    } while ((BinMode!=1)&&(i<3));

    if (BinMode==-1) { // error
    wndMain->WindowText(240, 70,messages2[language][12]);//"No data received from GPS receiver."
    }
    if (BinMode==0) { // still in text mode
    wndMain->WindowText(240, 70,messages2[language][14]);
    }


    //turning WAAS on/off
    if (GpsRecWaas) { // On
    memcpy(CommandStr, "\x01\x53\xAC\x15\x8F\xFA\xFA\x20\x0\x0\x0\x0\x0\x 0\x0\x0\x81\x0\x0\x0\x0\x0\x0\x0\x0\x39\x04", 27);
    } else { // Off
    memcpy(CommandStr, "\x01\x53\xAC\x15\x8F\xFA\xFA\x20\x0\x0\x0\x0\x0\x 0\x0\x0\x80\x0\x0\x0\x0\x0\x0\x0\x0\x38\x04", 27);
    }

    _com->Write(CommandStr, 27);

    BinMode=CheckData(100);

    //set mask angle to 0.0
    memcpy(CommandStr, "\x01\x51\xAE\x0C\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0 \x0\x0C\x01", 18);
    _com->Write(CommandStr, 18);
    BinMode=CheckData(100);

    switch (GpsRecBaud) {
    case 9600: // change to NMEA mode again Com1-9600
    memcpy(CommandStr, "\x01\x6E\x91\x01\x20\x21\x1", 7);
    break;
    case 19200: // change to NMEA mode again Com1-19200
    memcpy(CommandStr, "\x01\x6E\x91\x01\x40\x41\x1", 7);
    break;
    default: // change to NMEA mode again Com1-9600
    memcpy(CommandStr, "\x01\x6E\x91\x01\x20\x21\x1", 7);
    break;
    }

    i=0;
    do {
    _com->Write(CommandStr, 7);
    BinMode=CheckData(300);
    i++;
    } while ((BinMode)&&(i<3));

    if ((BinMode==1)&&(GpsRecBaudCurrent!=GpsRecBaud)) { // if still in binary, or the baud change successfully, but new baud rate!=old baud rate
    GpsRecBaudCurrent=GpsRecBaud;
    OpenCom(GpsRecCom, GpsRecBaudCurrent, GpsRecDatabits, GpsRecStopbits, GpsRecParity); // also close port before opening if open
    _com = ComPort[GpsRecCom];
    BinMode=CheckData(300);
    }

    if (BinMode==-1) { // error
    wndMain->WindowText(240, 70,messages2[language][12]);//"No data received from GPS receiver."
    }
    if (BinMode==1) { // still in binary mode
    wndMain->WindowText(240, 70,messages2[language][15]);//"Can not change to text mode for NMEA data commands."
    }

    // GpsRecRate Hz, GGa, VTG
    snprintf(CommandStr, 254, "$PMCAG,005,1,GGA,%03u,VTG,%03u\r\n", GpsRecRate, GpsRecRate);
    _com->Write(CommandStr, -1);
    CheckData(100);
    //5Hz GGA and VTG, save into memory
    strncpy(CommandStr, "$PMCAG,005,1,GGA,999,VTG,999\r\n", 254);
    //strncpy(CommandStr, "$PMCAG,005,0,GGA,001,VTG,001\r\n", 254);
    _com->Write(CommandStr, -1);
    CheckData(100);
    _com->Write(CommandStr, -1);
    CheckData(100);

    BinMode=CheckData(300);
    switch (BinMode){
    case 0:
    wndMain->WindowText(240, 90,messages2[language][16]); //"Configure successfuly"
    break;
    default:
    wndMain->WindowText(240, 90,messages2[language][17]);//"Configure failed"
    }
    }

    int CheckData(int ChkTime)
    {
    char* combuf;

    if (!_com) return -1; // error
    _com->FlushInBuffer();
    usleep(ChkTime*1000); // sleep ChkTime
    _com->Process();
    combuf=_com->InBuffer();

    if (!strlen_r(combuf)) return -1; // error
    if (strstr_r(combuf, "$GP")||strstr_r(combuf, "$PG")||strstr_r(combuf, "$PM"))
    return 0; // text
    else
    return 1; // binary
    }

    Hope I included all the relevant lines.
    Thanks again

  10. #9
    scm
    scm is offline
    Linux Engineer
    Join Date
    Feb 2005
    Posts
    1,044
    For convenience, could you post code between [ code ] tags to preserve indentation, please?

  11. #10
    Just Joined!
    Join Date
    Nov 2005
    Posts
    7
    open/close routines
    ============================================
    Code:
    void TComPort&#58;&#58;Open&#40;void&#41; 
    &#123; 
      char sPortName&#91;64&#93;; 
      tcflag_t BAUDRATE, DATABITS, STOPBITS, PARITY; 
     
      try&#123; 
        if &#40;_PortNumber<2&#41; &#123; 
          sprintf&#40;sPortName, "/dev/ttyS%d", _PortNumber&#41;; 
        &#125; else &#123; 
          sprintf&#40;sPortName, "/dev/ttyUSB%d", _PortNumber-2&#41;; 
        &#125; 
     
        Close&#40;&#41;; 
     
        _fd = open&#40;sPortName, O_RDWR | O_NOCTTY | O_NDELAY&#41;; 
        if &#40;_fd < 0&#41; throw Exception&#40;ErrMsgs&#91;ErrIdxCom+1&#93;&#41;; 
        fcntl&#40;_fd, F_SETFL, 0&#41;; 
     
        tcgetattr&#40;_fd, &oldtio&#41;; 
        tcgetattr&#40;_fd, &newtio&#41;; 
     
        tcflush&#40;_fd, TCIFLUSH&#41;; 
        switch &#40;_baud_rate&#41;&#123; 
        case 4800   &#58;  BAUDRATE = B4800;   break; 
        case 9600   &#58;  BAUDRATE = B9600;   break; 
        case 19200  &#58;  BAUDRATE = B19200;  break; 
        case 38400  &#58;  BAUDRATE = B38400;  break; 
        case 57600  &#58;  BAUDRATE = B57600;  break; 
        case 115200 &#58;  BAUDRATE = B115200; break; 
        default     &#58;  BAUDRATE = B38400;  break; 
        &#125; 
     
        switch &#40;_data_bits&#41; &#123; 
        case 5      &#58;  DATABITS = CS5;     break; 
        case 6      &#58;  DATABITS = CS6;     break; 
        case 7      &#58;  DATABITS = CS7;     break; 
        case 8      &#58;  DATABITS = CS8;     break; 
        default     &#58;  DATABITS = CS8;     break; 
        &#125; 
     
        switch &#40;_stop_bits&#41;&#123; 
        case 1      &#58;  STOPBITS = 0;      break; 
        case 2      &#58;  STOPBITS = CSTOPB; break; 
        default     &#58;  STOPBITS = 0;      break; 
        &#125; 
     
        switch &#40;_parity&#41;&#123; 
        case 0      &#58;  PARITY = 0;      break;  // none 
        case 1      &#58;  PARITY = PARODD; break;  // odd 
        case 2      &#58;  PARITY = 0;      break;  // even ?? 
        default     &#58;  PARITY = 0;      break;  // none 
        &#125; 
     
        newtio.c_cflag = BAUDRATE | DATABITS | STOPBITS | PARITY | CREAD | CLOCAL | HUPCL; 
     
        newtio.c_oflag &= ~OPOST; // raw output 
     
        // don't echo characters 
        newtio.c_lflag = 0; 
        newtio.c_lflag &= ~&#40;ICANON | ECHO | ECHOE | ISIG&#41;; // raw input 
     
        newtio.c_cc&#91;VTIME&#93; = 0; /* inter character timer unused */  
        newtio.c_cc&#91;VMIN&#93;  = 0; /* don't block read until some chars are received */         
     
        cfsetospeed&#40;&newtio, BAUDRATE&#41;; 
        tcflush&#40;_fd, TCIFLUSH&#41;; 
        tcsetattr&#40;_fd, TCSANOW, &newtio&#41;; 
        memset_r&#40;inbuffer, 0, MAXBUFIN+1&#41;; 
      &#125; 
      catch&#40;Exception &e&#41;&#123; 
        e.Process&#40;"TComPort&#58;&#58;Open&#40;&#41;"&#41;; 
      &#125; 
      catch&#40; ... &#41;&#123; 
        throw ; 
      &#125; 
    &#125;
    
    void TComPort&#58;&#58;Close&#40;void&#41; 
    &#123; 
      try&#123; 
        if &#40;_fd>=0&#41;&#123; 
        // restore the saved port attributes 
          tcflush&#40;_fd, TCIFLUSH&#41;; 
          tcsetattr&#40;_fd, TCSANOW, &oldtio&#41;;       
          if &#40;!close&#40;_fd&#41;&#41; &#123; 
    	if &#40;errno&#41; printerr&#40;"%s\n", strerror&#40;errno&#41;&#41;; //&#40;errno==EINTR&#41;|| 
    	if &#40;&#40;errno==EBADF&#41;||&#40;errno==EIO&#41;&#41; throw Exception&#40;ErrMsgs&#91;ErrIdxCom+2&#93;&#41;; 
          &#125; 
        &#125; 
      &#125; 
      catch&#40;Exception &e&#41;&#123; 
        e.Process&#40;"TComPort&#58;&#58;Close&#40;&#41;"&#41;; 
      &#125; 
      catch&#40; ... &#41;&#123; 
        throw ; 
      &#125; 
    &#125;
    
    int  TComPort&#58;&#58;Write&#40;char* psOutput, int len=-1&#41; 
    &#123;  
     int iOut; 
      try&#123; 
        if &#40;_fd < 1&#41; throw Exception&#40;ErrMsgs&#91;ErrIdxCom+3&#93;&#41;; 
        if &#40;len<0&#41; len=strlen_r&#40;psOutput&#41;; 
        iOut = write&#40;_fd, psOutput, len&#41;; 
     
        //if &#40;iOut < 0&#41; throw Exception&#40;ErrMsgs&#91;ErrIdxCom+4&#93;&#41;; 
        return iOut; 
      &#125;   
      catch&#40;Exception &e&#41;&#123; 
        e.Process&#40;"TComPort&#58;&#58;Write&#40;char* psOutput&#41;, int len"&#41;; 
      &#125; 
      catch&#40; ... &#41;&#123; 
        throw ; 
      &#125;    
      return -1; // should never reach here 
    &#125; 
    
    ============================================
    now the troublesome routine
    ============================================
    void ConfigGPS&#40;fgl&#58;&#58;FGControl *&#41; 
    &#123; 
      char tstr&#91;255&#93;=""; 
      wndMain->WindowText&#40;240,140,tstr&#41;; 
      OpenCom&#40;GpsRecCom, GpsRecBaudCurrent, GpsRecDatabits, GpsRecStopbits, GpsRecParity&#41;; // also close port before opening if open 
      _com = ComPort&#91;GpsRecCom&#93;; 
     
      switch &#40;GpsRecType&#41;&#123; 
      case gps_R3&#58; 
        wndMain->WindowBox&#40;240, 50, 400, 90, wndMain->GetPaper&#40;&#41;&#41;; 
        snprintf&#40;tstr,254,"%s %d.", messages2&#91;language&#93;&#91;18&#93;, GpsRecCom+1&#41;; 
        wndMain->WindowText&#40;240, 50,tstr&#41;; 
        Init_R3&#40;&#41;; 
        break; 
      case gps_R16&#58; 
        wndMain->WindowBox&#40;240, 50, 400, 90, wndMain->GetPaper&#40;&#41;&#41;; 
        snprintf&#40;tstr,254,"%s %d.",messages2&#91;language&#93;&#91;19&#93;, GpsRecCom+1&#41;;     
        wndMain->WindowText&#40;240, 50,tstr&#41;; 
        Init_R16&#40;&#41;; 
        break; 
      &#125; 
      CloseCom&#40;GpsRecCom&#41;; <<<<<<<<<<<<< here is the function that calls TComPort&#58;&#58;Close&#40;&#41; ##############################
      _com=NULL; 
    &#125; 
    
    
    // Init novatel receiver 
    void Init_R3&#40;&#41; 
    &#123; 
      char CommandStr&#91;255&#93;=""; 
      int BinMode, i=0; 
     
      //change to binary first and then send a binary message to set GPS receiver 
      strncpy&#40;CommandStr, "$PMCAG,000,6\r\n", 254&#41;; 
      _com->Write&#40;CommandStr, -1&#41;;   
     
      BinMode=CheckData&#40;100&#41;; 
     
      do &#123; 
        BinMode=CheckData&#40;100&#41;; 
        i++; 
      &#125; while &#40;&#40;BinMode!=1&#41;&&&#40;i<3&#41;&#41;; 
     
      if &#40;BinMode==-1&#41; &#123; // error 
        wndMain->WindowText&#40;240, 70,messages2&#91;language&#93;&#91;12&#93;&#41;;//"No data received from GPS receiver." 
      &#125; 
      if &#40;BinMode==0&#41; &#123; // still in text mode 
        wndMain->WindowText&#40;240, 70,messages2&#91;language&#93;&#91;14&#93;&#41;; 
      &#125; 
     
     
      //turning WAAS on/off 
      if &#40;GpsRecWaas&#41; &#123; // On 
        memcpy&#40;CommandStr, "\x01\x53\xAC\x15\x8F\xFA\xFA\x20\x0\x0\x0\x0\x0\x0\x0\x0\x81\x0\x0\x0\x0\x0\x0\x0\x0\x39\x04", 27&#41;; 
      &#125; else &#123;          // Off 
        memcpy&#40;CommandStr, "\x01\x53\xAC\x15\x8F\xFA\xFA\x20\x0\x0\x0\x0\x0\x0\x0\x0\x80\x0\x0\x0\x0\x0\x0\x0\x0\x38\x04", 27&#41;; 
      &#125; 
     
      _com->Write&#40;CommandStr, 27&#41;; 
     
      BinMode=CheckData&#40;100&#41;; 
     
      //set mask angle to 0.0 
      memcpy&#40;CommandStr, "\x01\x51\xAE\x0C\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0C\x01", 18&#41;; 
      _com->Write&#40;CommandStr, 18&#41;; 
      BinMode=CheckData&#40;100&#41;; 
     
      switch &#40;GpsRecBaud&#41; &#123; 
      case 9600&#58;  // change to NMEA mode again Com1-9600  
        memcpy&#40;CommandStr, "\x01\x6E\x91\x01\x20\x21\x1", 7&#41;; 
        break; 
      case 19200&#58; // change to NMEA mode again Com1-19200  
        memcpy&#40;CommandStr, "\x01\x6E\x91\x01\x40\x41\x1", 7&#41;; 
        break; 
      default&#58;    // change to NMEA mode again Com1-9600  
        memcpy&#40;CommandStr, "\x01\x6E\x91\x01\x20\x21\x1", 7&#41;; 
        break; 
      &#125; 
     
      i=0; 
      do &#123; 
        _com->Write&#40;CommandStr, 7&#41;; 
        BinMode=CheckData&#40;300&#41;; 
        i++; 
      &#125; while &#40;&#40;BinMode&#41;&&&#40;i<3&#41;&#41;; 
     
      if &#40;&#40;BinMode==1&#41;&&&#40;GpsRecBaudCurrent!=GpsRecBaud&#41;&#41; &#123; // if still in binary, or the baud change successfully, but new baud rate!=old baud rate 
        GpsRecBaudCurrent=GpsRecBaud; 
        OpenCom&#40;GpsRecCom, GpsRecBaudCurrent, GpsRecDatabits, GpsRecStopbits, GpsRecParity&#41;; // also close port before opening if open 
        _com = ComPort&#91;GpsRecCom&#93;;     
        BinMode=CheckData&#40;300&#41;; 
      &#125; 
     
      if &#40;BinMode==-1&#41; &#123; // error 
        wndMain->WindowText&#40;240, 70,messages2&#91;language&#93;&#91;12&#93;&#41;;//"No data received from GPS receiver." 
      &#125; 
      if &#40;BinMode==1&#41; &#123; // still in binary mode 
        wndMain->WindowText&#40;240, 70,messages2&#91;language&#93;&#91;15&#93;&#41;;//"Can not change to text mode for NMEA data commands." 
      &#125; 
     
      // GpsRecRate Hz, GGa, VTG 
      snprintf&#40;CommandStr, 254, "$PMCAG,005,1,GGA,%03u,VTG,%03u\r\n", GpsRecRate, GpsRecRate&#41;; 
      _com->Write&#40;CommandStr, -1&#41;; 
      CheckData&#40;100&#41;; 
      //5Hz GGA and VTG, save into memory  
      strncpy&#40;CommandStr, "$PMCAG,005,1,GGA,999,VTG,999\r\n", 254&#41;;   
      _com->Write&#40;CommandStr, -1&#41;; 
      CheckData&#40;100&#41;; 
      _com->Write&#40;CommandStr, -1&#41;; 
      CheckData&#40;100&#41;; 
     
      BinMode=CheckData&#40;300&#41;; 
      switch &#40;BinMode&#41;&#123; 
      case 0&#58; 
        wndMain->WindowText&#40;240, 90,messages2&#91;language&#93;&#91;16&#93;&#41;; //"Configure successfuly" 
        break; 
      default&#58; 
        wndMain->WindowText&#40;240, 90,messages2&#91;language&#93;&#91;17&#93;&#41;;//"Configure failed" 
      &#125;   
    &#125; 
    
    // check if receiver being in binary or text mode; ChkTime in milisecond 
    // result&#58; -1 error; 0-text mode 1-binary  
    int CheckData&#40;int ChkTime&#41; 
    &#123; 
      char* combuf; 
     
      if &#40;!_com&#41; return -1; // error 
      _com->FlushInBuffer&#40;&#41;; 
      usleep&#40;ChkTime*1000&#41;; // sleep ChkTime 
      _com->Process&#40;&#41;; 
      combuf=_com->InBuffer&#40;&#41;; 
     
      if &#40;!strlen_r&#40;combuf&#41;&#41; return -1; // error 
      if &#40;strstr_r&#40;combuf, "$GP"&#41;||strstr_r&#40;combuf, "$PG"&#41;||strstr_r&#40;combuf, "$PM"&#41;&#41;  
        return 0;  // text 
      else  
        return 1; // binary 
    &#125;
    Hope I included all the relevant lines.
    Thanks again

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •