c - 串行 c 在 linux 中读取有问题

标签 c linux arduino serial-port

我正在尝试使用 Odroid(单机板)在 C 中读取串口以通过 USB 电缆从 arduino 板获取数据。正在发布传感器数据的是 189。波特率为115200。

读取使用的主要代码:

#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/ipc.h>
#include <sys/shm.h>
#include "share.h"
#include <math.h>
#include <stdlib.h>
#pragma GCC diagnostic ignored "-Wwrite-strings"

/*
 * @brief Open serial port with the given device name
 *
 * @return The file descriptor on success or -1 on error.
 */
int open_port(char *port_device)
{
    int fd; /* File descriptor for the port */

    fd = open(port_device, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1)
    {
        perror("open_port: Unable to open /dev/Servo_LIDAR ");
    }
    else
        fcntl(fd, F_SETFL, 0);

    return (fd);
}

int main()
{

//--------------------------------------------------------------------------------
    struct termios options;
    int fd=-1;
    char *u_port = "/dev/Servo_LIDAR";
    fd=open_port(u_port);
    if(fd==-1)
    {
       printf("port not open");
       return -1;
    }

    tcgetattr(fd, &options);
    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);

    //Enable the receiver and set local mode...
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~CSIZE; /* Mask the character size bits */
    options.c_cflag |= CS8; /* Select 8 data bits */

    //No parity
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    //Set the new options for the port...
    tcsetattr(fd, TCSANOW, &options);


    printf("Reading...\n"); 

   while(true) 
  {


    while(1)
    {       
        //sleep(0.5);
        char buff[1024]={0};
        char buf[1]={0};
        while(1) {  
           ssize_t res=read(fd, buf, 1);

           if(res==0) continue;  
           buf[res]=0;  

           strcat(buff,buf);
           if (buf[0] == '\n')  break; 
      }  
      printf("%s\n", buff); 
      usleep(70000);
    break;
    }
 }

    close(fd);


}

我有这样的约会:

187

187187187

188

188188

188188188

188

1888

188

18188

188

186187

187

187

每次应该是 3 个字节的数据,但我遇到了这样的问题。任何建议,谢谢。

最佳答案

您的主要错误涉及语句:

    char buf[1]={0};
...  
       ssize_t res=read(fd, buf, 1);
...
       buf[res]=0;  

数组 buf[] 被声明为只有 一个 元素长,即 buf[0] 是数组的唯一元素.
read() 系统调用在成功时将返回值 1,因为这是指定的计数。
然后您尝试通过写入 buf[1] 来终止接收到的文本,但那是一个尚未分配的元素。
数组 buf[] 需要至少包含 2 个元素。

此错误的症状会因编译器和主机系统而异。在使用 gcc 4.8.4 的 x86 笔记本电脑上,您的原始程序根本不产生任何输出。

有关终止缓冲区数据的首选方法,请参阅 Linux Serial Read throws Error


代码审查

  1. 所有系统调用,包括tc[gs]etattr()read(),都应该检查错误返回代码,尤其是当您的程序没有表现如你所愿。

  2. 您的termios 配置不完整。您的程序将以任何先前配置的规范或非规范模式执行。这可能会产生意想不到的结果。

  3. 一次只读取一个字符(嵌套在多个 while 循环中)效率低下。规范读取可以为每个系统调用返回一行。学习"Two Styles of Input: Canonical or Not"

  4. usleep(70000) 等程序延迟是多余的。文件/设备已打开以阻止读取,因此 read() 在数据可用之前不会返回。

关于c - 串行 c 在 linux 中读取有问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36589454/

相关文章:

c - 重复调用的函数中的静态变量 C

linux - 某些命令无法通过 ssh(shell)在远程服务器上运行

javascript - 使用 Python 从 Arduino 读取串行数据

c++ - 一次移动多个无符号字符以便它们从一个字符流向另一个字符的最快方法是什么?

php - 如何确定一个列表是否是另一个列表的子集?

c - 这个基本的 C 程序总是得到错误的答案,特别是 x 总是 0,y 的值是正确的

c - STM32 USB CDC 不工作

linux - 使用 system() API 时 rpm 安装后脚本失败

linux - Linux 和 OS X 上的 Sqlite 数据文件不兼容?

c++ - 如何将cpp文件添加到arduino项目?