initial commit
This commit is contained in:
219
by_serial.c
Normal file
219
by_serial.c
Normal file
@@ -0,0 +1,219 @@
|
||||
#include "by_serial.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include "logc/log.h"
|
||||
|
||||
int by_serial_init(by_serial_t *serial_port, const char *dev_name)
|
||||
{
|
||||
serial_port->dev_name_len = strlen(dev_name);
|
||||
assert(0 < serial_port->dev_name_len);
|
||||
strcpy(serial_port->dev_name_str, dev_name);
|
||||
|
||||
int fd;
|
||||
fd = open(serial_port->dev_name_str, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
log_error("open uart device error");
|
||||
return -1;
|
||||
} else {
|
||||
serial_port->fd = fd;
|
||||
by_serial_set_baudrate(serial_port, 115200);
|
||||
by_serial_set_parity(serial_port, 8, 1, 'N');
|
||||
log_info("serial %s init successful", serial_port->dev_name_str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int by_serial_set_baudrate(by_serial_t *serial_port, int baudrate)
|
||||
{
|
||||
int index = 0;
|
||||
int status = 0;
|
||||
int speed_arr[] = {
|
||||
B115200,
|
||||
B38400,
|
||||
B19200,
|
||||
B9600,
|
||||
B4800,
|
||||
B2400,
|
||||
B1200};
|
||||
int name_arr[] = {
|
||||
115200,
|
||||
38400,
|
||||
19200,
|
||||
9600,
|
||||
4800,
|
||||
2400,
|
||||
1200};
|
||||
struct termios Opt = {0};
|
||||
|
||||
tcgetattr(serial_port->fd, &Opt);
|
||||
for (index = 0; index < sizeof(speed_arr) / sizeof(int); index++) {
|
||||
if (baudrate == name_arr[index]) {
|
||||
|
||||
/*设置前 flush*/
|
||||
tcflush(serial_port->fd, TCIOFLUSH);
|
||||
cfsetispeed(&Opt, speed_arr[index]);
|
||||
cfsetospeed(&Opt, speed_arr[index]);
|
||||
|
||||
/*tcsetattr(串口描述符,立即使用或者其他标示,指向 termios 的指针),通过
|
||||
tcsetattr 函数把新的属性设置到串口上。*/
|
||||
status = tcsetattr(serial_port->fd, TCSANOW, &Opt);
|
||||
if (0 != status) {
|
||||
log_error("tcsetattr COM error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*设置后 flush*/
|
||||
tcflush(serial_port->fd, TCIOFLUSH);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int by_serial_set_parity(by_serial_t *serial_port, int databits, int stopbits, char parity)
|
||||
{
|
||||
struct termios Opt = {0};
|
||||
|
||||
if (0 != tcgetattr(serial_port->fd, &Opt)) {
|
||||
log_error("tcgetattr COM error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
|
||||
Opt.c_oflag &= ~OPOST; /*Output*/
|
||||
|
||||
Opt.c_iflag &= ~ICRNL; // 禁止将输入的 CR 转换为 NL
|
||||
Opt.c_iflag &= ~(IXON); // 清 bit 位 关闭流控字符
|
||||
|
||||
/*设置数据位,取值为 7 或 8*/
|
||||
Opt.c_cflag &= ~CSIZE;
|
||||
switch (databits) {
|
||||
case 7:
|
||||
Opt.c_cflag |= CS7;
|
||||
break;
|
||||
case 8:
|
||||
Opt.c_cflag |= CS8;
|
||||
break;
|
||||
default:
|
||||
log_error("Unsupported data size");
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*设置停止位,取值为 1 或 2*/
|
||||
switch (stopbits) {
|
||||
case 1:
|
||||
Opt.c_cflag &= ~CSTOPB;
|
||||
break;
|
||||
case 2:
|
||||
Opt.c_cflag |= CSTOPB;
|
||||
break;
|
||||
default:
|
||||
log_error("Unsupported stop bits");
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*设置校验位,取值为 E,N,O,S*/
|
||||
switch (parity) {
|
||||
case 'e':
|
||||
case 'E': {
|
||||
Opt.c_cflag |= PARENB; /*Enable parity*/
|
||||
Opt.c_cflag &= ~PARODD; /*转换为偶效验*/
|
||||
Opt.c_iflag |= INPCK; /*Disnable parity checking*/
|
||||
} break;
|
||||
case 'n':
|
||||
case 'N': {
|
||||
Opt.c_cflag &= ~PARENB; /*Clear parity enable*/
|
||||
Opt.c_iflag &= ~INPCK; /*Enable parity checking*/
|
||||
} break;
|
||||
case 'o':
|
||||
case 'O': {
|
||||
Opt.c_cflag |= (PARODD | PARENB); /*设置为奇效验*/
|
||||
Opt.c_iflag |= INPCK; /*Disnable parity checking*/
|
||||
} break;
|
||||
case 's': /*as no parity*/
|
||||
case 'S': /*as no parity*/
|
||||
{
|
||||
Opt.c_cflag &= ~PARENB;
|
||||
Opt.c_cflag &= ~CSTOPB;
|
||||
} break;
|
||||
default:
|
||||
log_error("Unsupported parity\n");
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*设置结构体输入校验位*/
|
||||
if ('n' != parity) {
|
||||
Opt.c_iflag |= INPCK;
|
||||
}
|
||||
|
||||
tcflush(serial_port->fd, TCIFLUSH);
|
||||
Opt.c_cc[VTIME] = 150; /*设置超时 15 秒*/
|
||||
Opt.c_cc[VMIN] = 0; /*更新结构体并立即执行*/
|
||||
if (0 != tcsetattr(serial_port->fd, TCSANOW, &Opt)) {
|
||||
log_error("tcsetattr COM error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int by_serial_write(by_serial_t *serial_port, const char *buff, const int len)
|
||||
{
|
||||
int len_t;
|
||||
|
||||
if (serial_port->fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len_t = write(serial_port->fd, buff, len);
|
||||
|
||||
if (0 > len_t) {
|
||||
// log_error("write buff failed");
|
||||
return -1;
|
||||
} else {
|
||||
// printf("write buff successful %d/%d\r\n", len_t, len);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int by_serial_read(by_serial_t *serial_port, char *buff, const int len)
|
||||
{
|
||||
if (1 > by_serial_get_used_buffer_len(serial_port)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int len_t = -1;
|
||||
|
||||
if (serial_port->fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len_t = read(serial_port->fd, buff, len);
|
||||
|
||||
if (0 > len_t) {
|
||||
// log_error("read buff failed");
|
||||
return -1;
|
||||
} else {
|
||||
// printf("read buff successful %d/%d\r\n", len_t, len);
|
||||
return len_t;
|
||||
}
|
||||
}
|
||||
|
||||
int by_serial_get_used_buffer_len(by_serial_t *serial_port)
|
||||
{
|
||||
int used_len = 0;
|
||||
ioctl(serial_port->fd, FIONREAD, &used_len);
|
||||
return used_len;
|
||||
}
|
||||
Reference in New Issue
Block a user