Linux下多路复用式串口操作

来源:互联网 发布:seo在哪里可以自学 编辑:程序博客网 时间:2024/06/05 01:18
1.实验目的

  通过编写多路复用式串口读写,进一步理解多路复用函数的用法,同时更加熟练地掌握Linux设备文件的读写方法。

  2.实验内容

  本实验中,实现两台机器(宿主机和目标板)之间的串口通信,而且每台机器均可以发送数据和接收数据。 除了串口设备名称不同(宿主机上使用串口1:/dev/ttyS0,而在目标板上使用串口2:/dev/ttyS1),两台机器上的程序基本相同。

  首先,程序打开串口设备文件并进行相关配置,调用select()函数,使它等待从标准输入(终端)文件中的输入数据及从串口设备的输入数据。如果有标准输入文件上的数据,则写入到串口,使对方读取。如果有串口设备上的输入数据,则将数据写入到普通文件中。

  3.实验步骤

  (1)画出流程图。图2.6所示为程序流程图,两台机器上的程序使用同样的流程图。


  图2.6 宿主机/目标板程序的流程图

  (2)编写代码。编写宿主机和目标板上的代码,在这些程序中用到的open_port()和set_com_config()函数请参照后续章节所述,这里只列出宿主机上的代码。

  /* com_host.c */
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <string.h>
  #include <fcntl.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <errno.h>
  #include "uart_api.h"

  int main(void) 
  {
  int fds[SEL_FILE_NUM], recv_fd, maxfd;
  char buff[BUFFER_SIZE];
  fd_set inset,tmp_inset;
  struct timeval tv;
  unsigned loop = 1;
  int res, real_read, i;
  /* 将从串口读取的数据写入到这个文件中 */
  if ((recv_fd = open(RECV_FILE_NAME, O_CREAT|O_WRONLY, 0644)) < 0)
  { 
  perror("open");
  return 1;
  }

  fds[0] = STDIN_FILENO; /* 标准输入 */
  if ((fds[1] = open_port(HOST_COM_PORT)) < 0) /* 打开串口 */
  {
  perror("open_port");
  return 1;
  }

  if (set_com_config(fds[1], 115200, 8, 'N', 1) < 0) /* 配置串口 */
  {
  perror("set_com_config");
  return 1;
  }

  FD_ZERO(&inset); 
  FD_SET(fds[0], &inset);
  FD_SET(fds[1], &inset);
  maxfd = (fds[0] > fds[1])?fds[0]:fds[1];
  tv.tv_sec = TIME_DELAY;
  tv.tv_usec = 0;
  printf("Input some words(enter 'quit' to exit):\n");
  while (loop && (FD_ISSET(fds[0], &inset) || FD_ISSET(fds[1], &inset)))
  { 
  tmp_inset = inset;
  res = select(maxfd + 1, &tmp_inset, NULL, NULL, &tv);
  switch(res)
  {
  case -1: /* 错误 */
  {
  perror("select");
  loop = 0;
  }
  break;

  case 0: /* 超时 */
  {
  perror("select time out");
  loop = 0;
  }
  break;

  default:
  {
  for (i = 0; i < SEL_FILE_NUM; i++)
  {
  if (FD_ISSET(fds[i], &tmp_inset))
  {
  memset(buff, 0, BUFFER_SIZE);
  /* 读取标准输入或者串口设备文件 */
  real_read = read(fds[i], buff, BUFFER_SIZE);
  if ((real_read < 0) && (errno != EAGAIN))
  {
  loop = 0;
  }
  else if (!real_read)
  {
  close(fds[i]);
  FD_CLR(fds[i], &inset);
  }
  else
  { 
  buff[real_read] = '\0';
  if (i == 0)
  { /* 将从终端读取的数据写入到串口 */
  write(fds[1], buff, strlen(buff));
  printf("Input some words
  (enter 'quit' to exit):\n");
  }
  else if (i == 1)
  { /* 将从串口读取的数据写入到普通文件中 */
  write(recv_fd, buff, real_read);
  }
  if (strncmp(buff, "quit", 4) == 0)
  { /* 如果读取为quit则退出 */
  loop = 0;
  } 
  }
  } /* end of if FD_ISSET */
  } /* for i */
  } 
  } /* end of switch */
  } /* end of while */
  close(recv_fd); 
  return 0;
  } 

  (3)接下来,将目标板的串口程序交叉编译,再将宿主机的串口程序在PC上编译。

  (4)连接PC的串口1和开发板的串口2,然后将目标板串口程序下载到开发板上,分别在两台机器上运行串口程序。

  4.实验结果

  宿主机上的运行结果如下所示:

  $ ./com_host 
  Input some words(enter 'quit' to exit):
  Hello, Target!
  Input some words(enter 'quit' to exit):
  I'm host program!
  Input some words(enter 'quit' to exit):
  Byebye!
  Input some words(enter 'quit' to exit):
  quit /* 这个输入使双方的程序都结束 */ 

  从串口读取的数据(即目标板中发送过来的数据)写入到同目录下的recv.dat文件中。

  $ cat recv.dat 
  Hello, Host!
  I'm target program!
  Byebye! 

  目标板上的运行结果如下所示:

  $ ./com_target 
  Input some words(enter 'quit' to exit):
  Hello, Host!
  Input some words(enter 'quit' to exit):
  I'm target program!
  Input some words(enter 'quit' to exit):
  Byebye! 

  与宿主机上的代码相同,从串口读取的数据(即目标板中发送过来的数据)写入到同目录下的recv.dat文件中。

  $ cat recv.dat 
  Hello, Target!
  I'm host program!
  Byebye!
  Quit 

  请读者用poll()函数实现具有以上功能的代码。

  本文选自华清远见嵌入式培训教材《从实践中学嵌入式Linux应用程序开发》
0 0
原创粉丝点击