linux serial communication reading information

Posted by mb81 on Sun, 08 Dec 2019 05:25:13 +0100

In these two days, we need to do a serial communication to receive the information transmitted from peripheral devices. Many programs on the Internet are more complex. We have written a simple and easy program. The main process is: open serial port - > initialization - > circular reading.
The code is as follows:

#include <iostream>   
/*Serial port related header file*/
#Include < stdio. H > / * standard I / O definition*/
#Include < stdlib. H > / * standard function library definition*/
#Include < unistd. H > / * UNIX standard function definition*/
#include<sys/types.h> 
#include<sys/stat.h>   
#Include < fcntl. H > / * file control definition*/
#Include < termios. H > / * definition of ppsix terminal control*/
#Include < errno. H > / * error number definition*/
#include<string.h>
     
     
#define DEV_NAME  "/dev/ttyUSB0"
#define FALSE  -1
#define TRUE   0

     
int UART0_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)    
{    
       
    int   i;    
    int   status;    
    int   speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300};    
    int   name_arr[] = {115200,  19200,  9600,  4800,  2400,  1200,  300};    
             
    struct termios options;    
       
    /*  tcgetattr(fd,&options)Get the parameters related to the object fd points to, and save them in options, which can also test whether the configuration is correct,
        Whether the serial port is available, etc. If the call succeeds, the function return value is 0. If the call fails, the function return value is 1  */    
    if( tcgetattr( fd,&options)  !=  0)    
    {    
        perror("SetupSerial 1");        
        return(FALSE);     
    }    
      
    //Set input baud rate and output baud rate of serial port    
    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)    
    {    
        if  (speed == name_arr[i])    
        {                 
            cfsetispeed(&options, speed_arr[i]);     
            cfsetospeed(&options, speed_arr[i]);      
        }    
    }         
       
    //Modify the control mode to ensure that the program does not occupy the serial port    
    options.c_cflag |= CLOCAL;    
    //Modify the control mode so that the input data can be read from the serial port    
    options.c_cflag |= CREAD;    
      
    //Set data flow control    
    switch(flow_ctrl)    
    {    
          
        case 0 ://Do not use flow control    
              options.c_cflag &= ~CRTSCTS;    
              break;       
          
        case 1 ://Using hardware flow control    
              options.c_cflag |= CRTSCTS;    
              break;    
        case 2 ://Using software flow control    
              options.c_cflag |= IXON | IXOFF | IXANY;    
              break;    
    }    
    //set data bit    
    //Shield other flag bits    
    options.c_cflag &= ~CSIZE;    
    switch (databits)    
    {      
        case 5    :    
                     options.c_cflag |= CS5;    
                     break;    
        case 6    :    
                     options.c_cflag |= CS6;    
                     break;    
        case 7    :        
                 options.c_cflag |= CS7;    
                 break;    
        case 8:        
                 options.c_cflag |= CS8;    
                 break;      
        default:       
                 fprintf(stderr,"Unsupported data size\n");    
                 return (FALSE);     
    }    
    //Set check bit    
    switch (parity)    
    {      
        case 'n':    
        case 'N': //No parity bit.    
                 options.c_cflag &= ~PARENB;     
                 options.c_iflag &= ~INPCK;        
                 break;     
        case 'o':      
        case 'O'://Set to odd check        
                 options.c_cflag |= (PARODD | PARENB);     
                 options.c_iflag |= INPCK;                 
                 break;     
        case 'e':     
        case 'E'://Set to even check      
                 options.c_cflag |= PARENB;           
                 options.c_cflag &= ~PARODD;           
                 options.c_iflag |= INPCK;          
                 break;    
        case 's':    
        case 'S': //Set to space     
                 options.c_cflag &= ~PARENB;    
                 options.c_cflag &= ~CSTOPB;    
                 break;     
        default:      
                 fprintf(stderr,"Unsupported parity\n");        
                 return (FALSE);     
    }     
    // Set stop bit     
    switch (stopbits)    
    {      
        case 1:       
                 options.c_cflag &= ~CSTOPB; break;     
        case 2:       
                 options.c_cflag |= CSTOPB; break;    
        default:       
                       fprintf(stderr,"Unsupported stop bits\n");     
                       return (FALSE);    
    }    
       
    //Modify output mode, original data output    
    options.c_oflag &= ~OPOST;    
      
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);    
    //options.c_lflag &= ~(ISIG | ICANON);    
       
    //Set wait time and minimum receive characters    
    options.c_cc[VTIME] = 1; /* Read a character and wait for 1*(1/10)s */      
    options.c_cc[VMIN] = 1; /* The minimum number of characters to read is 1 */    
       
    //In case of data overflow, receive the data, but do not read and refresh the received data    
    tcflush(fd,TCIFLUSH);    
       
    //Activate the configuration (set the modified termios data to the serial port)    
    if (tcsetattr(fd,TCSANOW,&options) != 0)      
    {    
        perror("com set error!\n");      
        return (FALSE);     
    }    
    return (TRUE);     
}    
/*******************************************************************  
*Name: UART0? Init()  
*Function: serial port initialization  
*Entry parameter: fd file descriptor    
*                      speed      Serial port speed  
*                      flow_ctrl  Data flow control  
*                      databits   Data bit value is 7 or 8  
*                      stopbits   Stop bit value is 1 or 2  
*                      parity     Validity type value is n, e, O, s  
*                        
*Exit parameter: correct return is 1, error return is 0  
*******************************************************************/    
  
