【问题标题】:Linux Reading Data from UARTLinux 从 UART 读取数据
【发布时间】:2016-10-23 00:05:59
【问题描述】:

我想从 UART 读取数据,我关注了this tutorial,写入功能按预期工作,但是我遇到了读取功能的问题:

这是 uart_init 函数:

void uart_init()
{
 printf("\n +----------------------------------+");
 printf("\n |        Serial Port Write         |");
 printf("\n +----------------------------------+");

/*------------------------------- Opening the Serial Port -------------------------------*/

  fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY| O_SYNC);      /* !!blocks the read  */
                                                            /* O_RDWR Read/Write access to serial port           */
                                                            /* O_NOCTTY - No terminal will control the process   */
                                                            /* O_NDELAY -Non Blocking Mode,Does not care about-  */
                                                            /* -the status of DCD line,Open() returns immediatly */                                        
                                
 if(fd == -1)                                               /* Error Checking */
  printf("\n  Error! in Opening ttyUSB0  ");
 else
  printf("\n  ttyUSB0 Opened Successfully ");


 /*---------- Setting the Attributes of the serial port using termios structure --------- */
    
struct termios SerialPortSettings;          /* Create the structure                          */

tcgetattr(fd, &SerialPortSettings);         /* Get the current attributes of the Serial port */

cfsetispeed(&SerialPortSettings,B19200);        /* Set Read  Speed as 19200                       */
cfsetospeed(&SerialPortSettings,B19200);        /* Set Write Speed as 19200                       */

SerialPortSettings.c_cflag &= ~PARENB;          /* Disables the Parity   Enable bit(PARENB),So No Parity   */
SerialPortSettings.c_cflag &= ~CSTOPB;          /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
SerialPortSettings.c_cflag &= ~CSIZE;           /* Clears the mask for setting the data size             */
SerialPortSettings.c_cflag |=  CS8;             /* Set the data bits = 8                                 */

SerialPortSettings.c_cflag &= ~CRTSCTS;         /* No Hardware flow Control                         */
SerialPortSettings.c_cflag |= CREAD | CLOCAL;   /* Enable receiver,Ignore Modem Control lines       */ 
    
    
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);          /* Disable XON/XOFF flow control both i/p and o/p */
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /* Non Cannonical mode                            */

SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/

/* Setting Time outs */
SerialPortSettings.c_cc[VMIN] = 10; /* Read at least 10 characters */
SerialPortSettings.c_cc[VTIME] = 0; /* Wait indefinetly   */

if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/
 printf("\n  ERROR ! in Setting attributes");
else
 printf("\n  BaudRate = 19200 \n  StopBits = 1 \n  Parity   = none");
        
}

接收函数:

void uart_receive()
{
 char read_buffer[32];   /* Buffer to store the data received              */
 int  bytes_read = 0;    /* Number of bytes read by the read() system call */
 int i = 0;

 bytes_read = read(fd,&read_buffer,10); /* Read the data                   */
        
 printf("\n\n  Bytes Rxed %d", bytes_read); /* Print the number of bytes read */
 printf("\n\n  ");

 for(i=0;i<bytes_read;i++)   /*printing only the received characters*/
 printf("%c",read_buffer[i]);

 printf("\n +----------------------------------+\n\n\n");
}

主要功能:

void main(void)
{ 
  uart_init();
  /*------------------------------- Write data to serial port -----------------------------*/
  //uart_write_commande(write_buffer); //Write function works well
  uart_receive();

  close(fd);/* Close the Serial port */
}

我执行程序并等待 UART 接收到数据字节,我使用 UART 发送数据但读取功能一直被阻塞。

我正在使用带有 Ubunutu 14.04 的虚拟机,我不确定使用模拟 UART 是否会在接收期间引起问题。

【问题讨论】:

  • 我可以向您推荐一个好的库,它是开源的,因此您也可以从代码中获取灵感:library link
  • 具体问题是什么?
  • @Olaf 程序卡在读取函数中,我通过 UART 发送数据,但程序没有离开读取函数
  • 请在正文中添加此类信息和问题!
  • 使用O_NONBLOCK打开你的文件,然后寻找读取函数的返回值。如果是-1,那么read here关于为什么

标签: c linux uart


【解决方案1】:

您的程序在 read() 系统调用中挂起,因为它在等待行终止符时被阻塞。
您尝试使用以下语句将端口配置为非规范模式

SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /* Non Cannonical mode  

但该操作是在错误的 termios 元素上进行的。
ICANON 属性是 lflag 元素的一部分(而不是 iflag)。 (此错误源于您引用的教程!)
因此,您的程序正在执行阻塞规范读取。

有一个方便的 termios 函数用于配置非规范模式:

   cfmakeraw()  sets the terminal to something like the "raw" mode of the old 
   Version 7 terminal driver: input is available character by
   character, echoing is disabled, and all special processing of  
   terminal  input  and  output  characters  is  disabled.   The  terminal
   attributes are set as follows:

       termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
                       | INLCR | IGNCR | ICRNL | IXON);
       termios_p->c_oflag &= ~OPOST;
       termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
       termios_p->c_cflag &= ~(CSIZE | PARENB);
       termios_p->c_cflag |= CS8;

【讨论】:

  • 你说的很对,看来这是问题的根源,我试试这个配置,更新状态
  • 最终的解决方案是什么>?有人可以发帖吗?
  • @Raulp -- 有关使用 cfmakeraw() 的示例代码,请参阅 stackoverflow.com/questions/12437593/…
【解决方案2】:

读取函数出错

bytes_read = read(fd,&read_buffer,10); /* Read the data 

应该是

bytes_read = read(fd,read_buffer,10); /* Read the data 

【讨论】:

  • @lllishar,我改了,但问题依然存在
  • @fedi - 具体说明问题。您看到了什么错误消息或行为?
  • @Illishar 你错了! read_buffer 是一个数组,所以它也是一个指向数组第一个成员的指针。无需在前面加上&amp;
【解决方案3】:

无论出于何种原因,您的 read() 函数都可能被阻止。 Here is a discussion 从串行端口读取,包括用于阻止/未阻止设置的代码。

也有可能没有数据正在传输,导致没有任何数据被读取。如果无法访问硬件设置,如果没有关于您所看到的非常具体的信息,就很难走得更远。

此外,除了正确传递 read_buffer(另一个答案)之外,至少还有两件事可以改进:

1)使用前检查read的返回:

bytes_read = read(fd,&read_buffer,10); /* Read the data*/
if(bytes_read > 0)
{
    ...
}

2) 改变:

for(i=0;i<bytes_read;i++)   /*printing only the received characters*/
 printf("%c",read_buffer[i]);

收件人:

//after successful read:
read_buffer[bytes_read]=0;//place null termination after last character read.
printf("%s",read_buffer);//note format specifier

这将打印读取的字符数,没有循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多