1 Star 0 Fork 1

chxj / serial

forked from helanmouse / serial 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
serial_linux.c 6.62 KB
一键复制 编辑 原始数据 按行查看 历史
helanmouse 提交于 2021-08-23 22:58 . 修复linux下serial_read函数
/*
* serial.c - implementing serial port communication functions
* Copyright (c) 2012 Neolink Co.Ltd
*/
#include <limits.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include "serial.h"
static speed_t baudrate2speed(int baudrate)
{
switch (baudrate) {
case 50: return B50;
case 75: return B75;
case 110: return B110;
case 134: return B134;
case 150: return B150;
case 200: return B200;
case 300: return B300;
case 600: return B600;
case 1200: return B1200;
case 1800: return B1800;
case 2400: return B2400;
case 4800: return B4800;
case 9600: return B9600;
case 19200: return B19200;
case 38400: return B38400;
case 57600: return B57600;
case 115200: return B115200;
case 230400: return B230400;
default: return B0;
}
}
/**
* open a serial port
* @retval SERIAL_OK opening successed
* @retval SERIAL_ERR opening failed
*/
int serial_open (
serial_t *pfd, /* [out] return handle of serial */
const char *device, /* [in] device name */
unsigned int baudrate, /* [in] baudrate */
unsigned int bits, /* [in] start bits */
unsigned int stop, /* [in] stop bits */
char parity /* [in] 'E'- even, 'O' - odd, '\0' - null */
)
{
int fd = -1;
struct termios tis;
int ret;
/* Open serial device */
fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY);
if ( fd >= 0 ) {
// get old terminos
ret = tcgetattr(fd, &tis);
if (ret < 0) {
close(fd);
return SERIAL_ERR;
}
// baudrate
cfsetispeed(&tis, baudrate2speed(baudrate));
cfsetospeed(&tis, baudrate2speed(baudrate));
// databits
tis.c_cflag &= ~CSIZE;
switch (bits) {
case 5: tis.c_cflag |= CS5; break;
case 6: tis.c_cflag |= CS6; break;
case 7: tis.c_cflag |= CS7; break;
case 8: tis.c_cflag |= CS8; break;
}
// parity
switch (parity)
{
case 'n':
case 'N':
tis.c_cflag &= ~PARENB;
tis.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
tis.c_cflag |= (PARODD | PARENB);
tis.c_iflag |= INPCK;
break;
case 'e':
case 'E':
tis.c_cflag |= PARENB;
tis.c_cflag &= ~PARODD;
tis.c_iflag |= INPCK;
break;
}
// stopbits
switch (stop) {
case 1: tis.c_cflag &= ~CSTOPB; break;
case 2: tis.c_cflag |= CSTOPB; break;
}
// flow control
tis.c_cflag &= ~CRTSCTS;
//tis.c_oflag = 0;
tis.c_lflag = ~(ICANON | ECHO | ECHOE | ISIG);
tis.c_cc[VTIME] = 0;
tis.c_cc[VMIN] = 0;
//flush the buffer
tcflush(fd, TCIFLUSH);
ret = tcsetattr(fd, TCSANOW, &tis);
if (ret < 0) {
if (serial_debug) {
serial_printf("serial_open %s failed, tcsetattr error!\n",
device
);
}
close(fd);
return SERIAL_ERR;
}
*pfd = fd;
}
if (serial_debug) {
serial_printf("serial_open %s, baudrate %d, 0x%x -> fd[%d]\n",
device, baudrate, tis.c_cflag, fd
);
}
return (fd > 0) ? SERIAL_OK : SERIAL_ERR;
}
/**
* flush serial buffer
*/
int serial_flush (
serial_t fd, /* [in] the handle for the serial port */
int timeout /* [in] timeout, millseconds waiting to read */
)
{
unsigned char buffer[64];
#ifdef __APPLE__
struct
#endif
fd_set fdr;
struct timeval tv = {0,0};
int ret;
if (serial_debug) {
serial_printf("serial_flush fd[%d]\n", fd);
}
ret = SERIAL_OK;
/* Returns 0 upon success, -1 upon failure. */
if (tcflush(fd, TCIOFLUSH) < 0) {
return SERIAL_ERR;
}
for (;;) {
FD_ZERO(&fdr);
FD_SET(fd, &fdr);
tv.tv_sec = SERIAL_INTERVAL_MSEC_SPLIT_SEC(timeout);
tv.tv_usec = SERIAL_INTERVAL_MSEC_SPLIT_USEC(timeout);
ret = select(fd+1, &fdr, NULL, NULL, &tv);
if ( ret < 0) { // failed
ret = SERIAL_ERR;
break;
} else if ( ret == 0 ) { // timed-out
ret = SERIAL_OK;
break;
} else {
if ( FD_ISSET(fd, &fdr) ) {
ret = read(fd, (char*)buffer, sizeof(buffer));
if (ret < 0) {
ret = SERIAL_ERR;
break;
}
else if (ret == 0) {
ret = SERIAL_OK;
break;
}
}
}
}
return ret;
}
/**
* close the serial port
*/
void serial_close(serial_t fd)
{
if (serial_debug) {
serial_printf("serial_close fd[%d]\n", fd);
}
close(fd);
}
/**
* write to serial port
* @return SERIAL_OK or SERIAL_ERR
*/
int serial_write (
serial_t fd, /* [in] the handle for the serial port */
unsigned char *buffer, /* [in] buffer the data to be written */
unsigned int len /* [in] len the length of the data */
)
{
int w;
unsigned char *p;
int ret = SERIAL_OK;
if (serial_debug) {
log_t *lmsg = logpc(LOG_NONE);
logp(lmsg, "serial_write fd[%d], size %d:\n", fd, len);
logpb(lmsg, buffer, len, "%x", ",");
logp(lmsg, "\n");
logpf(lmsg);
}
p = buffer;
while (len > 0) {
w = write(fd, p, len);
if ( w < 1 ) {
ret = SERIAL_ERR;
break;
}
len -= w;
p += w;
}
return ret;
}
/**
* read data with specified length from the serial port
* @retval SERIAL_OK if expected number of bytes read
* @retval SERIAL_TIMEOUT if timed-out during the read
* @retval SERIAL_ERR if read failed
*/
int serial_read(
serial_t fd, /* [in] the handle for the serial port */
unsigned char *buffer, /* [in] the data to be read */
unsigned int *len, /* [in,out] input the length of the data, return received data length */
int timeout /* [in] millseconds waiting to read */
)
{
int ret = SERIAL_OK;
int r = -1;
#ifdef __APPLE__
struct
#endif
fd_set fdr;
struct timeval tv = {0,0};
unsigned int cnt = 0;
while (cnt < *len) {
FD_ZERO(&fdr);
FD_SET(fd, &fdr);
if (timeout == -1) {
r = select(fd + 1, &fdr, NULL, NULL, NULL);
} else {
tv.tv_sec = SERIAL_INTERVAL_MSEC_SPLIT_SEC(timeout);
tv.tv_usec = SERIAL_INTERVAL_MSEC_SPLIT_USEC(timeout);
r = select(fd + 1, &fdr, NULL, NULL, &tv);
}
if ( r < 0) { // failed
ret = SERIAL_ERR;
break;
} else if ( r == 0 ) { // timed-out
ret = SERIAL_TIMEOUT;
break;
} else {
if ( FD_ISSET(fd, &fdr) ) {
r = read(fd , (char*)(buffer + cnt), *len - cnt);
if ( r >= 0 ) {
cnt += r;
}
}
}
}
*len = cnt;
if ( (r >= 0) && (cnt > 0)) {
if (serial_debug) {
log_t *lmsg = logpc(LOG_NONE);
logp(lmsg, "serial_read fd[%d], size %d:\n", fd, cnt);
logpb(lmsg, buffer, cnt, "%x", ",");
logp(lmsg, "\n");
logpf(lmsg);
}
}
else if (r == 0) {
if (serial_debug) {
serial_printf("serial_read fd[%d], timer %d is timeout!\n",
fd, timeout
);
}
}
else if (r < 0) {
if (serial_debug) {
serial_printf("serial_read fd[%d] fail, errcode = %d!\n",
fd, r
);
}
}
return ret;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/chxj8080/serial.git
git@gitee.com:chxj8080/serial.git
chxj8080
serial
serial
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891