Simple+Easy C++ Serial code (linux)

Caporegime
Joined
18 Oct 2002
Posts
32,733
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.
    // ..........
 
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:
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.
 
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