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

📄 c_serial.c

📁 linux/unix下的串行口操作测试程序(C语言)
💻 C
字号:
/* ******************************************************************** */
/*	UNIX串行口操作接口						*/
/* ******************************************************************** */

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#ifndef M_UNIX
  #include <sys/time.h>
#endif
#include <sys/ioctl.h>
#include <sys/termios.h>
#include <sys/select.h>


static	int	s2comid;		/* 串行口设备句柄 */
static	int	s2istty;		/* 是否由应用程序打开了设备 */
static	struct	termios   s2orgtm;	/* 原始的属性,关闭时恢复 */


#ifdef DEBUG_S
/*
 * 16进制显示一个字符串
 */
void DebugStr(char *buf, int len, char chFlag)
{
  while (len-- > 0) {
    fprintf(stderr, "%c%02X ", chFlag, (u_char)*buf++);
  }
}
#endif


/*
 * 由应用程序打开了设备, 因此, OpenDevice就不必打开了
 */
void com_Attach(int hnd)
{
  s2comid = hnd;
}


/*
 * 打开指定的串口设备
 * 如果devname=NULL则直接使用s2comid的当前值; speed=-1则不设置速率
 * 返回:该设备句柄,-1表示不能打开
 */
int com_OpenDevice(char *devname, long speed)
{
  struct termios  tm;

  s2istty = (devname==NULL);
  if (devname != NULL)  s2comid = open(devname, 2);
  if (s2comid != -1) {
    ioctl(s2comid, TCGETA, &s2orgtm);
    memcpy(&tm, &s2orgtm, sizeof(tm));

    tm.c_iflag = 0;
    tm.c_oflag = 0;
    tm.c_lflag = 0;
    tm.c_cflag = CS8|HUPCL;
    tm.c_cc[VMIN]  = 1;

    if (speed != -1) {
      tm.c_cflag &= ~CBAUD;
      switch (speed) {
      case 1200:
        tm.c_cflag |= B1200;
        break;
      case 2400:
        tm.c_cflag |= B2400;
        break;
      case 4800:
        tm.c_cflag |= B4800;
        break;
      case 19200:
        tm.c_cflag |= B19200;
        break;
      default:
        tm.c_cflag |= B9600;
      }
    }
    ioctl(s2comid, TCSETA, &tm);
  }

  return s2comid;
}


/*
 * 关闭串行设备
 */
void com_CloseDevice(void)
{
  if (s2comid != -1) {
    ioctl(s2comid, TCSETA, &s2orgtm);
    if (!s2istty)  close(s2comid);
    s2comid = -1;
  }
}


/*
 * 发送一个指定长度的包。timeout=-1永远等待, 0=无超时,否则为超时值(秒)
 * 返回:0-成功,-3-超时
 */
int com_Send(char *buff, int len, int timeout)
{
  fd_set  v_send;
  struct  timeval  t_out;
  int	  rc, tmax, tleft;

#ifdef DEBUG_S
  DebugStr(buff, len, 'w');
#endif

  if (timeout > 0) {
    tmax = time(NULL)+timeout;
    tleft = timeout;
  }

  do {
    FD_ZERO(&v_send);
    FD_SET(s2comid, &v_send);
    if (timeout >= 0) {
      t_out.tv_sec = timeout?tleft:0;
      t_out.tv_usec = 0;
    }

    rc = select(s2comid+1, NULL, &v_send, NULL, timeout==-1? NULL:&t_out);
    if (rc == -1  ||  !FD_ISSET(s2comid, &v_send))  break;

    rc = write(s2comid, buff, len);
    if (rc > 0) {
      buff += rc;
      len -= rc;
      if (len <= 0)  return 0;
    }

    if (timeout == 0)  break;
    tleft = tmax - time(NULL);
  } while (tleft > 0);

  return -3;
}


/*
 * 接收一个不超过指定长度的包。timeout=-1永远等待, 0=无超时,否则为超时值(秒)
 * 返回:>0-成功收到的字节数,-3-超时
 */
int com_Recv(char *buff, int maxlen, int timeout)
{
  fd_set  v_recv;
  struct  timeval  t_out;
  int	  rc;

  FD_ZERO(&v_recv);
  FD_SET(s2comid, &v_recv);
  if (timeout >= 0) {
    t_out.tv_sec = timeout;
    t_out.tv_usec = 0;
  }

  rc = select(s2comid+1, &v_recv, NULL, NULL, timeout==-1? NULL:&t_out);
  if (rc == -1  ||  !FD_ISSET(s2comid, &v_recv))  return -3;

  rc = read(s2comid, buff, maxlen);
#ifdef DEBUG_S
  DebugStr(buff, rc, 'r');
#endif
  if (rc > 0)  return rc;

  return -3;
}


/*
 * 清除收发缓冲: 0=清读,1=清写,2=清读写
 */
void com_Flush(void)
{
  ioctl(s2comid, TCFLSH, 2);
}

main()
{
  com_Flush();
}



⌨️ 快捷键说明

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