在linux C程序中可以写入,但不能从串口ttyS0读取 [英] Can write to, but can't read from serial port ttyS0 in linux C program

查看:82
本文介绍了在linux C程序中可以写入,但不能从串口ttyS0读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何使用 C 在 Linux 中对 ttyS0 串行端口进行编程.我有另一台机器连接到我的串行端口,大约每两秒发送 5f 和 6f 的交替十六进制值.我已经与其他端口监控应用程序验证了这些值出现在端口上.在我的代码中,我将阻塞 read() 用于 10 个字符长度的缓冲区.即使我的另一台机器仍在发送数据,read() 将永远阻塞.如果我包含将 read() 设置为非阻塞 read() 的行 fcntl(fd, F_SETFL, FNDELAY); 总是以 -1 的值返回,这意味着 UART 缓冲区中没有数据,而我的 for 循环代码只是打印出缓冲区中的随机值.所以简而言之,我的假设是我的代码没有读取 ttyS0,我不知道为什么.下面是我的代码,希望有人会看到是什么导致了我的问题并让我直截了当.顺便说一句,我使用的是 Scientific Linux,我相信 ttyS0 是 com 端口 1,就像在 RedHat 和 Fedora 中一样.下面是我运行代码时的输出.它似乎可以毫无问题地写入 COM 端口,但读取时却说它不可用.另外很明显,我打印出的缓冲区只是随机值,而不是已读入的数据.谢谢

I'm trying to learn how to program the ttyS0 serial port in Linux using C. I have another machine connected to my serial port sending alternating hex values of 5f and 6f about every two seconds. I've verified with other port monitoring apps that these values are appearing at the port. In my code I'm using a blocking read() into a 10 char length buffer. Even though my other machine is still sending data, read() blocks forever. If I include the line fcntl(fd, F_SETFL, FNDELAY); which sets read() to non-blocking read() always returns with a value of -1, meaning no data was in the UART buffer, and my for loop code just prints out random values that are in the buffer. So in short my assumption is that my code is not reading ttyS0 and I have no idea why. Below is my code, hopefully someone will see what's causing my problem and set me straight. By the way, I'm using Scientific Linux, I believe ttyS0 is com port 1, as it is in RedHat and Fedora. Aslo below is the output when i run the code. It seems to be writing to the COM port with no problems, but for a read it says its unavailable. Also it's clear that the buffer I'm printing out is just random values not data that's been read in. Thanks

hello world
hi again
write error: : Success
 wrote 4 bytes
number of bytes read is -1
read error:: Resource temporarily unavailable
4  8  120  -99  -73  -65  41  -120  4  8  
should of put something out

代码

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>

int main()
{
    printf("hello world\n");
    int n;
    int fd;
    char c;
    int bytes;

    char buffer[10];
    char *bufptr;
    int nbytes;
    int tries;
    int x;
    struct termios options;


    fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd == -1)
    {
        perror("open_port: Unable to open:");
    }
    else
    {
        fcntl(fd, F_SETFL, 0);
        printf("hi again\n");
    }

    tcgetattr(fd, &options);

    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    options.c_cflag &= ~( ICANON | ECHO | ECHOE |ISIG );
    options.c_iflag &= ~(IXON | IXOFF | IXANY );
    options.c_oflag &= ~OPOST;

    tcsetattr(fd, TCSANOW, &options);


    write(fd, "ATZ\r",4);
    printf(" wrote\n");
    bufptr = buffer;


    fcntl(fd, F_SETFL, FNDELAY);
     bytes = read(fd, bufptr, sizeof(buffer));
    printf("number of bytes read is %d\n", bytes);
    perror ("read error:");

    for (x = 0; x < 10 ; x++)
    {
        c = buffer[x];
        printf("%d  ",c);
    }
    close(fd);

    //puts(buffer[0]);
    printf("\nshould of put something out \n");

    return (0);
}

推荐答案

尝试设置 MIN 和/或 TIME 值:

Try setting MIN and/or TIME values:

/*...*/
options.c_cc[VMIN] = 1; //read() will return after receiving 1 character
options.c_cc[VTIME] = 0; // == 0 - infinite timeout, != 0 - sets timeout in deciseconds
/*...*/
tcsetattr(fd, TCSANOW, &options);

给定的示例将设置您的 read() 在获取任何符号后返回并无限期地等待输入.当然,您可以根据需要使用这些参数(例如,如果需要,可以将 MIN 设置为 10).

The given example will set your read() to return after getting any symbol and to wait indefinitely for input. Naturally, you may play with these parameters as you see fit (e.g. set MIN to 10 if you want).

您可能希望删除 fcntl(fd, F_SETFL, FNDELAY); 调用以使其正常工作.

You may want to remove fcntl(fd, F_SETFL, FNDELAY); call for this to work though.

在离开程序之前保存之前的 termios 设置并恢复它们也是明智之举.

It is also wise to save previous termios settings and restore them before leaving your program.

这篇关于在linux C程序中可以写入,但不能从串口ttyS0读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