我的termios设置是使用read()修改从串行端口读取的第一个字符。我有一个与Linux盒子通讯的微 Controller 。微 Controller 响应从linux机器发送的命令。设置如下:
当我运行类似Cutecom的终端程序时,一切都会按计划进行。我向PIC发送了一个命令字符,但是得到了响应,但是当我使用命令行程序时,第一个字符已被修改。这是我的代码:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#define DEVICE "/dev/ttyUSB0"
#define SPEED B38400
int main()
{
struct termios tio; //to hold serial port settings
struct termios stdio; //so we can accept user input
struct termios old_stdio; //save the current port settings
int tty_fd; //file descriptor for serial port
int res, n, res2, read1, wri;
char buf[255];
char buf2[255];
//save the current port settings
tcgetattr(STDOUT_FILENO,&old_stdio);
//setup serial port settings
bzero(&tio, sizeof(tio));
tio.c_iflag = 0;
tio.c_iflag = IGNPAR | IGNBRK | IXOFF;
tio.c_oflag = 0;
tio.c_cflag = CS8 | CREAD | CLOCAL; //8n1 see termios.h
tio.c_lflag = ICANON;
//open the serial port
tty_fd=open(DEVICE, O_RDWR | O_NOCTTY);
//set the serial port speed to SPEED
cfsetospeed(&tio,SPEED);
//apply to the serial port the settings made above
tcsetattr(tty_fd,TCSANOW,&tio);
for(n = 5; n > 0; n--)
{
printf("Please enter a command: ");
(void)fgets(buf2, 255, stdin);
(void)write(tty_fd, buf2, strlen(buf2));
printf("Ok. Waiting for reply.");
res = read(tty_fd, buf, 255);
printf("Read:%d START%d %d %d %d %dFINISH\n",res,buf[0],buf[1],buf[2],buf[3],
buf[4]);
}
//close the serial port
close(tty_fd);
//restore the original port settings
tcsetattr(STDOUT_FILENO,TCSANOW,&old_stdio);
return EXIT_SUCCESS;
}
这是我得到的结果的一个例子。
由于某些原因,第一个字符被某些termios设置弄乱了。它必须是termios设置,因为当我运行Cutecom时,将完全返回上述相同的测试输入。我已经一遍又一遍地阅读了手册页,尝试对输入控件进行所有不同的设置,但是无论我做什么都不能动摇这个问题。
为了轻松解决问题,我只能将数据跨1个字符移动,但要避免这样做。
有没有人遇到过这样的问题,或者不知道该怎么办?
非常感谢。
13年3月28日
奥斯丁的好建议。对于那些感兴趣的人,这里有两个输出:
速度38400波特;第0行;第0列;行= 0;
intr =;退出=;擦除=;杀死=; eof =;
eol =; eol2 =; swtch =;开始=;停止=;
susp =; rprnt =; werase =;下一个=;
冲洗=;最小值= 0;时间= 0;
-parenb -parodd cs8 -hupcl -cstopb读取clocal -crtscts
ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon ixoff
-iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt
-echoctl -echoke
速度38400波特;第0行;第0列;行= 0;
intr = ^ C;退出= ^\;擦除= ^ ?;杀= ^ U; eof = ^ D; eol =;
eol2 =; swtch =;开始= ^ Q;停止= ^ S; susp = ^ Z; rprnt = ^ R;
werase = ^ W; lnext = ^ V;冲洗= ^ O;最小值= 60;时间= 1;
-parenb -parodd cs8 hupcl -cstopb读取clocal -crtscts
ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt
-echoctl -echoke
我仍在进行所有操作,并且在取得进展时会更新该帖子。
29/3/13
仍然有同样的问题。我什至找到了Cutecom的源代码,并遵循了它们使用的termios设置。问题仍然存在。该第一个字符已损坏!!!
速度38400波特;第0行;第0列;行= 0;
intr = ^ ?;退出= ^\;擦除= ^ H;杀= ^ U; eof = ^ D; eol =;
eol2 =; swtch =;开始= ^ Q;停止= ^ S; susp = ^ Z; rprnt = ^ R;
werase = ^ W; lnext = ^ V;冲洗=;最小值= 60;时间= 1;
-parenb -parodd cs8 hupcl -cstopb读取clocal -crtscts
ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt
-echoctl -echoke
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#define DEVICE "/dev/ttyUSB0"
#define SPEED B38400
int main()
{
struct termios tio; //to hold serial port settings
struct termios stdio; //so we can accept user input
struct termios old_stdio; //save the current port settings
int tty_fd; //file descriptor for serial port
int retval, res, n, res2, read1, wri;
char buf[255];
char buf2[255];
tty_fd = open(DEVICE, O_RDWR | O_NDELAY);
if(tty_fd < 0)
{
perror(DEVICE);
exit(-1);
}
printf("Init 1 complete.\n");
tcflush(tty_fd, TCIOFLUSH);
int f = fcntl(tty_fd, F_GETFL, 0);
fcntl(tty_fd, F_SETFL, f & ~O_NDELAY);
retval = tcgetattr(tty_fd, &old_stdio);
if(retval != 0)
{
perror(DEVICE);
exit(-1);
}
printf("Init 2 complete.\n");
struct termios newtio;
retval = tcgetattr(tty_fd, &newtio);
if(retval != 0)
{
perror(DEVICE);
exit(-1);
}
printf("Init 3 complete.\n");
cfsetospeed(&newtio, SPEED);
cfsetispeed(&newtio, SPEED);
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8;
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~(PARENB | PARODD);
newtio.c_cflag &= ~CRTSCTS;
newtio.c_cflag &= ~CSTOPB;
newtio.c_iflag = IGNBRK;
newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
newtio.c_lflag = 0;
newtio.c_oflag = 0;
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = 60;
newtio.c_cc[VINTR] = 127;
newtio.c_cc[VQUIT] = 28;
newtio.c_cc[VERASE] = 8;
newtio.c_cc[VKILL] = 21;
newtio.c_cc[VEOF] = 4;
newtio.c_cc[VSTOP] = 19;
newtio.c_cc[VSTART] = 17;
newtio.c_cc[VSUSP] = 26;
newtio.c_cc[VREPRINT] = 18;
newtio.c_cc[VFLSH] = 15;
newtio.c_cc[VWERASE] = 23;
newtio.c_cc[VLNEXT] = 22;
retval = tcsetattr(tty_fd, TCSANOW, &newtio);
if(retval != 0)
{
perror(DEVICE);
exit(-1);
}
printf("Init 4 complete.\n");
int mcs = 0;
ioctl(tty_fd, TIOCMGET, &mcs);
mcs |= TIOCM_RTS;
ioctl(tty_fd, TIOCMSET, &mcs);
retval = tcgetattr(tty_fd, &newtio);
if(retval != 0)
{
perror(DEVICE);
exit(-1);
}
printf("Init 5 complete.\n");
newtio.c_cflag &= ~CRTSCTS;
retval = tcsetattr(tty_fd, TCSANOW, &newtio);
if(retval != 0)
{
perror(DEVICE);
exit(-1);
}
printf("Init 6 complete.\n");
for(n = 5; n > 0; n--)
{
printf("Please enter a command: ");
(void)fgets(buf2, 255, stdin);
(void)write(tty_fd, buf2, strlen(buf2));
printf("Ok. Waiting for reply\n");
res = read(tty_fd, buf, 255);
printf("Read:%d START%d %d %d %d %dFINISH\n",res,buf[0],buf[1],buf[2], buf[3],
buf[4]);
}
//restore the original port settings
tcsetattr(tty_fd, TCSANOW, &old_stdio);
close(tty_fd);
return EXIT_SUCCESS; //return all good
}
我完全不知道该怎么办,或者我应该从这里拿走它。
最佳答案
快速浏览您的代码,我看不出任何明显错误的地方。如果您希望使用8位值,则可能要考虑移至unsigned char buf[]
。
由于您在Cutecom中有一个可运行的程序,因此您可以使用它们的termios设置作为调试您自己的程序的引用。
当Cutecom在/dev/ttyUSB0
上运行时,在另一个终端上运行以下命令以转储tty设置:
stty -a -F /dev/ttyUSB0
运行程序时执行相同的操作,并查找两种配置之间的差异。尝试在程序中设置终端设置,使其与为Cutecom报告的设置完全匹配。
更新:
由于修复termios设置仍无法解决问题,因此,请尝试以下其他操作。我可能会猜测某个地方存在计时问题。在Cutecom控制台上打字时,您一次要向设备发送一个字符,每个字符之间的间隔为毫秒。使用程序时,输入命令后将发送完整的字符缓冲区,并且字符将以驱动程序允许的最快速度背对背发送。也许您的PIC程序无法处理数据流的时序,或者期望例如两个停止位而不是一个停止位,从而导致一些奇怪的返回码。
最好的起点可能是从源头开始。掌握示波器或逻辑分析仪,并验证PIC发送的数据实际上是正确的。您将必须了解位电平的波形,并考虑起始位和停止位。比较Cutecom和您的程序的波形。如果使用逻辑分析仪,请确保使用的时钟是波特率的高倍数。例如32乘法器。
调试的另一种方法是使用
strace
来验证驱动程序返回的字符实际上是不正确的,并且这不是程序的问题。使用strace
,您将能够看到程序的原始读/写以及内核返回的内容。在程序运行时,使用strace -o ~/tmp/strace_output.txt -ttt -xx your_program
转储所有系统调用。有时,仅在编制程序的过程中,它的运行速度会降低,足以显示时序错误。您可以将读取/写入的时间与Cutecom的strace
进行比较。仅出于测试目的,您可以添加自己的write()
函数,该函数发送一个字符串,但在每个字符之间延迟一小段时间。
关于c - Linux termios在串行端口read()之后修改第一个字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15672751/