使用C / C ++从Linux中的串口读取

时间:2016-07-28 05:43:54

标签: c++ linux serial-port raspberry-pi raspberry-pi3

我正在尝试从其他设备发送的串口读取数据。 在我的串口接收部分,我使用信号处理程序读取读取缓冲区中的数据。 它可以工作,但是对于相同的数据有一些触发器,有时它会停止工作。 我的接收计划是

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <iostream>
#include <strings.h>
#include <stdlib.h> 
#include <sys/signal.h>
#include <sys/ioctl.h>
using namespace std;
/* baudrate settings are defined in <asm/termbits.h>, which is
included by <termios.h> */
#define BAUDRATE B9600            
/* change this definition for the correct port */
#define MODEMDEVICE "/dev/ttyS0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */

#define FALSE 0
#define TRUE 1
int fd;
int res;
char buf[255];
volatile int STOP=FALSE; 
void signal_handler_IO (int status);   /* definition of signal handler */
main()
{

      struct termios oldtio,newtio;
          struct sigaction saio;

    /* 
      Open modem device for reading and writing and not as controlling tty
      because we don't want to get killed if linenoise sends CTRL-C.
    */
     fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
     if (fd <0) {perror(MODEMDEVICE); exit(-1); }

     tcgetattr(fd,&oldtio); /* save current serial port settings */
     bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */

    /* 
      BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
      CRTSCTS : output hardware flow control (only used if the cable has
            all necessary lines. See sect. 7 of Serial-HOWTO)
      CS8     : 8n1 (8bit,no parity,1 stopbit)
      CLOCAL  : local connection, no modem contol
      CREAD   : enable receiving characters
    */
     newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

    /*
      IGNPAR  : ignore bytes with parity errors
      ICRNL   : map CR to NL (otherwise a CR input on the other computer
            will not terminate input)
      otherwise make device raw (no other input processing)
    */
     newtio.c_iflag = IGNPAR | ICRNL;

    /*
     Raw output.
    */
     newtio.c_oflag = 0;

    /*
      ICANON  : enable canonical input
      disable all echo functionality, and don't send signals to calling program
    */
     newtio.c_lflag = ICANON;
     /*set signal*/
         saio.sa_handler = signal_handler_IO;
         saio.sa_flags = 0;
         saio.sa_restorer = NULL; 
         sigaction(SIGIO,&saio,NULL);

         fcntl(fd, F_SETFL, FNDELAY|FASYNC);
         fcntl(fd, F_SETOWN, getpid());

    /* 
      initialize all control characters 
      default values can be found in /usr/include/termios.h, and are given
      in the comments, but we don't need them here
    */
     newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
     newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
     newtio.c_cc[VERASE]   = 0;     /* del */
     newtio.c_cc[VKILL]    = 0;     /* @ */
     newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
     newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
     newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
     newtio.c_cc[VSWTC]    = 0;     /* '\0' */
     newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
     newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
     newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
     newtio.c_cc[VEOL]     = 0;     /* '\0' */
     newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
     newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
     newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
     newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
     newtio.c_cc[VEOL2]    = 0;     /* '\0' */

    /* 
      now clean the modem line and activate the settings for the port
    */
     tcflush(fd, TCIFLUSH);
     tcsetattr(fd,TCSANOW,&newtio);
         ioctl(fd, TCIFLUSH, 0);
          ioctl(fd, TCIFLUSH, 1);
    /*
      terminal settings done, now handle input
      In this example, inputting a 'z' at the beginning of a line will 
      exit the program.
    */
     while (STOP==FALSE) {                         

     }
     /* restore the old port settings */
     tcsetattr(fd,TCSANOW,&oldtio);
}

void signal_handler_IO (int status)
{           

        res = read(fd,buf,255); 
        buf[res]=0;             /* set end of string, so we can printf */
        printf("%s\n", buf);
            ioctl(fd, TCIFLUSH, 0);

}

对于此测试,我在Raspberry PI中进行了测试,并使用USB-SERIAL适配器从USB端口发送数据。我用Python发送数据的模拟程序是

#!/usr/bin/env python
import time
import serial
ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate = 9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=1
)
counter=0
while 1:
  ser.write('Write counter: %d \n'%(counter))
  time.sleep(1)
  counter += 1

有效。但它会触发一些数据

root@raspberrypi:/home/pi/Softwares/SerialPortTest/build# ./SerialPortTest 
Write counter: 3 

Write counter: 4 

Write counter: 5 

Write counter: 5 

Write counter: 5 

Write counter: 5 

Write counter: 5 

Write counter: 5 

Write counter: 5 

Write counter: 5 

Write counter: 8 

Write counter: 9 

Write counter: 10 

Write counter: 11 

Write counter: 11 

Write counter: 11 

Write counter: 11 

^C
root@raspberrypi:/home/pi/Softwares/SerialPortTest/build# ./SerialPortTest 


Write counter: 23 

Write counter: 24 

Write counter: 24 

Write counter: 24 

Write counter: 24 

Write counter: 24 

在描述发生的事情时,它为Write counter: 5触发了几次,然后程序停在Write counter: 11。我停止了程序并再次运行。然后有时,我失去了Write counter: 6 and Write counter: 7。我该如何解决这个问题呢?

0 个答案:

没有答案