int UART0_Init(int fd, int speed,int flow_ctrl,int databits,int stopbits,int parity)    
{    
    int err;    
    //Format serial data frame    
    if (UART0_Set(fd,115200,0,8,1,'N') == FALSE)    
    {                                                             
        return FALSE;    
    }    
    else    
    {    
        return  TRUE;    
    }    
}    

int decode_distance(unsigned char *rcv_buf){
  int distance;
  distance = (int) rcv_buf[2] + (int) rcv_buf[3]*256;
  return distance;
}

int decode_strength(unsigned char rcv_buf[8]){
  int strength;
  strength = (int) rcv_buf[4] + (int) rcv_buf[5]*256;
  return strength;
}

int decode_sigment(unsigned char rcv_buf[8]){
  int sigment;
  sigment = (int) rcv_buf[6];
  if(sigment == 7||sigment == 8)
  {
    return 1;
  }else{
    return 0;
  }
}

using namespace std;
     
int main(int argc, char **argv)
{
    int fd;                            //File descriptor
    int len;                        
    int i;
    int err;                           //Returns the status of the calling function
    int distance;
    int strength;
    int sigment;
    unsigned char rcv_buf[1024];       
	
    fd = open( DEV_NAME, O_RDWR|O_NOCTTY|O_NDELAY);
    //O rdonly read only. O'wronlywrite on only. O? Rdwr read / write is on. O append is added to the end of the file every time it is written. O'creat create this file if it does not exist.
    //std::cout<<fd<<std::endl;
	
    if(fd < 0) {
      std::cout<<"Error opening"<<std::endl;
      return -1;
    }

    do  
    {    
      err = UART0_Init(fd,115200,0,8,1,'N');    
      printf("Set Port Exactly!\n"); 
      sleep(1);   
    }while(FALSE == err || FALSE == fd);

    while (1) //Loop read data
    {
      len = read(fd, rcv_buf , 9);
      cout << len << endl;
      sleep(2);
      if (len < 0) 
      {
        std::cout<<"Read error "<<std::endl;
        return -1;
      }
      
      distance = decode_distance(rcv_buf);
      cout<<"distance: "<<distance<<endl;
      strength = decode_strength(rcv_buf);
      sigment = decode_sigment(rcv_buf);
      
      cout<<"The signal strength is:"<< strength << endl;
      
      if(sigment==1){
	cout<<"Trusted data"<< endl;
      }else{
	cout<<"Data not trusted"<< endl;
      }
      
//       cout<<rcv_buf<<endl;
//       int a =(int)rcv_buf[0];
//       cout<<a<<endl;
//       int b = (int)rcv_buf[1];
//       cout<<b<<endl;
//       for(int i =0;i < 9; i++)
//       {
// 	rcv_buf[i] = 0;
//       }
//       
// 
//       a =(int)rcv_buf[2];
//       cout<<a<<endl;
//       b = (int)rcv_buf[3];
//       cout<<b<<endl;
    }
    
    return 0;
}

Be careful:
1. When opening the serial port, you need to use super permission to implement, so you can

sudo kdevelop

After entering the compiler for operation or directly cmake or make

chmod 777 ./new_port
sudo ./new_port

2. In the process of use, when my buffer array RCV buf is small, the result of the implementation is not updated, and there is a failure, so it is recommended that the general RCV buf take a larger value.

3. For data decoding, I decode the data according to the specific situation of the peripheral I use. Let's also analyze the specific situation.

Topics: sudo Unix cmake