1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Simple+Easy C++ Serial code (linux)

Discussion in 'HTML, Graphics & Programming' started by D.P., 5 Feb 2010.

  1. D.P.

    Caporegime

    Joined: 18 Oct 2002

    Posts: 31,501

    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.
        // ..........
     
     
  2. D.P.

    Caporegime

    Joined: 18 Oct 2002

    Posts: 31,501

    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: 5 Feb 2010
  3. Ladforce

    Hitman

    Joined: 17 Feb 2006

    Posts: 898

    Location: Fleet

    Your buffer ptr does not point to a buffer which has had memory allocated for it.

    Buffer should be something like "char buffer[255]"
     
  4. D.P.

    Caporegime

    Joined: 18 Oct 2002

    Posts: 31,501

    Thanks, thats true.

    I've been through the code again and it looks ok.
     
  5. Ladforce

    Hitman

    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?
     
  6. D.P.

    Caporegime

    Joined: 18 Oct 2002

    Posts: 31,501

    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.
     
  7. D.P.

    Caporegime

    Joined: 18 Oct 2002

    Posts: 31,501

    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.