⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux串口通信示例子.txt

📁 linux下的串口通信程序详细示例 详细解释了更种串口通信所需的系统调用
💻 TXT
📖 第 1 页 / 共 2 页
字号:
#include  
#include  
#include  

#define BAUDRATE B38400 
#define MODEMDEVICE "/dev/ttyS1" 
#define _POSIX_SOURCE 1 /* POSIX 系统相容 */ 
#define FALSE 0 
#define TRUE 1 

volatile int STOP=FALSE;  

main() 
{ 
  int fd,c, res; 
  struct termios oldtio,newtio; 
  char buf[255]; 

 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );  
 if (fd <0) {perror(MODEMDEVICE); exit(-1); } 

 tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定 */ 

 bzero(&newtio, sizeof(newtio)); 
 newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; 
 newtio.c_iflag = IGNPAR; 
 newtio.c_oflag = 0; 

 /* 设定输入模式 (非标准型, 不回应,...) */ 
 newtio.c_lflag = 0; 
  
 newtio.c_cc[VTIME]    = 0;   /* 不使用分割字元组计时器 */ 
 newtio.c_cc[VMIN]     = 5;   /* 在读取到 5 个字元前先停止 */ 

 tcflush(fd, TCIFLUSH); 
 tcsetattr(fd,TCSANOW,&newtio); 


 while (STOP==FALSE) {       /* 输入回圈 */ 
   res = read(fd,buf,255);   /* 在输入 5 个字元後即返回 */ 
   buf[res]=0;               /* 所以我们能用 printf... */ 
   printf(":%s:%d\n", buf, res); 
   if (buf[0]=='z') STOP=TRUE; 
 } 
 tcsetattr(fd,TCSANOW,&oldtio); 
} 


3.3 非同步式输入  

#include  
#include  
#include  
#include  
#include  
#include  

#define BAUDRATE B38400 
#define MODEMDEVICE "/dev/ttyS1" 
#define _POSIX_SOURCE 1 /* POSIX 系统相容 */ 
#define FALSE 0 
#define TRUE 1 

volatile int STOP=FALSE;  

void signal_handler_IO (int status);   /* 定义讯号处理程序 */ 
int wait_flag=TRUE;                    /* 没收到讯号的话就会是 TRUE */ 

main() 
{ 
  int fd,c, res; 
  struct termios oldtio,newtio; 
  struct sigaction saio;           /* definition of signal action */ 
  char buf[255]; 

  /* 开启装置为 non-blocking (读取功能会马上结束返回) */ 
  fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK); 
  if (fd <0) {perror(MODEMDEVICE); exit(-1); } 

  /* 在使装置非同步化前, 安装讯号处理程序 */ 
  saio.sa_handler = signal_handler_IO; 
  saio.sa_mask = 0; 
  saio.sa_flags = 0; 
  saio.sa_restorer = NULL; 
  sigaction(SIGIO,&saio,NULL); 
   
  /* 允许行程去接收 SIGIO 讯号*/ 
  fcntl(fd, F_SETOWN, getpid()); 
  /* 使档案ake the file descriptor 非同步 (使用手册上说只有 O_APPEND 及 
  O_NONBLOCK, 而 F_SETFL 也可以用...) */ 
  fcntl(fd, F_SETFL, FASYNC); 

  tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定值 */ 
  /* 设定新的序列埠为标准输入程序 */ 
  newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; 
  newtio.c_iflag = IGNPAR | ICRNL; 
  newtio.c_oflag = 0; 
  newtio.c_lflag = ICANON; 
  newtio.c_cc[VMIN]=1; 
  newtio.c_cc[VTIME]=0; 
  tcflush(fd, TCIFLUSH); 
  tcsetattr(fd,TCSANOW,&newtio); 
  
  /* 等待输入讯号的回圈. 很多有用的事我们将在这做 */  
  while (STOP==FALSE) { 
    printf(".\n");usleep(100000); 
    /* 在收到 SIGIO 後, wait_flag = FALSE, 输入讯号存在则可以被读取 */ 
    if (wait_flag==FALSE) {  
      res = read(fd,buf,255); 
      buf[res]=0; 
      printf(":%s:%d\n", buf, res); 
      if (res==1) STOP=TRUE; /* 如果只输入 CR 则停止回圈 */ 
      wait_flag = TRUE;      /* 等待新的输入讯号 */ 
    } 
  } 
  /* 回存旧的序列埠设定值 */ 
  tcsetattr(fd,TCSANOW,&oldtio); 
} 

/*************************************************************************** 
* 讯号处理程序. 设定 wait_flag 为 FALSE, 以使上述的回圈能接收字元          * 
***************************************************************************/ 

void signal_handler_IO (int status) 
{ 
  printf("received SIGIO signal.\n"); 
  wait_flag = FALSE; 
} 


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 会马上结束返回.  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -