Simple+Easy C++ Serial code (linux)

Caporegime
Joined
18 Oct 2002
Posts
32,615
I have a windows VBasic (gasp!) program that I need to port to C++ within a linux environment. All I need help with is the Serial communication.


I have a device which constantly spits out a long string of bytes which I need to read. I also need to send the device a string of bytes.
This is done through a USB-to-serial converter to an XBEE wireless serial interface. The fact that it is wireless serial shouldn't matter, the VBasic code is very transparent.


I cannot for he life of me find any reasonable example code, tutorial, human readable help file, etc., that helps me develop very simple C++ serial communication code that works under linux. I don't want VisualStudio C++ windows only stuff. Just pure simple GNU C code.

The Visual Basic code is this:
Code:
'///////////////////////
' ENABLE BUTTON COM PORT
'///////////////////////
Private Sub Enable_Click()

' SET ERROR INTERRUPT
On Error GoTo ErrorMess1

' SET BAUDRATE
MSComm1.Settings = "57600,N,8,1"

' Flow control?
If FlowControl.Value = 1 Then

    MSComm1.RTSEnable = True
    MSComm1.Handshaking = comRTS

Else

    MSComm1.RTSEnable = False
    MSComm1.Handshaking = comNone

End If


' ENABLE PORT
MSComm1.PortOpen = True

' CLEAR DISABLE OPTION
Disable.Value = False

' LOCK PORT CHANGE
PortCombo.Locked = True


GoTo finish

' ERROR MESSAGE ROUTINE
ErrorMess1:
MsgBox "Please select an available port      ", vbExclamation, "      PORT IS UNAVAILABLE!"
Disable.Value = True

finish:
End Sub




'///////////////////////
' RECEIVE BYTE FROM PORT
'///////////////////////
Private Function RXBYTE()

On Error GoTo error

RXDATA = DataIN(Index)
                
Index = Index + 1

error:
End Function



'//////////////////////////////
'RS-232 MESSAGE RECEIVE HANDLER
'//////////////////////////////
Private Sub MSComm1_OnComm()

Dim i As Integer
Dim DataSave(100) As Byte
Dim CHECKSUM, CHECKSUM_RX As Long

' ERROR CONTROL
'On Error GoTo finish

' RECEIVE MESSAGE HANDLER
If MSComm1.CommEvent = comEvReceive Then

    ' Read data
    DataIN = StrConv(MSComm1.Input, vbFromUnicode)
    
    Index = 0
       
' CONTINUE IF WRONG CHARACTER RX
CONTINUE:

    ' READ BYTE
    Call RXBYTE
    
    ' Header
    If RXDATA = 170 Then
            
        ' READ BYTE
        Call RXBYTE
        
        ' Header
        If RXDATA = 85 Then
            
            ' Read in Data
            For i = 1 To 70
                       
                ' READ BYTE
                Call RXBYTE
                
                CHECKSUM = CHECKSUM + RXDATA
                
                ' Save Data
                DataSave(i) = RXDATA
                
            Next i
               
            ' READ BYTE
            Call RXBYTE
               
            ' End
            If RXDATA = 255 Then
            
                ' READ BYTE
                Call RXBYTE
                        
                ' End
                If RXDATA = 13 Then
                          
                    ' READ BYTE
                    Call RXBYTE
                    
                    ' Rx Checksum
                    CHECKSUM_RX = CLng(RXDATA) * 256
                    
                    ' READ BYTE
                    Call RXBYTE
                    
                    CHECKSUM_RX = CHECKSUM_RX + RXDATA
                    
                    ' Checksum is valid
                    If CHECKSUM = CHECKSUM_RX Then

     // do some data conversion from bytes to ints etc.
    // ..........
 
Caporegime
OP
Joined
18 Oct 2002
Posts
32,615
I have this C++ code:

Code:
 int fd; /* File descriptor for the port */

 /*  * 'open_port()' - Open serial port 1.
     *
     * Returns the file descriptor on success or -1 on error.
     */
int    open_port(void)
{
   printf("Trying to open port\n");

      fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
      if (fd == -1)
      {
       /*
	* Could not open the port.
	*/
	perror("open_port: Unable to open /dev/ttyUSB0 - ");
      }
      else
      {
	fcntl(fd, F_SETFL, 0);
        printf("I opened the port /dev/ttyUSB0  !\n");

        struct termios options;

       /*
       * Get the current options for the port...
       */
       tcgetattr(fd, &options);

     /*
     * Set the baud rates to 57600 ..
     */
    cfsetispeed(&options, B57600);
    cfsetospeed(&options, B57600);

     /*
     * Enable the receiver and set local mode...
     */
    options.c_cflag |= (CLOCAL | CREAD);

     // 8N1
     options.c_cflag &= ~PARENB;
     options.c_cflag &= ~CSTOPB;
     options.c_cflag &= ~CSIZE; /* Mask the character size bits */
     options.c_cflag |= CS8;    /* Select 8 data bits */


      // Do the following to enable hardware flow control:
     //    options.c_cflag |= CNEW_RTSCTS;    /* Also called RTSCTS /

     //Similarly, to disable hardware flow control:
    //options.c_cflag &= ~CNEW_RTSCTS;


     /*
     * Set the new options for the port...
     */
    tcsetattr(fd, TCSANOW, &options);


      }
      return (fd);
}



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

   open_port();
   int n = write(fd, "ATZ\r", 4);
   if (n < 0)   fputs("write() of 4 bytes failed!\n", stderr);

   printf("Wrote \%i bytes\n",n);

    char *buffer;
   //fcntl(fd, F_SETFL, FNDELAY);
   int recieved =   read( fd, buffer, 5);
 printf("recieved \%i bytes\n",recieved);
     close(fd);

     return EXIT_SUCCESS;
}

If the serial device is not in then errros are reported, which is good. The writing works without error but I cannot check.

But when I try to read data I don't receive anything. Actually, the whole reading part is a mystery to me.
 
Last edited:
Associate
Joined
17 Feb 2006
Posts
898
Location
Fleet
So your code, with the buffer change, just waits at the read() line and never progresses? Are you certain something on the other end is writing at least 5 bytes of data down the line?
 
Caporegime
OP
Joined
18 Oct 2002
Posts
32,615
I have something to check the hardware device is actually transmitting (will boot a 2nd PC and usb-to-serial-to-xbee using the windows visual basic program I know works, and can read form the linux PC). So will report back in an hour or so.
 
Caporegime
OP
Joined
18 Oct 2002
Posts
32,615
I have something to check the hardware device is actually transmitting (will boot a 2nd PC and usb-to-serial-to-xbee using the windows visual basic program I know works, and can read form the linux PC). So will report back in an hour or so.
 
Back
Top Bottom