首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RaspberryPi RS-232故障

RaspberryPi RS-232故障
EN

Stack Overflow用户
提问于 2013-09-28 22:49:10
回答 2查看 465关注 0票数 1

我使用我的Pi上的RS-232线与激光测距仪通信.我已经测试了两个使用minicom的波特率为19200的通信(因为这是LRF的波特率,不能更改),而且它工作得很好。尽管向LRF写入任何命令(由单个字符组成并按下'enter')可能需要几次尝试才能生效,但两个方向的通信都非常有效。

然而,当我开始用C代码编程用RS-232进行读写时,它只工作了一半。下面是我使用的代码:

代码语言:javascript
复制
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>

//SETUP UART0

int main(){
    int uart0_filestream = -1;
    int loop;
    int i;
    int isError=1, rx_length;
    unsigned char rx_buffer[256];
    useconds_t micro=3000;

    uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);

    if(uart0_filestream == -1)
        printf("ERROR: Unable to open UART\n\n");
    else
        printf("UART open\n\n");

    struct termios options;

    tcgetattr(uart0_filestream, &options);
    options.c_cflag = B19200 | CS8 | CLOCAL | CREAD;
    options.c_iflag = IGNPAR | ICRNL;
    options.c_oflag = 0;
    options.c_lflag = 0;

    tcflush(uart0_filestream, TCIFLUSH);
    tcsetattr(uart0_filestream, TCSANOW, &options);

    unsigned char tx_buffer[20];
    unsigned char *p_tx_buffer;

    p_tx_buffer = &tx_buffer[0];
    *p_tx_buffer++ = 'o';
    *p_tx_buffer++ = '\n';

    /*
    if(uart0_filestream != -1){
        for(i = 0; i<100; i++){
            int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0]));
            if(count < 0)
                printf("\n\nERROR: No bytes written\n\n");
            else
                printf("%i bytes written: %s\n", (p_tx_buffer - &tx_buffer[0]), tx_buffer);
        }
    }
    */
    if(uart0_filestream != -1){
        for(i=0; i<50; ){
            rx_length = read(uart0_filestream, (void*)rx_buffer, 255);

            if(rx_length > 0){
                printf("rx_lentgh = %i:\t ", rx_length);
                for(loop=0; loop<30; loop++){
                    //check for NULL and new line for easier readability
                    if(rx_buffer[loop] == NULL)
                        rx_buffer[loop] = '$';
                    if(rx_buffer[loop] == '\n')
                        rx_buffer[loop] = '%';
                    printf("%c", rx_buffer[loop]);
                }
                printf("\n");
                i++;
            }
        }
    }

    close(uart0_filestream);
}

当我尝试从设备读取时,它总是返回一个错误。我开始循环,看看持续阅读是否会产生不同的结果。在这100次尝试中,通常是4-5返回数据,其余的irx_length/i返回-1。返回的数据应该如下所示:

计数:0000

数字取决于LRF测量的距离。但相反,我得到了这样的输出:

rx_lentgh = 16: jR$COUNTS:0000%$0000%$ rx_lentgh = 8:%$COUNTSTS:0000%$ rx_lentgh = 16::0142%美元计数:0$0$ rx_lentgh = 8: 000%$COCOUNTS:$0$ rx_lentgh = 16: UNTS:0142%$COUN$ rx_lentgh = 24: TS:0142%计数:0000%$ rx_lentgh = 8:计数:0%$计数:0000%$ rx_lentgh = 16: 142%计算:$2000:0000%$ rx_lentgh = 16: 0%$计数:0142%:0000%$ rx_lentgh = 8:%$COUNTSTS:0142%:0000%$ rx_lentgh = 8: 0000%$TS:0142%:0000%$ rx_lentgh = 8:计数:0TS:0142%:0000%$ rx_lentgh = 24: 142%$COUN:0142%$COUN$ rx_lentgh = 8: TS:0000%UNTS:0142%$COUN$ rx_lentgh = 16:%$COUN:0000%$2%$COUN$ rx_lentgh = 8:计数:0:0000%%2%$COUN$ rx_lentgh = 16: 142%统计:0002%$COUN$ rx_lentgh = 8: 0%$COUN:0002%$COUN$ rx_lentgh = 16: TS:0142%$COUNTS2 2%$COUN$ rx_lentgh = 8: 0000%$$%$COUN 2%$$COUN$ rx_lentgh = 16:计数:0142%$CO2%$COUN$ rx_lentgh = 8: UNTS:000142%$CO2%%$COUN$ rx_lentgh = 24: 0%$计数:0142%$计算$ rx_lentgh = 16::0000%计算$计数:0%计算$ rx_lentgh = 24: 142%$COUN:0142%$COUN$ rx_lentgh = 8: TS:0000%UNTS:0142%$COUN$ rx_lentgh = 16:%$COUN:0142%$2%$COUN$

