我使用以下功能打开串口
int open_port (unsigned char * port)
{
int fd = open(port,O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1)
{
return PORT_ERR;
}
else
{
struct termios new_termios;
struct termios orig_termios;
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
cfmakeraw(&new_termios);
cfsetispeed(&new_termios,B9600);
cfsetospeed(&new_termios,B9600);
tcsetattr(fd, TCSANOW, &new_termios);
return fd;
}
}
我正在使用Debian(raspberrypi)发行版在Cubieboard2上运行该程序。当我手动运行程序时,它工作正常。但是当程序在init.d脚本启动时启动时,它可以正常运行并执行其他任务(读取和写入文件),但它不会读取串行端口上发送的任何数据。
lsof /dev/ttyUSB1
还显示我的程序正在使用该端口。有什么想法吗?
答案 0 :(得分:1)
您应该更完整地初始化 termios 结构,例如 cflags ,VMIN和VTIME,如this working code中所示,或使用 perror()系统调用
rc = tcgetattr(sfd, &tty);
if (rc < 0) {
perror("failed to get attr");
exit (-2);
}
savetty = tty; /* preserve original settings for restoration */
spd = B115200;
cfsetospeed(&tty, (speed_t)spd);
cfsetispeed(&tty, (speed_t)spd);
cfmakeraw(&tty);
tty.c_cc[VMIN] = 1; /* wait for at least 1 char */
tty.c_cc[VTIME] = 10; /* or 1 sec after a char */
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS; /* no HW flow control */
tty.c_cflag |= CLOCAL | CREAD;
rc = tcsetattr(sfd, TCSANOW, &tty);
if (rc < 0) {
perror("failed to set attr");
exit (-3);
}
您还应该测试所有系统调用的每个返回代码,尤其是遇到问题时。
再次查看代码, tcgetattr()的第一个参数显然不正确:
tcgetattr(0, &orig_termios);
防御性编码(例如验证参数和检查返回调用)有助于捕获可能消耗大量调试时间的这些类型的愚蠢错误。
<强>附录强>
我想我理解为什么代码似乎在第一种情况下工作,何时启动&#34;手动&#34;来自外壳。
文件描述符值0是STDIN_FILENO的值
因此tcgetattr(0, &orig_termios)
语句将检索 stdin 的 termios 值。 (最初我假设你总是有一个未检测到的错误返回,所以结构将不加修改地返回。)大概你在嵌入式系统上执行了这个,其中控制台是一个串口(并且stdin的返回值是一个串口&#39) ; S)。
当我在PC上运行此代码时, cflags 会在禁用CREAD标志的情况下提供,这应该会在以后引起问题。请注意,设置 cflags 是我的建议之一。 VMIN和VTIME分别返回为8和4,但这些异常值不会像CREAD标志那样致命。 stdin视频控制台还有其他不常见的 termios 值,少数会被你的(最小)初始化代码纠正,或者由于使用了非规范模式,大多数异常值都无关紧要。