要说最好用的是select的形式,防止漏掉发送过来的数据,缺点是需要单开一条线程独立出来串口服务用来接收数据 一般比较大的工程里还是结合着libevent来用吧。 一般形式
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int set_serial(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
struct termios newttys1,oldttys1;
/*保存原有串口配置*/
if(tcgetattr(fd,&oldttys1)!=0)
{
perror("Setupserial 1");
return -1;
}
bzero(&newttys1,sizeof(newttys1));
newttys1.c_cflag|=(CLOCAL|CREAD ); /*CREAD 开启串行数据接收,CLOCAL并打开本地连接模式*/
newttys1.c_cflag &=~CSIZE;/*设置数据位*/
/*数据位选择*/
switch(nBits)
{
case 7:
newttys1.c_cflag |=CS7;
break;
case 8:
newttys1.c_cflag |=CS8;
break;
}
/*设置奇偶校验位*/
switch( nEvent )
{
case '0': /*奇校验*/
newttys1.c_cflag |= PARENB;/*开启奇偶校验*/
newttys1.c_iflag |= (INPCK | ISTRIP);/*INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特 */
newttys1.c_cflag |= PARODD;/*启用奇校验(默认为偶校验)*/
break;
case 'E':/*偶校验*/
newttys1.c_cflag |= PARENB; /*开启奇偶校验 */
newttys1.c_iflag |= ( INPCK | ISTRIP);/*打开输入奇偶校验并去除字符第八个比特*/
newttys1.c_cflag &= ~PARODD;/*启用偶校验*/
break;
case 'N': /*无奇偶校验*/
newttys1.c_cflag &= ~PARENB;
break;
}
/*设置波特率*/
switch( nSpeed )
{
case 2400:
cfsetispeed(&newttys1, B2400);
cfsetospeed(&newttys1, B2400);
break;
case 4800:
cfsetispeed(&newttys1, B4800);
cfsetospeed(&newttys1, B4800);
break;
case 9600:
cfsetispeed(&newttys1, B9600);
cfsetospeed(&newttys1, B9600);
break;
case 115200:
cfsetispeed(&newttys1, B115200);
cfsetospeed(&newttys1, B115200);
break;
default:
cfsetispeed(&newttys1, B9600);
cfsetospeed(&newttys1, B9600);
break;
}
/*设置停止位*/
if( nStop == 1)/*设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB*/
{
newttys1.c_cflag &= ~CSTOPB;/*默认为一位停止位; */
}
else if( nStop == 2)
{
newttys1.c_cflag |= CSTOPB;/*CSTOPB表示送两位停止位*/
}
/*设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时*/
newttys1.c_cc[VTIME] = 0;/*非规范模式读取时的超时时间;*/
newttys1.c_cc[VMIN] = 0; /*非规范模式读取时的最小字符数*/
tcflush(fd ,TCIFLUSH);/*tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */
/*激活配置使其生效*/
if((tcsetattr( fd, TCSANOW,&newttys1))!=0)
{
perror("com set error");
return -1;
}
return 0;
}
SINGAL信号形式
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/signal.h>
#include<fcntl.h>
#include<termios.h>
#include<errno.h>
#include <cstring>
#define FALSE -1
#define TRUE 0
#define flag 1
#define noflag 0
int wait_flag = noflag;
int STOP = 0;
int res;
int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300,};
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300,};
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 fd1");
return;
}
tcflush(fd, TCIOFLUSH);
}
}
}
int set_Parity(int fd, int databits, int stopbits, int parity) {
struct termios options;
if (tcgetattr(fd, &options) != 0) {
perror("SetupSerial 1");
return (FALSE);
}
options.c_cflag &= ~CSIZE;
switch (databits) {
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr, "Unsupported data size\n");
return (FALSE);
}
switch (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);
options.c_iflag |= INPCK; /* Disnable parity checking */ break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD;
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 (FALSE);
}
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);
} /* Set input parity option */ if (parity != 'n') options.c_iflag |= INPCK;
tcflush(fd, TCIFLUSH);
options.c_cc[VTIME] = 150;
options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(fd, TCSANOW, &options) != 0) {
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
void signal_handler_IO(int status) {
printf("received SIGIO signale.\n");
wait_flag = noflag;
}
int main() {
printf("This program updates last time at %s %s\n", __TIME__, __DATE__);
printf("STDIO COM1\n");
int fd;
struct sigaction saio;
fd = open("/dev/ttyUSB0", O_RDWR);
if (fd == -1) { perror("serialport error\n"); }
else {
printf("open ");
printf("%s", ttyname(fd));
printf(" succesfully\n");
}
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask);
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO, &saio,
NULL); //allow the process to receive SIGIO
fcntl(fd, F_SETOWN,
getpid()); //make the file descriptor asynchronous
fcntl(fd, F_SETFL, FASYNC);
set_speed(fd, 9600);
if (set_Parity(fd, 8, 1, 'N') == FALSE) {
printf("Set Parity Error\n");
exit(0);
}
char buf[254]={0};
while (STOP == 0) {
usleep(100000); /* after receving SIGIO ,wait_flag = FALSE,input is availabe and can be read */
if (wait_flag == 0) {
memset(buf, 0, sizeof(buf));
res = read(fd, buf, 254);
if ((int) buf[0] == 85) {
for (int i = 0; i < 254; i++) {
std::cout << std::hex << (int) buf[i] << " ";
}
std::cout << std::endl;
}
// printf("nread=%d,%s\n", res,buf);
// if (res ==1)
// STOP = 1; /*stop loop if only a CR was input */
wait_flag = flag; /*wait for new input */
}
}
close(fd);
return 0;
}
select阻塞形式
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/signal.h>
#include<fcntl.h>
#include<termios.h>
#include<errno.h>
#include <cstring>
#include <vector>
#define FALSE -1
#define TRUE 0
#define flag 1
#define noflag 0
int wait_flag = noflag;
int STOP = 0;
int res;
int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300,};
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300,};
struct STime stcTime;
struct SAcc stcAcc;
struct SGyro stcGyro;
struct SAngle stcAngle;
struct SMag stcMag;
struct SDStatus stcDStatus;
struct SPress stcPress;
struct SLonLat stcLonLat;
struct SGPSV stcGPSV;
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 fd1");
return;
}
tcflush(fd, TCIOFLUSH);
}
}
}
int set_Parity(int fd, int databits, int stopbits, int parity) {
struct termios options;
if (tcgetattr(fd, &options) != 0) {
perror("SetupSerial 1");
return (FALSE);
}
options.c_cflag &= ~CSIZE;
switch (databits) {
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr, "Unsupported data size\n");
return (FALSE);
}
switch (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);
options.c_iflag |= INPCK; /* Disnable parity checking */ break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD;
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 (FALSE);
}
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);
} /* Set input parity option */
if (parity != 'n') options.c_iflag |= INPCK;
tcflush(fd, TCIFLUSH);
options.c_cc[VTIME] = 150;
options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(fd, TCSANOW, &options) != 0) {
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
void signal_handler_IO(int status) {
printf("received SIGIO signale.\n");
wait_flag = noflag;
}
class DATA {
DATA(char type) {
}
};
int main() {
std::vector<DATA> info;
printf("This program updates last time at %s %s\n", __TIME__, __DATE__);
printf("STDIO COM1\n");
int fd;
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) { perror("serialport error\n"); }
else {
printf("open ");
printf("%s", ttyname(fd));
printf(" succesfully\n");
}
set_speed(fd, 9600);
if (set_Parity(fd, 8, 1, 'N') == FALSE) {
printf("Set Parity Error\n");
exit(0);
}
char buf;
fd_set rd;
int nread = 0;
// char buffer[5] = {char(0xff), char(0xaa), char(0x03), char(0x05), char(0x00)};
// write(fd, buffer, 5);
int lock = true;
std::vector<char> data_st;
while (1) {
FD_ZERO(&rd);
FD_SET(fd, &rd);
while (FD_ISSET(fd, &rd)) {
if (select(fd + 1, &rd, NULL, NULL, NULL) < 0) {
perror("select error\n");
} else {
while ((nread = read(fd, &buf, sizeof(buf))) > 0) {
std::cout << std::hex << (int) buf << std::endl;
if (lock && buf != 0x55) {
lock=true;
continue;
} else {
lock= false;
// data_st.insert(data_st.begin(), (long) 0x55);
data_st.push_back((long) buf);
if (data_st.size() == 11) {
char t_buf[11];
std::vector<char>::iterator it;
int i = 0;
long sum = 0;
for (it = data_st.begin(); it < data_st.end(); it++) {
t_buf[i] = *it;
sum = (long) *it;
i++;
}
data_st.clear();
if (sum == (2 * long(t_buf[11]))) {
}
switch (t_buf[1]) {
case 0x51:
memcpy(&stcAcc, &t_buf[2], 8);
std::cout << "0x51 加速度"
<< " ax: " << (float) stcAcc.a[0] / 32768 * 16.0 * 9.8
<< " ay: " << (float) stcAcc.a[1] / 32768 * 16.0 * 9.8
<< " az: " << (float) stcAcc.a[2] / 32768 * 16.0 * 9.8
<< " T: " << (float) (stcAcc.T) / 100
<< std::endl;
break;
case 0x52:
memcpy(&stcGyro, &t_buf[2], 8);
break;
case 0x53:
memcpy(&stcAngle, &t_buf[2], 8);
std::cout << "0x53 角度"
<< " agx: " << (float) stcAngle.Angle[0] / 32768 * 180
<< " agy: " << (float) stcAngle.Angle[1] / 32768 * 180
<< " az: " << (float) stcAngle.Angle[2] / 32768 * 180
<< " T: " << (float) (stcAngle.T) / 100
<< std::endl;
break;
case 0x54:
memcpy(&stcMag, &t_buf[2], 8);
std::cout << "0x54 磁场"
" cx: " << (float)stcMag.h[0] <<
" cy: " << (float)stcMag.h[1] <<
" cz: " << (float)stcMag.h[2] <<
" cT: " << (float)stcMag.T/100
<< std::endl;
break;
case 0x55:
memcpy(&stcDStatus, &t_buf[2], 8);
std::cout << "0x55" << std::endl;
break;
case 0x56:
memcpy(&stcPress, &t_buf[2], 8);
std::cout << "0x56" << std::endl;
break;
case 0x57:
memcpy(&stcLonLat, &t_buf[2], 8);
std::cout << "0x57" << std::endl;
break;
case 0x58:
memcpy(&stcGPSV, &t_buf[2], 8);
std::cout << "0x58" << std::endl;
break;
}
// std::vector<char>::iterator it;
// for(it=data_st.begin();it<data_st.end();it++){
// std::cout<<std::hex<<(int)*it<<" ";
// }
// std::cout<<std::endl;
// exit(0);
}
}
}
}
}
}
close(fd);
return 0;
}