串行 c 读入 linux 有问题
serial c to read in linux with issues
我正在尝试使用Odroid(单机板)在C中读取串口以通过usb电缆从arduino板获取数据。发布传感器数据就像 189。波特率为115200.
读取使用的主要代码:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/ipc.h>
#include <sys/shm.h>
#include "share.h"
#include <math.h>
#include <stdlib.h>
#pragma GCC diagnostic ignored "-Wwrite-strings"
/*
* @brief Open serial port with the given device name
*
* @return The file descriptor on success or -1 on error.
*/
int open_port(char *port_device)
{
int fd; /* File descriptor for the port */
fd = open(port_device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open_port: Unable to open /dev/Servo_LIDAR ");
}
else
fcntl(fd, F_SETFL, 0);
return (fd);
}
int main()
{
//--------------------------------------------------------------------------------
struct termios options;
int fd=-1;
char *u_port = "/dev/Servo_LIDAR";
fd=open_port(u_port);
if(fd==-1)
{
printf("port not open");
return -1;
}
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
//Enable the receiver and set local mode...
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~CSIZE; /* Mask the character size bits */
options.c_cflag |= CS8; /* Select 8 data bits */
//No parity
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
//Set the new options for the port...
tcsetattr(fd, TCSANOW, &options);
printf("Reading...\n");
while(true)
{
while(1)
{
//sleep(0.5);
char buff[1024]={0};
char buf[1]={0};
while(1) {
ssize_t res=read(fd, buf, 1);
if(res==0) continue;
buf[res]=0;
strcat(buff,buf);
if (buf[0] == '\n') break;
}
printf("%s\n", buff);
usleep(70000);
break;
}
}
close(fd);
}
我有这样的约会:
187
187187187
188
188188
188188188
188
1888
188
18188
188
186187
187
187
每次应该是3个字节的数据,但我遇到了这样的问题。任何建议,谢谢。
有几件事我会尝试。首先是调整读取returns 0字节后的休眠。如果串行端口不是 buffered/interrupt 驱动,则 10ms 非常接近接收一个字节所需的时间(当前波特率是 11.52)。
第二个问题可能在输出端。您是否考虑过问题可能在那里?尝试每读取 10 次才打印一次,从而减少输出端的流量。
您的主要错误涉及语句:
char buf[1]={0};
...
ssize_t res=read(fd, buf, 1);
...
buf[res]=0;
数组buf[]声明只有一个个元素长,即buf[0] 是数组的唯一元素。
read() 系统调用成功时的 return 值为 1,因为这是指定的计数。
然后您尝试通过写入 buf[1] 来终止接收到的文本,但这是一个尚未分配的元素。
数组 buf[] 需要至少 2 个元素长。
此错误的症状因编译器和主机系统而异。在使用 gcc 4.8.4 的 x86 笔记本电脑上,您的原始程序根本没有输出。
有关终止缓冲区数据的首选方法,请参阅
代码审查
所有系统调用,包括 tc[gs]etattr() 和 read(),应该是检查错误 return 代码,尤其是当您的程序未按预期运行时。
您的 termios 配置不完整。您的程序将以任何先前配置的规范或非规范模式执行。这可能会产生意想不到的结果。
一次只读取一个字符(嵌套在多个 while 循环中)效率低下。规范读取可以 return 每个系统调用一行。学习"Two Styles of Input: Canonical or Not"
诸如usleep(70000)
之类的程序延迟是多余的。 file/device 已打开以阻止读取,因此 read() 不会 return 直到数据可用。
我正在尝试使用Odroid(单机板)在C中读取串口以通过usb电缆从arduino板获取数据。发布传感器数据就像 189。波特率为115200.
读取使用的主要代码:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/ipc.h>
#include <sys/shm.h>
#include "share.h"
#include <math.h>
#include <stdlib.h>
#pragma GCC diagnostic ignored "-Wwrite-strings"
/*
* @brief Open serial port with the given device name
*
* @return The file descriptor on success or -1 on error.
*/
int open_port(char *port_device)
{
int fd; /* File descriptor for the port */
fd = open(port_device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open_port: Unable to open /dev/Servo_LIDAR ");
}
else
fcntl(fd, F_SETFL, 0);
return (fd);
}
int main()
{
//--------------------------------------------------------------------------------
struct termios options;
int fd=-1;
char *u_port = "/dev/Servo_LIDAR";
fd=open_port(u_port);
if(fd==-1)
{
printf("port not open");
return -1;
}
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
//Enable the receiver and set local mode...
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~CSIZE; /* Mask the character size bits */
options.c_cflag |= CS8; /* Select 8 data bits */
//No parity
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
//Set the new options for the port...
tcsetattr(fd, TCSANOW, &options);
printf("Reading...\n");
while(true)
{
while(1)
{
//sleep(0.5);
char buff[1024]={0};
char buf[1]={0};
while(1) {
ssize_t res=read(fd, buf, 1);
if(res==0) continue;
buf[res]=0;
strcat(buff,buf);
if (buf[0] == '\n') break;
}
printf("%s\n", buff);
usleep(70000);
break;
}
}
close(fd);
}
我有这样的约会:
187
187187187
188
188188
188188188
188
1888
188
18188
188
186187
187
187
每次应该是3个字节的数据,但我遇到了这样的问题。任何建议,谢谢。
有几件事我会尝试。首先是调整读取returns 0字节后的休眠。如果串行端口不是 buffered/interrupt 驱动,则 10ms 非常接近接收一个字节所需的时间(当前波特率是 11.52)。
第二个问题可能在输出端。您是否考虑过问题可能在那里?尝试每读取 10 次才打印一次,从而减少输出端的流量。
您的主要错误涉及语句:
char buf[1]={0};
...
ssize_t res=read(fd, buf, 1);
...
buf[res]=0;
数组buf[]声明只有一个个元素长,即buf[0] 是数组的唯一元素。
read() 系统调用成功时的 return 值为 1,因为这是指定的计数。
然后您尝试通过写入 buf[1] 来终止接收到的文本,但这是一个尚未分配的元素。
数组 buf[] 需要至少 2 个元素长。
此错误的症状因编译器和主机系统而异。在使用 gcc 4.8.4 的 x86 笔记本电脑上,您的原始程序根本没有输出。
有关终止缓冲区数据的首选方法,请参阅
代码审查
所有系统调用,包括 tc[gs]etattr() 和 read(),应该是检查错误 return 代码,尤其是当您的程序未按预期运行时。
您的 termios 配置不完整。您的程序将以任何先前配置的规范或非规范模式执行。这可能会产生意想不到的结果。
一次只读取一个字符(嵌套在多个 while 循环中)效率低下。规范读取可以 return 每个系统调用一行。学习"Two Styles of Input: Canonical or Not"
诸如
usleep(70000)
之类的程序延迟是多余的。 file/device 已打开以阻止读取,因此 read() 不会 return 直到数据可用。