串口设备:读取8N1有效,但写入单个字节失败

发布于 2024-08-08 01:19:25 字数 1950 浏览 5 评论 0原文

在我的程序中,我从串行设备(Linux,8N1)读取数据没有任何问题。但如果我想写出一个字节,我在界面上什么也得不到。我认为我的串行输出设置是错误的。但是设置 c_oflag 的方法并不多...

我的代码:

#define TTYDEVICE "/dev/ttyS0"
#define BAUDRATE B9600

int openSerialDevice(const char* devTTY, struct termios oldTio) {
//----< Open serial device >----------------------------------
int fileDescriptor;
// fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY);
//fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY /*| OPOST*/);
if (fileDescriptor == -1) {
    perror("Error while opening serial interface occurred!");
    return -99;
}

// set new parameters to the serial device
struct termios newtio;
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

// set to 8N1
newtio.c_cflag &= ~PARENB;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS8;

newtio.c_iflag = IGNPAR;

// output mode to
//newtio.c_oflag = 0;
newtio.c_oflag |= OPOST;

/* set input mode (non-canonical, no echo,...) */
newtio.c_lflag = 0;

newtio.c_cc[VTIME] = 10; /* inter-character timer 1 sec */
newtio.c_cc[VMIN] = 0; /* blocking read disabled  */

tcflush(fileDescriptor, TCIFLUSH);
if (tcsetattr(fileDescriptor, TCSANOW, &newtio)) {
    perror("could not set the serial settings!");
    return -99;
}

//----< / Open serial device >----------------------------------
return fileDescriptor;
}

int ACK[1] = { 6 };

int main() {
// old termios to restablish
struct termios oldTIO;
// filedescriptor
int fd;

fd = openSerialDevice(TTYDEVICE, oldTIO);

if ((fd == -1) | (fd == -99)) {
    perror("Could not open TTY-Device. Exit on failure!");
    return EXIT_FAILURE;
}

write(fd, ACK, 1);  // Problem !! 


     return 0:
}

现在,如果我使用

屏幕 /dev/ttyS1 9600 8n1

来验证 /dev/ttyS0 上出现的内容。我什么也看不见。如果我用 Docklight 1.8 嗅探,也是如此。

有什么建议吗?谢谢

In my program I read from the serial device (Linux, 8N1) without any problem. But in the case I want to write out a single byte, I get nothing out on the interface. I assume that my serial output settings are wrong. But there aren't that many ways how to set c_oflag...

My code:

#define TTYDEVICE "/dev/ttyS0"
#define BAUDRATE B9600

int openSerialDevice(const char* devTTY, struct termios oldTio) {
//----< Open serial device >----------------------------------
int fileDescriptor;
// fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY);
//fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY /*| OPOST*/);
if (fileDescriptor == -1) {
    perror("Error while opening serial interface occurred!");
    return -99;
}

// set new parameters to the serial device
struct termios newtio;
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

// set to 8N1
newtio.c_cflag &= ~PARENB;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS8;

newtio.c_iflag = IGNPAR;

// output mode to
//newtio.c_oflag = 0;
newtio.c_oflag |= OPOST;

/* set input mode (non-canonical, no echo,...) */
newtio.c_lflag = 0;

newtio.c_cc[VTIME] = 10; /* inter-character timer 1 sec */
newtio.c_cc[VMIN] = 0; /* blocking read disabled  */

tcflush(fileDescriptor, TCIFLUSH);
if (tcsetattr(fileDescriptor, TCSANOW, &newtio)) {
    perror("could not set the serial settings!");
    return -99;
}

//----< / Open serial device >----------------------------------
return fileDescriptor;
}

int ACK[1] = { 6 };

int main() {
// old termios to restablish
struct termios oldTIO;
// filedescriptor
int fd;

fd = openSerialDevice(TTYDEVICE, oldTIO);

if ((fd == -1) | (fd == -99)) {
    perror("Could not open TTY-Device. Exit on failure!");
    return EXIT_FAILURE;
}

write(fd, ACK, 1);  // Problem !! 


     return 0:
}

Now, if I use

screen /dev/ttyS1 9600 8n1

to verify what's coming out on /dev/ttyS0. I can't see anything. Same if I sniff with Docklight 1.8.

Any suggestions? thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

通知家属抬走 2024-08-15 01:19:25

您如何验证没有任何结果?

您可以尝试删除 RTSCTS,然后重试。事实上,如果您希望 tty 层的干扰最小,您应该使用以下命令将终端设置为 raw:

cfmakeraw(&newtio);

How do you verify nothing is coming out ?

You can try to drop the RTSCTS, and try again. Infact, if you want minimal interference from the tty layer, you should set your terminal to raw, using this :

cfmakeraw(&newtio);
疯了 2024-08-15 01:19:25

您向 write() 提供 ACK 的数据参数,它是一个指向 int 的指针。这可能不是你的意思。根据您所在计算机的 字节序,这意味着 write() 将“看到”包含字符 { 6, 0, 0, 0 } (little-endian)或 { 0, 0, 0, 6 } 的缓冲区>(大端)。这里假设 sizeof (int) == 4 为 true,根据需要调整其他大小,问题仍然存在。

