📄 cserial.cpp
字号:
#include "CSerial.h" // 串口类头文件
/****************************************
* 构造函数填充串口基本信息
* 默认是波特率为9600, 8N1, ttyS0, 软件流控
****************************************/
CSerial::CSerial(int baud=9600, char databit='8', char parity='N', char stopbit='1', char tty='0', char flowctl='2'){
PPortInfo = new PortInfo;
PPortInfo->baudrate = baud;
PPortInfo->databit = databit;
PPortInfo->parity = parity;
PPortInfo->stopbit = stopbit;
PPortInfo->tty = tty;
PPortInfo->flowctl = flowctl;
}
CSerial::~CSerial(){
delete PPortInfo;
}
/****************************************
* 打开串口,返回文件描述符,失败返回-1
****************************************/
int CSerial::PortOpen(){
int fd;
char* tty;
switch(PPortInfo->tty){
case '0':
tty = "/dev/ttyS0";
break;
case '1':
tty = "/dev/ttyS1";
break;
case '2':
tty = "/dev/ttyS2";
break;
case '3':
tty = "/dev/ttyS3";
break;
case '4':
tty = "/dev/ttyS4";
break;
case '5':
tty = "/dev/ttyS5";
break;
default:
tty = "/dev/ttyS0";
}
fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
return (fd);
}
/*******************************************
* 设置串口属性,成功返回true,失败返回false
* fd: 已打开的文件描述符
*******************************************/
int CSerial::PortSet(int fd){
struct termios termios_old, termios_new;
int i, errorstatus; 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 };
bzero(&termios_old, sizeof(termios_old));
bzero(&termios_new, sizeof(termios_new));
cfmakeraw(&termios_new);
tcgetattr(fd, &termios_old);
/*****设置波特率*****/
for(i=0; i<sizeof(speed_arr) / sizeof(int); i++){
if (PPortInfo->baudrate == name_arr[i]){
cfsetispeed(&termios_new, PPortInfo->baudrate); //填入串口输入端波特率
cfsetospeed(&termios_new, PPortInfo->baudrate); //填入串口输出端波特率
break;
}
}
termios_new.c_cflag |= CLOCAL; //控制模式, 保证程序不会成为端口的占有者
termios_new.c_cflag |= CREAD; //控制模式, 使能端口读取输入的数
/*****流控制模式*****/
switch(PPortInfo->flowctl){
case '0':
termios_new.c_cflag &= ~CRTSCTS; //关闭流控制
break;
case '1':
termios_new.c_cflag |= CRTSCTS; //硬件流控
break;
case '2':
termios_new.c_iflag |= IXON | IXOFF |IXANY; //软件流控
break;
default:
termios_new.c_iflag |= IXON | IXOFF |IXANY; //软件流控
}
/*****设置字符位数*****/
termios_new.c_cflag &= ~CSIZE; //控制模式, 屏蔽字符大小
switch(PPortInfo->databit){
case '5':
termios_new.c_cflag |= CS5;
break;
case '6':
termios_new.c_cflag |= CS6;
break;
case '7':
termios_new.c_cflag |= CS7;
break;
default:
termios_new.c_cflag |= CS8;
}
/*****设置奇偶校验*****/
switch(PPortInfo->parity){
case 'N':
termios_new.c_cflag &= ~PARENB; //无校验
break;
case 'O':
termios_new.c_cflag |= PARENB; //偶校验
termios_new.c_cflag &= ~PARODD;
break;
case 'E':
termios_new.c_cflag |= PARENB; //奇校验
termios_new.c_cflag |= PARODD;
break;
default:
termios_new.c_cflag &= ~PARENB; //无校验
}
/*****设置停止位*****/
if (PPortInfo->stopbit == '2' )
termios_new.c_cflag |= CSTOPB;
else
termios_new.c_cflag &= ~CSTOPB;
/*****设置为原始模式输出*****/
termios_new.c_oflag &= ~OPOST;
/*****设置读取控制*****/
termios_new.c_cc[VMIN] = 1; //控制字符, 所要读取字符的最小数量
termios_new.c_cc[VTIME] = 1; //控制字符, 读取第一个字符的等待时间, unit: (1/10)second
/*****刷清缓存,使新设置生效*****/
tcflush(fd, TCIFLUSH);
errorstatus = tcsetattr(fd, TCSANOW, &termios_new);
if (errorstatus < 0)
return (false);
return(true);
}
/***************************************
* 串口关闭
* fd: 待关闭的文件描述符
***************************************/
int CSerial::PortClose(int fd){
if (fd<0)
return (false);
else{
close(fd);
return (true);
}
}
/***************************************
* 往串口写数据
* fd: 文件描述符,data: 待写入的数据, datalen: 待写入数据的长度
***************************************/
int CSerial::PortWrite(int fd, char* data, int datalen){
int len;
len = write(fd, data, datalen); //实际写入的长度
if(len == datalen){
return (len);
}
else{
tcflush(fd, TCOFLUSH);
return -1;
}
}
/*******************************************************
* 从串口读数据
* 返回实际读到数据的长度,出错返回-1
* fd: 文件描述符, buff:保存读入的数据, realen:读取字符数
*******************************************************/
int CSerial::PortRead(int fd, char* buff, int readlen){
int len, fs_sel;
fd_set fs_read;
struct timeval tv_timeout;
FD_ZERO(&fs_read);
FD_SET(fd, &fs_read);
tv_timeout.tv_sec = readlen * 20 / (PPortInfo->baudrate) + 2; //设置超时
tv_timeout.tv_usec = 0;
fs_sel = select(fd+1, &fs_read, NULL, NULL, &tv_timeout);
if(fs_sel){
len == read(fd, buff, readlen);
return(len);
}
else
return(-1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -