Linux 串行读取引发错误 [英] Linux Serial Read throws Error

查看:16
本文介绍了Linux 串行读取引发错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用以下 C 代码从我的串行端口读取数据.我可以成功写入正在监听的计算机(耶!),但读取会引发错误(代码 11 - 资源暂时不可用).我还注意到我的消息/dmesg 日志没有任何有关故障等的信息.所以这很好.

I'm attempting to read from my serial port using the following C code. I can successfully write to a listening computer (yay!) but the read throws Error (Code 11 - Resource temporarily unavailable). I have also noticed my messages/dmesg logs don't have any information regarding faults,etc. So that's good.

//A bunch of INCLUDES exist here....the the code

int fd=0;
int status=0;
int running=1;
char buffer[100];
char message[7];

void main(){
    fd = 1;

    fd=open("/dev/ttyM0",O_RDWR | O_NOCTTY);

    if(fd == -1)
    {
        perror("open_port: Unable to open /dev/ttys0");
    }
    else
    {
        while(running<20)
        {
            sprintf(message,"Test%d
",running);
            status=write(fd,message,6);

            if(status<0)
            {
                printf("Error Writing. Status=%d
 %s
",errno, strerror(errno));
            }
            status=read(fd,buffer,8);  //This throws an error(11). My connected device is writing "Testing/r"

            if(status<0)
            {
                printf("Error Reading. Status=%d 
%s
",errno, strerror(errno));
                //close(fd);
                running=running+1;
            }
            else
            {
                printf("%s

",buffer);
            }
            sleep(2);
        }
        close(fd);
    }

} //END MAIN

这些是我的端口串行设置.我正在尝试以 9600 8 位、无奇偶校验、1 个停止位读取/写入.我认为我的设置是正确的.

These are my serial settings for my port. I'm attempting to read/write at 9600 8bit, No parity, 1 stop bit. I think my settings are correct.

sudo stty -a -F /dev/ttyM0 
speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 1; time = 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

任何帮助将不胜感激.谢谢!

Any help would be very much appreciated. Thank you!

推荐答案

随着 O_NDELAY 的消失,程序只是坐在那里等待输入

With O_NDELAY gone the program just sits there waiting for input

看起来 termios 是为规范输入设置的(基于 stty 输出中的 icanon).在规范(又名熟)模式下,从串行端口接收的字符在使用 read() 提供给用户程序之前进行处理.

Looks like termios is setup for canonical input (based on the icanon in the stty output). In canonical (aka cooked) mode, the characters received from the serial port are processed before being made available to the user program using read().

根据 Linux 手册页:

Per the Linux man page:

在规范模式下:

  • 输入是逐行提供的.输入线可用当键入其中一个行分隔符时(NL、EOL、EOL2;或 EOF 在行首).除 EOF 的情况外,行分隔符包含在 read(2) 返回的缓冲区中.

您的 termios 还设置了 icrnl,这意味着在输入时将回车转换为换行符(除非设置了 igncr,这不是,因为它前面有一个连字符).eoleol2 都未定义(这是默认值).

Your termios also has icrnl set, which means that a carriage return is translated to newline on input (unless igncr is set, which is not since it has a preceding hyphen). Both eol and eol2 are undefined (which are the default values).

因此,对于您的设置,行尾定义为换行符或回车符(或行首的 cntl-D).验证您的远程设备是否实际发送 CR 或 LF 控制字符来终止线路.您在代码中的注释表明它不是(即/r"不是回车).

So for your setup, an end-of-line is defined as a newline or a carriage return (or cntl-D at the start of the line). Verify that your remote device is actually sending a CR or LF control character to terminate the line. Your comment in the code indicates that it is not (i.e. "/r" is not a carriage return).

要正确使用 read() 返回的文本作为字符串,请将请求设置为比分配的缓冲区大小小一(以确保附加空终止符的空间).然后在返回好之后,将返回的字节数作为索引来存储字符串终止符.

To properly use the text returned by read() as a string, set the request for one less than the allocated buffer size (to ensure room for appending a null terminator). Then after a good return, use the returned byte count as the index to store the string terminator.

        status = read(fd, buffer, sizeof(buffer) - 1);  
        if (status < 0) {
            /* handle error condition */
        } else {
            buffer[status] = '';
            printf("%s

", buffer);
        }

这篇关于Linux 串行读取引发错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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