- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我已经在 C 中实现了从串行端口的阻塞读取。我的目标是在新数据到达之前进行阻塞读取。
下面是我实现串行伪对象的方式(为了代码更清晰,我删除了多线程保护)。
typedef struct
{
int fd;
se_serial_speed_t speed;
se_serial_parity_t parity;
bool flow_control;
}se_serial_t;
int se_serial_constructor(se_serial_t** self, char* serial_port)
{
int fd;
if(NULL != *self)
{
return ERR_NNULL_PTR;
}
else if(0 != access(serial_port, F_OK))
{
ERRNO("Serial port is not available");
return ERR_ILLEGAL_PARAM;
}
else
{
if(-1 == (fd = open(serial_port, O_RDWR | O_NOCTTY)))
{
ERRNO("Error opening %s in rw mode", serial_port);
return ERR_OFILE_FAIL;
}
else if(NULL == (*self = malloc(sizeof(se_serial_t))))
{
ERROR("Error allocating memory for Serial");
return ERR_MALLOC_FAIL;
}
(*self)->fd = fd;
}
return ERR_OK;
}
int se_serial_configure_interface(se_serial_t* self, se_serial_speed_t speed, se_serial_parity_t parity, bool flow_control)
{
struct termios options;
if(NULL == self)
{
return ERR_NULL_PTR;
}
else
{
if(0 != tcgetattr(self->fd, &options))
{
ERRNO("Unable to get serial port current configuration");
}
if(0 != cfsetospeed(&options, speed))
{
ERRNO("Unable to set serial port output speed");
}
if(0 != cfsetispeed(&options, speed))
{
ERRNO("Unable to set serial port input speed");
}
switch(parity)
{
case SE_SERIAL_PARITY_8N1:
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
break;
case SE_SERIAL_PARITY_7E1:
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
break;
case SE_SERIAL_PARITY_7O1:
options.c_cflag |= PARENB;
options.c_cflag |= PARODD;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
break;
case SE_SERIAL_PARITY_7S1:
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
break;
default:
WARNING("Unable to set serial port parity");
break;
}
if(flow_control)
options.c_cflag |= CRTSCTS;
else
options.c_cflag &= ~CRTSCTS;
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;
if(0 != tcsetattr(self->fd, TCSANOW, &options))
{
ERRNO("Error configuring serial port");
return ERR_SERIAL_CONF_FAIL;
}
self->speed = speed;
self->parity = parity;
self->flow_control = flow_control;
}
return ERR_OK;
}
int se_serial_read(se_serial_t* self, uint8_t* buffer, int size)
{
int bytes_read = 0;
int ret;
if(NULL == self)
{
return ERR_NULL_PTR;
}
else
{
while(bytes_read < size)
{
if(0 > (ret = read(self->fd, &(buffer[bytes_read]), size - bytes_read)))
{
ERROR("Error reading from %s : %d\n", self->serial_port, ret);
return ERR_RFILE_FAIL;
}
bytes_read += ret;
}
size = bytes_read;
}
return size;
}
与我通信的设备在启动后每秒发送一个 11 字节的帧。
所以我在初始化串行端口后无限循环接收帧,然后打印它们。
se_serial_t* serial = NULL;
uint8_t buffer[1024] = {0};
int ret = 0;
int i;
if(0 > (ret = se_serial_constructor(&serial, "/dev/ttyUSB0")))
{
ERROR("Error creating serial : %d", ret);
return ERR_SERIAL_CREATION_FAIL;
}
else if(0 > (ret = se_serial_configure_interface(serial, SE_SERIAL_SPEED_B115200, SE_SERIAL_PARITY_8N1, false)))
{
ERROR("Error configuring serial interface : %d", ret);
return ERR_SERIAL_CONFIG_FAIL;
}
while(1)
{
if(0 > (ret = se_serial_read(serial, buffer, 11)))
{
ERROR("Error reading from serial : %d", ret);
return ret;
}
else
{
for(i=0;i<ret;i++)
{
printf("%02x ", buffer[i]);
}
printf("\n");
}
}
我得到的结果很奇怪,即使我知道设备正在发送帧,读取也会永远阻塞。
但是,如果我用另一个程序(如 minicom)打开端口,我可以接收其中的帧。使用 minicom 打开端口并退出后,我的程序运行良好,直到下次重新启动计算机。
如果我重启设备,代码会阻塞,直到它开始发送帧并正常接收它们。
我还尝试了 Raspberry Pi 3 以确保它不是我笔记本电脑上的配置问题,但我得到了相同的结果。
有人知道我为什么会出现这种行为吗?
最佳答案
What is strange with the result I get is that the read blocks forever even if I know that the device is sending frames.
...
Once the port has been opened using minicom and that I have exited it, my program works well until next reboot of my computer.
一点都不奇怪。
这清楚地表明您的程序对串行终端的初始化不完整,并且取决于预先存在的初始化是否合适。
(顺便说一句,“奇怪” 是一种基于意见的描述,不传达任何有助于调试的技术信息。)
系统启动后,串行终端的默认模式通常是规范模式(用于传输文本)。
因此,串行终端的(无意的)规范 read() 将阻塞,直到遇到行终止字符(例如换行符或 0x0A)。
如果源从不发送任何行终止字符,您的程序将永远阻塞。
您可以使用 stty -F/dev/ttyUSB0 -a
命令确认这一点,并发现 icanon 属性前面没有连字符。
Minicom 将串行终端配置为非规范模式,这是您的程序显然也希望串行终端在其中运行的模式。
然而,您的程序仅配置波特率、帧和流量控制的 termios 参数。
它缺少串行终端可靠操作的几个重要术语。
如果您的程序需要非规范模式,那么它必须显式配置该模式,而不是依赖于预先存在的配置。
由于还应为非规范模式设置或清除许多其他相关属性,宏 cfmakeraw() 是对您的代码进行最简单的编辑。
插入
cfmakeraw(&options);
在您的波特率和“奇偶校验”配置之间。
请注意,如果数据不完全是 ASCII 文本,则使用 7 位数据帧可能会导致损坏,因此在您的程序中支持这三种模式是不协调的。
另一个显着遗漏是启用接收器和设置本地模式:
options.c_cflag |= (CLOCAL | CREAD);
The device I'm communicating with send a frame of 11 bytes
顺便说一句,您在串行终端的上下文中使用“frame” 是不合适的。在异步串行通信中,每个字符或字节都是成帧的。您对 “框架” 的引用称为消息、数据包或数据报更合适。
关于如果不使用 minicom 打开一次,则无法从串口读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52138242/
我有一个 minicom script它通过串行发送一些命令并期待返回(有效)但我无法退出 minicom 屏幕。 下面是 minicom 脚本: success1: print \nSu
我正在使用 minicom 来尝试连接到 cisco 路由器。我用 minicom -s 做了配置将串口改成合适的 /dev/ttyS1 .保存为 dfl。和退出。 当 minicom 开始时,我得到
我正在尝试在 STM32f429I 上运行 NuttX。我已经构建了 nuttX 并将 nuttx 闪存到设备。但是当我试图启动 minicom 时闪烁后,它显示了这个问题 minicom: cann
我一直在尝试执行一个简单的runsript,它读取变量$1并使用“send”命令将其作为串行数据传递出去。我在脚本中使用该命令发送文本没有任何问题,但我不想编写多个脚本只是为了发送不同的内容。我不确定
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve th
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我正在使用 minicom 通过串行链接连接到目标(sparc 处理器的 UART 链接)。使用 gtkterm 或 cutecom,我可以连接、读取和发送字符。它们唯一的问题是它们都在每个 LF 字
我在将 Linux 服务器连接到串行端口时遇到问题。通过 epabx 从串口传来连续的数据流。 在 Minicom 中,我获得了第一个调用的数据,而从第二个调用开始,它就离线了。我没有看到任何数据。
我正在使用 minicom 来测试我在串口上的连接。 sudo minicom -b 115200 -D /dev/ttyS0 以这种方式 minicom 打开它的“console-gui”并允许我
我正在尝试粘贴一行;这是: setenv -p STARTUP "ifconfig eth0 -auto;boot -z -elf 136.170.195.87:vmlinuz-nfs-7231b0-
我最近开始使用 minicom我总是需要做 Ctrl+A+n (x2):每行时间戳(扩展) 我在 man 中也没有发现任何东西(除了) N Toggle between three states, w
我正在 Linux 上使用 minicom 与 PDP-11 通信,并且我正在使用描述的 shell 脚本 here下载二进制文件。我看到的是“pv”显示的进度条显示下载几乎是立即进行的,而不是串行线
当我尝试在 minicom 中为 linux-3.10 内核和 x86 板打印一些函数名称时,我在 minicom 的每一行中得到额外的空格。我已经在 minicom 中打开了 Line Wrap,但
我已经在 C 中实现了从串行端口的阻塞读取。我的目标是在新数据到达之前进行阻塞读取。 下面是我实现串行伪对象的方式(为了代码更清晰,我删除了多线程保护)。 typedef struct { i
当我使用Minicom从串口抓取数据时,我需要将大数据保存到一个文件中,命名为minicom.cap .但是,如果我按 Ctrl+A 和 L 来捕获文件,则失败。没有创建文件(minicom.cap
我正在尝试从 BeagleBone Black 上的串行端口 (/dev/ttyS4) 读取数据,但我认为(?)这通常适用于所有 Linux 设备。 目前我可以设置minicom,波特率为9600,数
我有一个带有 BusyBox 的嵌入式 Linux 系统。 BusyBox 自带 ash 作为它的默认 shell,但我需要额外的功能所以我想安装 bash。 我已经安装了 bash,并在系统上运行它
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 9年前关闭。 Improve this que
我在 Linux 上遇到 UART 问题。这是我的程序: void open_IMU_UART_connection() { /* Description: * This function open
我正在尝试编写一个 shell 脚本来创建一个新窗口并在其中运行一个 minicom 终端(连接到/dev/ttyACM0)。这是脚本文件 my_script.sh: #!/bin/bash gnom
我是一名优秀的程序员,十分优秀!