- 微控制器(PIC24F) RS485端口 <--> RS485转USB转换器 <--> Ubuntu PC。
#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;
}
以下是我得到的结果示例。
- 当PIC发送“00000\n”时,输出为:读取:6 START-16 48 48 48 48FINISH
- 当PIC发送“23456\n”时,输出为:读取:6 START-14 51 52 53 54FINISH
- 当PIC发送“34567\n”时,输出为:读取:6 START-14 52 53 54 55FINISH
- 当PIC发送“45678\n”时,输出为:读取:6 START-12 53 54 55 56FINISH
- 当PIC发送“56789\n”时,输出为:读取:6 START-12 54 55 56 57FINISH
由于某些termios设置的原因,第一个字符被搞乱了。这一定是termios设置问题,因为当我运行Cutecom时,相同的测试输入返回的结果完全相同。我一遍又一遍地阅读手册页面,尝试在输入控制上使用所有不同的设置,但无论我做什么都无法解决这个问题。
对于一个简单的解决方法,我可以将我的数据向右移动一个字符,但想避免这样做。
有人遇到过这样的问题或者有任何关于此问题的想法吗?
非常感谢。
28/3/13 Austin提出了一个很好的建议。对于那些感兴趣的人,以下是两个输出:
首先是我程序中的 termios 设置
速率 38400 baud; 行数 0; 列数 0; 行 = 0; 中断 = ; 退出 = ; 擦除 = ; 杀死 = ; 结束文件 = ; 结尾1 = ; 结尾2 = ; 开关 = ; 开始 = ; 停止 = ; 暂停 = ; 重打 = ; 字符消去 = ; lnext = ; 刷新 = ; 最小值 = 0; 时间 = 0; -parenb -parodd cs8 -hupcl -cstopb cread 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
然后是 cutecom 使用的设置
速率 38400 baud; 行数 0; 列数 0; 行 = 0; 中断 = ^C; 退出 = ^\; 擦除 = ^?; 杀死 = ^U; 结束文件 = ^D; 结尾1 = ; 结尾2 = ; 开关 = ; 开始 = ^Q; 停止 = ^S; 暂停 = ^Z; 重打 = ^R; 字符消去 = ^W; lnext = ^V; 刷新 = ^O; 最小值 = 60; 时间 = 1; -parenb -parodd cs8 hupcl -cstopb cread 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
我仍在研究并会在取得进展时更新此帖子。
2013年3月29日 问题仍然存在。我甚至找到了 Cutecom 的源代码并使用了它们的 termios 设置,但问题依旧存在。第一个字符被损坏!!!
Here are the Termios settings from my program. Cannot set flush for some reason.
speed 38400 baud; rows 0; columns 0; line = 0; intr = ^?; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = ; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ; min = 60; time = 1; -parenb -parodd cs8 hupcl -cstopb cread 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
And my new code:
#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 }
我完全不知道可以做什么或者从哪里继续下去。
涉及IT技术的内容,暂无法提供更多信息。请提供更具体的翻译要求。
expected & 0xEE
修改了一样... - Jonathan Leffler'0'
(0x30)时,你得到的是 0x10,而且 0x30 & 0xDE == 0x10(16)。同样地,当第一个字节为'2'
(0x32)时,你得到的是 14 或者 0x0E;0x3E & 0xDE = 0x0E。对于'3'
(0x33),0x33 & 0xDE == 0x0E(14);对于'4'
(0x34),0x34 & 0xDE == 0x0C(12);对于'5'
(0x35),0x35 & 0xDE == 0x0C(12)。因此,就好像第一个字节被与 0xDE 进行了 AND 操作。我想不出为什么会发生这种情况,但这解释了你所看到的模式。 - Jonathan LefflerIXOFF
。你的 C 程序启用了输入的 XON/XOFF 流控制(而 Cutecom 没有)。这也符合症状;XON/XOFF 流控制字符默认为DC1
到DC4
(十进制 17 到 20),但你已经将它们(.c_cc[VSTART]
、.c_cc[VSTOP]
、.c_cc[VSTATUS]
)替换为 NUL,这可能会导致内核驱动程序产生奇怪的起始字节。你基本上告诉内核驱动程序,你希望它根据特殊代码处理输入流控制,但是又将流控制的起始和停止代码都设置为 NUL(零字节)。 - Nominal Animal