浅谈linux下的串口通讯开发

2019-10-13 11:20:14王冬梅

3.4 等待来自多个信号来源的输入

这一段很短. 它只能被拿来当成写程序时的提示, 故范例程序也很简短. 但这个范例不只能用在序列埠上, 还可以用在被当成文档来使用的装置上.

select 呼叫及伴随它所引发的巨集共用 fd_set. fd_set 则是一个位元阵列, 而其中每一个位元代表一个有效的文档叙述结构. select 呼叫接受一个有效的文档叙述结构并传回 fd_set 位元阵列, 而该位元阵列中若有某一个位元为 1, 就表示相对映的文档叙述结构的文档发生了输入, 输出或有例外事件. 而这些巨集提供了所有处理 fd_set 的功能. 亦可参考手册 select(2).

#include 
#include 
#include 

main()
{
  int  fd1, fd2; /* 输入源 1 及 2 */
  fd_set readfs;  /* 文档叙述结构设定 */
  int  maxfd;   /* 最大可用的文档叙述结构 */
  int  loop=1;  /* 回圈在 TRUE 时成立 */ 

  /* open_input_source 开启一个装置, 正确的设定好序列埠,
   并回传回此文档叙述结构体 */
  fd1 = open_input_source("/dev/ttyS1");  /* COM2 */
  if (fd1<0) exit(0);
  fd2 = open_input_source("/dev/ttyS2");  /* COM3 */
  if (fd2<0) exit(0);
  maxfd = MAX (fd1, fd2)+1; /* 测试最大位元输入 (fd) */

  /* 输入回圈 */
  while (loop) {
   FD_SET(fd1, &readfs); /* 测试输入源 1 */
   FD_SET(fd2, &readfs); /* 测试输入源 2 */
   /* block until input becomes available */
   select(maxfd, &readfs, NULL, NULL, NULL);
   if (FD_ISSET(fd1))     /* 如果输入源 1 有信号 */
    handle_input_from_source1();
   if (FD_ISSET(fd2))     /* 如果输入源 2 有信号 */
    handle_input_from_source2();
  }

}  

这个范例程序在等待输入信号出现前, 不能确定它会停顿下来. 如果你需要在输入时加入逾时功能, 只需把 select 呼叫换成:

int res;
struct timeval Timeout;

/* 设定输入回圈的逾时值 */
Timeout.tv_usec = 0; /* 毫秒 */
Timeout.tv_sec = 1; /* 秒 */
res = select(maxfd, &readfs, NULL, NULL, &Timeout);
if (res==0)
/* 文档叙述结构数在 input = 0 时, 会发生输入逾时. */ 

这个程序会在 1 秒钟后逾时. 如果超过时间, select 会传回 0, 但是应该留意 Timeout 的时间递减是由 select 所等待输入信号的时间为基准. 如果逾时的值是 0, select 会马上结束返回.

Linux 环境下使用RS-232接口
RS是英文 "推荐标准"的缩写
232为标识号
RS-485
串口通信表示计算机一次传送一个位的数据,
当使用串行通信时,每个字的数据是一个位一个位的传输或接收的,
每个位不是高电平,就是低电平.
串行通信的速率通常是使用"位/每秒"的方式来表示的,即波特率。
全双工--计算机可以同时收发数据,
它有两个独立的数据通道,一个输入,一个输出,
半双工意味着计算机不能同时收发信息,