如果通过终端而不是通过应用程序进行写入,为什么rts信号会有所不同?

时间:2016-12-07 15:48:56

标签: c shell serial-port linux-device-driver

我在Ubuntu 16.04下使用rs232 db9公连接器 让我们假设引脚5接地 我可以使用echo "pippo" > /dev/ttyS0之类的命令从终端写入连接器,并使用协议分析器,我可以看到:

  • 引脚3正确传输信号
  • 引脚4和引脚7在数据传输之前均为低电平
  • 引脚4和引脚7均为高电平,而引脚3上的数据传输
  • 引脚3上的数据传输后,引脚4和引脚7均为低电平

现在,如果我尝试运行以下C代码

int file_descriptor = open ("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
unsigned char* buffer = (unsigned char*)"pippo";
buffer_length = strlen((char*)buffer);
unsigned int written = 0;
while(written<buffer_length){
    unsigned int tmp = write (this_ptr->dev_file_descriptor, buffer+written, buffer_length-written);
    if(tmp <0){
        break;
    }
    written += tmp;
}
tcdrain(this_ptr->dev_file_descriptor);
if(written != buffer_length){
    perror("Serial write failure\n");
    return-1;
}
close(file_descriptor);

我可以看到

  • 数据在引脚3 BUT
  • 上传输
  • 引脚4和引脚7始终为低电平

我需要RTS而且我不明白为什么这两种情况下的行为会有所不同。

stty -F /dev/ttyS0 -a的输出实际上是

  速度9600波特;行0;第0列; line = 0;   intr = ^ C;退出= ^ \; erase = ^?; kill = ^ U; eof = ^ D; eol =; eol2 =; swtch =; start = ^ Q; stop = ^ S; susp = ^ Z; rprnt = ^ R; werase = ^ W;   lnext = ^ V; discard = ^ O; min = 1;时间= 0;   -parenb -parodd -cmspar 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 -flusho -extproc

正如我所说,它可以在终端上运行,但它并非来自我的应用程序。

谢谢和问候

2 个答案:

答案 0 :(得分:1)

实际上跟随Kevin建议不起作用设置CRTSCTS使应用程序每次我尝试向串行设备写入一些字节时挂起(我认为CTS信号不是由从设置,所以它一直在等待它)。我要连接一个moxa db9转换器以获得rs485串行输出,但是现在我只是用我的协议分析器检查信号的逻辑状态。 但是提示是正确的,我的意思是如果我用ioctl函数手动设置RTS标志,则RTS被正确管理。因此,如果我们只对控制RTS信号感兴趣而没有完全硬件流控制,我们必须使用attr.c_cflag &= ~CRTSCTS禁用CRTSCTS标志,然后我们可以为RTS引脚创建具有适当ioctl功能的写功能。如果我们有一个支持硬件流控制的从机,那么启用CRTSCTS标志就足够了。

答案 1 :(得分:0)

我不打算包含所有错误处理,我将其作为OP的练习。对于所有正确的包含文件等,请man ioctl / man tcgetattr / man tcsetattr

您必须先设置CRTSCTS标志:

struct termios attr, oldterminfo;
int fd, status;

fd = open(devicename, O_RDWR);

tcgetattr(fd, &oldterminfo);
memcpy (&attr, &oldterminfo, sizeof(termios))
attr.c_cflag |= CRTSCTS | CLOCAL;
attr.c_oflag = 0;
tcsetattr(fd, TCSANOW, &attr);

RTS标志设置为高

ioctl(fd, TIOCMGET, &status);
status |= TIOCM_RTS;
ioctl(fd, TIOCMSET, &status);

您可以在此处对设备进行书写 .....

并且,完成后,将RTS标志设置为低

ioctl(fd, TIOCMGET, &status);
status &= ~TIOCM_RTS;
ioctl(fd, TIOCMSET, &status);