linux 串口 拼帧处理
串口每次read数据可能不是完整的数据,参照网上的代码,写了拼帧的代码#include <stdio.h>
#include <termios.h> #include <unistd.h> #include <fcntl.h> #include <strings.h> #include <sys/time.h> #include <sys/types.h> int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300}; int name_arr[] = { 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300}; /** *@brief Set Serial Port BitRate *@param fd Type : int The File Description of Serial Port *@param speed Type : int Serial Speed *@return void */ void set_speed(int fd, int speed) { int i; int status; struct termios Opt; tcgetattr(fd, &Opt); for( i=0; i < (sizeof(speed_arr) / sizeof(int)); i++ ) { if (speed == name_arr[i]) { tcflush(fd, TCIOFLUSH); cfsetispeed(&Opt, speed_arr[i]); cfsetospeed(&Opt, speed_arr[i]); status = tcsetattr(fd, TCSANOW, &Opt); if (status != 0) { perror("tcsetattr fd"); return; } tcflush(fd,TCIOFLUSH); } } } /** *@brief Set Serial Port Databits, Stopbits and Parity. *@param fd Type: int The File Description of Serial Port *@param databits Type: int Databits 7 or 8 *@param stopbits Type: int Stopbits 1 or 2 *@param parity Type: int Parity Type: n,N,e,E,o,O,s,S */ int set_Parity(int fd, int databits, int parity, int stopbits) { struct termios options; if ( tcgetattr( fd,&options) != 0) { perror("SetupSerial 1"); return(-1); } options.c_cflag &= ~CSIZE; switch (databits) /*Set Datebits*/ { case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr,"Unsupported data size\n"); return(-1); } switch (parity) /*Set Parity*/ { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); /* Odd Checking*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; /* Even Checking*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'S': case 's': /*as no parity*/ options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: fprintf(stderr,"Unsupported parity\n"); return(-1); } switch (stopbits) /*Set Stobits*/ { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr,"Unsupported stop bits\n"); return(-1); } /* Set input parity option */ if (parity != 'n') options.c_iflag |= INPCK; /*以下两句添加后发送方可以不加回车换行,但是read读取不完整*/ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ options.c_oflag &= ~OPOST; /*Output*/ //屏蔽功能: NL(换行)->CR(回车)、CR->NL、忽略输入回车 options.c_iflag &= ~(INLCR | ICRNL | IGNCR); options.c_oflag &= ~(ONLCR | OCRNL); tcflush(fd,TCIFLUSH); //未设置O_NONBLOCK或O_NDELAY options.c_cc[VTIME] = 150; /* Timeout in 15 seconds*/ options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(fd,TCSANOW,&options) != 0) { perror("SetupSerial 3"); return(-1); } return(0); } void print_frame(unsigned char *buf,int size) { int i; for(i = 0; i < size; i++) { printf("0x%x ", buf[i]); } printf("\n"); } void getCompleteFrame(unsigned char *inBuf,int inCnt,unsigned char *outBuf,int *destCnt,int *readStatus) { int i; for(i = 0; i < inCnt; i++) { if(inBuf[i] == 0x01 && inBuf[i+1] == 0x03)//header { outBuf[(*destCnt)++] = inBuf[i]; *readStatus = 1; continue; } if(*readStatus == 1)//body { outBuf[(*destCnt)++] = inBuf[i]; } if(*destCnt == outBuf[2] && *readStatus == 1)//tail { print_frame(outBuf,*destCnt); *readStatus = 0; *destCnt = 0; memset(outBuf, -1, sizeof(outBuf)); // memset(inBuf,0,sizeof(inBuf)); continue; } } } int main(void) { unsigned char battery_msg[512]; int fd; unsigned char read_buf[512] = {0}; int nread = 0; fd = open("/dev/ttyS0", O_RDWR|O_NOCTTY); if (fd > 0) { printf("Open Port Success!\n"); } else { printf("Can't Open port\n"); return(-1); } set_speed(fd, 115200); if(set_Parity(fd, 8, 'N', 1) == -1) { close(fd); return(-1); } int i = 0, rc = 0; int flag = 0; fd_set rset; struct timeval tv; int read_status = 0; int dest_cnt = 0; while (1) //循环读取数据 { FD_ZERO(&rset); FD_SET(fd, &rset); tv.tv_sec = 5; tv.tv_usec = 0; rc = select(fd+1, &rset, NULL, NULL, &tv); if(rc > 0) {
if(FD_ISSET(fd_485C2, &rset))
{
memset(read_buf, 0, sizeof(read_buf)); usleep(100); nread = read(fd, read_buf, sizeof(read_buf)); // printf("read %d data\n", nread); if(nread > 0) { getCompleteFrame(read_buf, nread, battery_msg,&dest_cnt,&read_status); }
} } } close(fd); return 0; }
Talk is cheap, show me the code