我正在尝试使用C程序在Linux环境中读取UART设备,但是在使用屏幕与UART通信方面,我会遇到不同的结果。
我用来测试UART通信的C代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <getopt.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <signal.h>
#include <ctype.h>
bool loop;
void sigHandler(int32_t sig)
{
if(sig == SIGINT)
{
printf("Catched SIGINT");
loop = false;
}
}
int main(int argc, char *argv[])
{
char *devname = argv[1];
int fd = -1;
int nread = -1;
int nwrite = -1;
int ret;
struct termios t_new = {0};
struct termios t_old = {0};
signal(SIGINT, sigHandler);
fd = open(devname, O_RDWR | O_NOCTTY |O_NONBLOCK);
if(fd > 0)
{
printf("TTY open ! Configuring TTY");
}
else
{
fd = -1;
return 1;
}
ret = tcgetattr(fd, &t_old);
if(ret < 0)
{
perror("tcgetattr ");
close(fd);
fd = -1;
return 1;
}
t_new = t_old;
t_new.c_cflag = (B9600 | CS8 | CREAD );
t_new.c_oflag = 0;
t_new.c_iflag = 0;
t_new.c_lflag = 0;
ret = tcsetattr(fd, TCSANOW, &t_new);
loop = true;
while(loop)
{
char s[] = "at+gmi=?\r\n";
nwrite = write(fd, s, strlen(s));
if(nwrite == strlen(s))
{
fd_set rfd;
struct timeval tm = {.tv_sec = 0, .tv_usec = 500000};
FD_ZERO(&rfd);
FD_SET(fd, &rfd);
char buffer[64] = {0};
if(select(fd + 1, &rfd, NULL, NULL, &tm) > 0)
nread = read(fd, buffer, sizeof(buffer));
if(nread > 0)
printf("Reply is: %s\n", buffer);
}
usleep(500000);
}
}
但是当我阅读回复时,它总是包含我发送的字符串。
使用screen
不会遇到此问题。
使用Linux在C语言中从UART读取的最佳方法是什么?
多路传输方式(使用select
会引起问题吗?
编辑 为了完整起见,输出为:
Reply is: at+gmi=?
OK
而且,有时候我什么都不看。
答案 0 :(得分:2)
但是当我阅读回复时,它总是包含我发送的字符串。
由于termios配置消除了本地回显属性,并且您正在发送AT调制解调器命令,因此应尝试发送ATE0
命令以禁用调制解调器的回显。
我在使用屏幕时没有遇到此问题。
此观察结果确认所连接的调制解调器已启用其回显功能。
键入时,AT命令会被调制解调器回显,但是在这种情况下,您不反对接收到的数据(因为您想查看键入的内容)。
如果调制解调器没有启用回显,那么您会抱怨在屏幕中键入的内容不可见。
IOW回声,但是在通过程序发送数据时,必须禁用回声。
使用Linux在C语言中从UART读取的最佳方法是什么?
(从技术上讲,您不是从“ UART” 读取数据,而是从完全缓冲所有输入和输出的串行终端读取数据。)
符合Setting Terminal Modes Properly中所述的POSIX标准的代码
和Serial Programming Guide for POSIX Operating Systems会比您现在拥有的更好。
令我惊讶的是,它根本没有用(例如,未启用CREAD)。
多路复用方式(使用select)会导致问题吗?
不是回声“问题”。
您的程序不需要执行任何使用 select()和非阻止模式的操作。
而且,有时候我什么都不看。
编写与POSIX不兼容的代码时,不应期望可靠的程序行为。