代码语言:javascript
复制
**The above is edited in my code for readability. A NULL character is replaced with '$' and a '\n' is replaced with '%'

你可以看到,每次它得到数据,它至少得到一部分良好的阅读,偶尔整件事情。但里面有很多垃圾。您可以在我的代码中看到,我过滤掉了在错误中返回的所有读取。可能需要1000多条阅读才能得到这么多“好”读物。我真的认为这与时间有关,但即使它是时间,难道我不应该仍然得到等量/我的数据吗?

写作也有同样的问题。一次写什么也做不到。将编写代码循环100次可能会使代码下降到LRF,但是在运行该代码之后,LRF几乎无法工作,而且我也不需要切断电源,让它再次工作并查看minicom中的数据。

LRF可以根据模式以200 on或10 on的频率发送数据包。所有检索到的数据都是在200 the的LRF发送数据包时完成的。

任何帮助都是非常感谢的!在我的其他课程和工作之间,我已经为此工作了好几个星期。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-09-29 04:09:54

您的代码有几个问题。

代码语言:javascript
复制
uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);

您已经为非阻塞I/O设置了端口。

这可能不是你想要的。在返回代码检查后添加以下内容:

代码语言:javascript
复制
fcntl(uart0_filestream, F_SETFL, 0);

为了配置阻塞I/O。

代码语言:javascript
复制
if(uart0_filestream == -1)
    printf("ERROR: Unable to open UART\n\n");

当出现致命错误时,程序应该退出,而不是继续运行。

当syscall返回-1时,还需要检查errno的值。

代码语言:javascript
复制
tcgetattr(uart0_filestream, &options);
  ...
tcsetattr(uart0_filestream, TCSANOW, &options);

应该始终检查syscalls的返回代码。

代码语言:javascript
复制
options.c_cflag = B19200 | CS8 | CLOCAL | CREAD;
options.c_iflag = IGNPAR | ICRNL;
options.c_oflag = 0;
options.c_lflag = 0;

这是对termios成员的错误修改。

只应执行适当的宏和按位操作.请参考Posix串行编程指南

您已经禁用了规范的输入处理,这可能不是您想要做的。

您要读取的输入是带有行终止的ASCII文本,因此使用规范模式让系统解析每一行的末尾。

您现在已经将端口配置为raw模式,用于二进制数据或忽略ASCII控制字符。

有关配置规范模式的示例代码,请参阅这个答案

代码语言:javascript
复制
        rx_length = read(uart0_filestream, (void*)rx_buffer, 255);

同样,当syscall返回-1时,您需要检查errno的值。

read()为您的代码返回-1时,errno可能是EAGAIN,以指示没有可用的数据。

如果指定了阻塞I/O和规范的I/O,而不是原始I/O,那么每个read()将返回完整的输入行。

票数 1
EN

Stack Overflow用户

发布于 2013-09-29 03:43:03

暗示OP误解了数据--看上去相当不错。

推荐重写内环

代码语言:javascript
复制
// for(loop=0; loop<30; loop++)
for(loop=0; loop<rx_length; loop++)

这样做后,效果应该会好得多。诀窍是,read()示例异步地发生在到达的数据上,因此只读取消息的一部分。read()不知道数据包何时结束。它返回的时候,它的全部,错误,或当有一个没有更多的可用数据在那一刻。在read()和包端到达之间没有同步。需要重新整合信息。

同步伪码

代码语言:javascript
复制
i = 0;
length = 0;
forever() {   
  do {
    i += length;
    length = read(&buffer[i])
    if (length means bad read) handle error;
    search buffer from i to (i+length) for End-of-packet
  } while (end-of-packet not found and buffer not too full)
  Use buffer from start to end-of-packet.
  length = i+length-end-of-packet-index
  memmove(&buffer[0], &buffer[end-of-packet-index+1], length);
  i = 0;
}

您可以签入其他read()-like函数,这些函数读取到超时为止。(也许也有不同的open()选项?

其他次要问题

  1. options.c_cflag中有更多的注释来解释选项。
  2. "rx_length“和"rx_lentgh”。
  3. rx_buffer[loop] == NULL是一种糟糕的形式。rx_buffer[loop]charNULL是一个指针。使用rx_buffer[loop] == '\0'
  4. 为了调试的目的,请考虑

代码语言:javascript
复制
// printf("%c", rx_buffer[loop]);
if (isprint(rx_buffer[loop])) {
   printf("%c", rx_buffer[loop]);
}
else {
   printf("(%02hhX)", rx_buffer[loop]);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19072518

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档