您很可能应该将缓冲区改为unsigned char。另外,如果您这样拨打电话:

int wrote = write(fd, ACK, sizeof ACK);
printf("Wrote %d bytes\n", wrote);

您会得到直接反馈。您应该测试这样的东西,看看写入是否确实成功。

You're giving write() the data argument of ACK, which is a pointer to int. This is probably not what you mean. Depending on the endianness of the computer you're on, this means write() will "see" a buffer containing the chars { 6, 0, 0, 0 } (little-endian) or { 0, 0, 0, 6 } (big-endian). This assumes that sizeof (int) == 4 is true, adjust for other sizes as needed, the problem remains.

You should very probably make the buffer unsigned char instead. Also, if you had made the call like this:

int wrote = write(fd, ACK, sizeof ACK);
printf("Wrote %d bytes\n", wrote);

You would have gotten direct feedback. You should test something like this, to see that the write actually succeeds.

盛夏尉蓝 2024-08-15 01:19:25

激活的硬件流控制(CRTSCTS)是 write() 被阻止并且最终串行输出上没有出现任何内容的原因。

谢谢!

有效的代码快照:

int openSerialDevice(const char* devTTY, struct termios oldTio) {

    //----< Open serial device >----------------------------------
    int fileDescriptor;
    // fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
    fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY);
    //fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY /*| OPOST*/);
    if (fileDescriptor == -1) {
        perror("Error while opening serial interface occurred!");
        return -99;
    }

    // set new parameters to the serial device
    struct termios newtio;

    fcntl(fileDescriptor, F_SETFL, 0);
    // set everything to 0
    bzero(&newtio, sizeof(newtio));

    // again set everything to 0
    bzero(&newtio, sizeof(newtio));

    newtio.c_cflag |= BAUDRATE; // Set Baudrate first time
    newtio.c_cflag |= CLOCAL; // Local line - do not change "owner" of port
    newtio.c_cflag |= CREAD; // Enable receiver

    newtio.c_cflag &= ~ECHO; // Disable echoing of input characters
    newtio.c_cflag &= ~ECHOE;

    // set to 8N1
    newtio.c_cflag &= ~PARENB; // no parentybyte
    newtio.c_cflag &= ~CSTOPB; // 1 stop bit
    newtio.c_cflag &= ~CSIZE; // Mask the character size bits
    newtio.c_cflag |= CS8; // 8 data bits

    // output mode to
    newtio.c_oflag = 0;
    //newtio.c_oflag |= OPOST;


    // Set teh baudrate for sure
    cfsetispeed(&newtio, BAUDRATE);
    cfsetospeed(&newtio, BAUDRATE);

    newtio.c_cc[VTIME] = 10; /* inter-character timer  */
    newtio.c_cc[VMIN] = 0; /* blocking read until  */

    tcflush(fileDescriptor, TCIFLUSH); // flush pending data

    // set the new defined settings
    if (tcsetattr(fileDescriptor, TCSANOW, &newtio)) {
        perror("could not set the serial settings!");
        return -99;
    }

    //----< / Open serial device >----------------------------------
    return fileDescriptor;
}

The activated Hardware-Flow-Control (CRTSCTS) was the reason why write() blocked and finally nothing has appeared on the serial output.

thanks!

Code snap which works:

int openSerialDevice(const char* devTTY, struct termios oldTio) {

    //----< Open serial device >----------------------------------
    int fileDescriptor;
    // fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
    fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY);
    //fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY /*| OPOST*/);
    if (fileDescriptor == -1) {
        perror("Error while opening serial interface occurred!");
        return -99;
    }

    // set new parameters to the serial device
    struct termios newtio;

    fcntl(fileDescriptor, F_SETFL, 0);
    // set everything to 0
    bzero(&newtio, sizeof(newtio));

    // again set everything to 0
    bzero(&newtio, sizeof(newtio));

    newtio.c_cflag |= BAUDRATE; // Set Baudrate first time
    newtio.c_cflag |= CLOCAL; // Local line - do not change "owner" of port
    newtio.c_cflag |= CREAD; // Enable receiver

    newtio.c_cflag &= ~ECHO; // Disable echoing of input characters
    newtio.c_cflag &= ~ECHOE;

    // set to 8N1
    newtio.c_cflag &= ~PARENB; // no parentybyte
    newtio.c_cflag &= ~CSTOPB; // 1 stop bit
    newtio.c_cflag &= ~CSIZE; // Mask the character size bits
    newtio.c_cflag |= CS8; // 8 data bits

    // output mode to
    newtio.c_oflag = 0;
    //newtio.c_oflag |= OPOST;


    // Set teh baudrate for sure
    cfsetispeed(&newtio, BAUDRATE);
    cfsetospeed(&newtio, BAUDRATE);

    newtio.c_cc[VTIME] = 10; /* inter-character timer  */
    newtio.c_cc[VMIN] = 0; /* blocking read until  */

    tcflush(fileDescriptor, TCIFLUSH); // flush pending data

    // set the new defined settings
    if (tcsetattr(fileDescriptor, TCSANOW, &newtio)) {
        perror("could not set the serial settings!");
        return -99;
    }

    //----< / Open serial device >----------------------------------
    return fileDescriptor;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文