linux下的串口配置

 经过验证是准确无误的,配置以后可以通过以下指令查看

stty -F /dev/ttyUSB0 -a   //查看/dev/ttyUSB0的串口配置

stty -F /dev/ttyUSB0 ispeed 115200 ospeed 115200 cs8 //配置/dev/ttyUSB0的输入输出波特率和数据位


/*******************************************************************
*名称:             UART_Open
*功能:             打开串口并返回串口设备文件描述
*入口参数:         fd      文件描述符
 port    串口号(ttyS0,ttyS1,ttyS2)
*出口参数:正确返回为文件描述符,错误返回为-1
*******************************************************************/
int UART_Open(int fd, const char *port) {
  printf("UART_OPEN start\n");
  int flags = 0;
  fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd < 0) {
    fprintf(stderr, "fd = %d can not open %s\n", fd, port);
    return (FALSE);
  }
  //获取原来的状态
  flags = fcntl(fd, F_GETFL, 0);
  if (flags < 0) {
    perror("fcntl");
    return -1;
  }
  // 设置串口为非阻塞状态   具体情况具体对待
  flags |= O_NONBLOCK;
  if (fcntl(fd, F_SETFL, flags) < 0) {
    fprintf(stderr, "fd = %d fcntl failed \n", fd);
    return (FALSE);
  } else {
    printf("fcntl=%d\n", fcntl(fd, F_SETFL, 0));
  }
  //测试是否为终端设备
  if (0 == isatty(STDIN_FILENO)) { //如果不是终端设备
    // isatty,函数名。主要功能是检查设备类型 , 判断文件描述词是否是为终端机。
    //     用 法: int isatty(int desc);
    // 返回值:如果参数desc所代表的文件描述词为一终端机则返回1,否则返回0。
    printf("standard input is not a terminal device\n");
    return (FALSE);
  }
  printf("UART_OPEN end\n");
  return fd;
}
/*******************************************************************
*名称:             UART_Close
*功能:             关闭串口并返回串口设备文件描述
*入口参数:         fd          文件描述符
                    port        串口号(ttyS0,ttyS1,ttyS2,ttyUSB0等)
*出口参数:void
*******************************************************************/

void UART_Close(int fd) { close(fd); }

/*******************************************************************
 * 名称:            UART_Recv
 * 功能:            接收串口数据
 * 入口参数:        fd         文件描述符
 *                   rcv_buf    接收串口中数据存入rcv_buf缓冲区中
 *                   data_len   一帧数据的长度
 * 出口参数:        正确返回为1,错误返回为0
 *******************************************************************/
int UART_Recv(int fd, char *rcv_buf, int data_len) {
  return read(
      fd, rcv_buf,
      data_len); //底层只负责读操作,结果返回给上层,以便上层根据需求来操作
  
}
/********************************************************************
 * 名称:            UART_Send
 * 功能:            发送数据
 * 入口参数:        fd           文件描述符
 *                   send_buf     存放串口发送数据
 *                   data_len     一帧数据的个数
 * 出口参数:        正确返回为发送的长度,错误返回为0
 *******************************************************************/
int UART_Send(int fd, char *send_buf, int data_len) {
  printf("fd = %d  UART_Send_DATA : %s\n", fd, send_buf);
  return write(
      fd, send_buf,
      data_len); //底层只负责写,写的结果返回给上层,以便上层根据具体情况具体解决
}
/*******************************************************************
 *名称:             set_opt
 *功能:             设置串口数据位,停止位和效验位
 *入口参数:         fd          串口文件描述符
 *                   baudrate       串口速度
 *                   flow_ctrl   数据流控制
 *                   databits    数据位   取值为 7 或者8
 *                   stopbits    停止位   取值为 1 或者2
 *                   parity      效验类型 取值为N,E,O,,S
 *出口参数:正确返回为0,错误返回为-1
 *******************************************************************/
static int set_opt(int fd, int baudrate, int flow_ctrl, int databits,
                   int stopbits, int parity) {
  struct termios new_uart_options;
  struct termios old_uart_options;
  //                      termios
  //                      函数族提供了一个常规的终端接口,用于控制非同步通信端口。
  //                      这个结构包含了至少下列成员:
  // tcflag_t c_iflag;      /* 输入模式 */
  // tcflag_t c_oflag;      /* 输出模式 */
  // tcflag_t c_cflag;      /* 控制模式 */
  // tcflag_t c_lflag;      /* 本地模式 */
  // cc_t c_cc[NCCS];       /* 控制字符 */
  // struct termios
  // {unsigned short c_iflag; /* 输入模式标志*/
  // unsigned short c_oflag; /* 输出模式标志*/
  // unsigned short c_cflag; /* 控制模式标志*/
  // unsigned short c_lflag; /*区域模式标志或本地模式标志或局部模式*/
  // unsigned char c_line; /*行控制line discipline */
  // unsigned char c_cc[NCC]; /* 控制字符特性*/
  if (tcgetattr(fd, &old_uart_options) !=
      0) { /*  tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将它们保存于options,该函数还可以测试配置是否正确,
该串口是否可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1. */
    fprintf(stderr, "fd = %d SetupSerial err:%s\n", fd, strerror(errno));
    return FALSE;
  }
  bzero(&new_uart_options, sizeof(new_uart_options)); //清零new_uart_options
  new_uart_options.c_cflag |= CLOCAL; //修改控制模式,保证程序不会占用串口
  new_uart_options.c_cflag |=
      CREAD; //修改控制模式,使得能够从串口中读取输入数据
  new_uart_options.c_cflag &= ~CSIZE; //设置数据位字节
  //设置数据位
  switch (databits) { //默认8位数据位
  case 7:
    new_uart_options.c_cflag |= CS7;
    break;
  case 8:
    new_uart_options.c_cflag |= CS8;
    break;
  default:
    fprintf(stderr, "fd = %d unsupported databits\n", fd);
    return FALSE;
    break;
  }
  //设置波特率
  switch (baudrate) {
  case 9600:
    cfsetispeed(&new_uart_options, B9600);
    cfsetospeed(&new_uart_options, B9600);
    break;
  case 19200:
    cfsetispeed(&new_uart_options, B19200);
    cfsetospeed(&new_uart_options, B19200);
    break;
  case 38400:
    cfsetispeed(&new_uart_options, B38400);
    cfsetospeed(&new_uart_options, B38400);
    break;
  case 57600:
    cfsetispeed(&new_uart_options, B57600);
    cfsetospeed(&new_uart_options, B57600);
    break;
  case 115200:
    cfsetispeed(&new_uart_options, B115200);
    cfsetospeed(&new_uart_options, B115200);
    break;
  default:
    fprintf(stderr, "fd = %d unsupported baudrate\n", fd);
    return FALSE;
    break;
  }
  switch (flow_ctrl) { //默认无流控
  case 0:              //不使用流控
    new_uart_options.c_cflag &= ~CRTSCTS;
    break;
  case 1: //使用硬件流控
    new_uart_options.c_cflag |= CRTSCTS;
    break;
  case 2: //使用软件流控
    new_uart_options.c_cflag |= IXON | IXOFF | IXANY;
    break;
  default:
    fprintf(stderr, "fd = %d unsupported flow_ctrl\n", fd);
    return FALSE;
    break;
  }

  //设置校验位
  switch (parity) {
  case 'N': //无奇偶校验
    new_uart_options.c_cflag &= ~PARENB;
    // new_uart_options.c_cflag &= ~INPCK;
    break;
  case 'O': //设置为奇校验
    new_uart_options.c_cflag |= PARENB;
    new_uart_options.c_cflag |= PARODD;
    new_uart_options.c_cflag |= (INPCK | ISTRIP);
    break;
  case 'E': //设置为偶校验
    new_uart_options.c_cflag |= (INPCK | ISTRIP);
    new_uart_options.c_cflag |= PARENB;
    new_uart_options.c_cflag &= ~PARODD;
    break;
  default:
    fprintf(stderr, "fd = %d unsupported parity\n", fd);
    return FALSE;
    break;
  }

  // 设置停止位
  switch (stopbits) {
  case 1:
    new_uart_options.c_cflag &= ~CSTOPB;
    break;
  case 2:
    new_uart_options.c_cflag |= CSTOPB;
    break;
  default:
    fprintf(stderr, "fd = %d unsupported stopbits\n", fd);
    return FALSE;
    break;
  }

  // //修改输出模式,原始数据输出
  new_uart_options.c_oflag &= ~OPOST;

  new_uart_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  // new_uart_options.c_lflag &= ~(ISIG | ICANON);

  //设置等待时间和最小接收字符
  new_uart_options.c_cc[VTIME] = 0; /* 读取一个字符等待1*(1/10)s */
  new_uart_options.c_cc[VMIN] = 0;  /* 读取字符的最少个数为1 */

  //如果发生数据溢出,接收数据,但是不再读取 刷新收到的数据但是不读
  tcflush(fd, TCIFLUSH);
  // int tcflush(int fd, int queue_selector);
  //
  // fd                // 终端I/O打开的句柄
  //
  // queue_selector    // 控制tcflush的操作,取值为下面三个常数中的一个:
  //
  //   TCIFLUSH  // 清除正收到的数据,且不会读取出来。
  //
  //   TCOFLUSH  // 清除正写入的数据,且不会发送至终端。
  //
  //   TCIOFLUSH // 清除所有正在发生的I/O数据。
  // 返回值说明:
  //
  // 0     // 成功
  //
  // -1    // 失败,并且为 errno 置值来指示错误

  //激活配置 (将修改后的termios数据设置到串口中)
  if (tcsetattr(fd, TCSANOW, &new_uart_options) !=
      0) { // tcsetattr函数用于设置终端参数。函数在成功的时候返回0,失败的时候返回-1,并设置errno的值。
    // perror("com set error!\n");
    fprintf(stderr, "fd = %d com set err! errstring = %s\n", fd,
            strerror(errno));
    return FALSE;
  }
  return TRUE;
}
/*******************************************************************
 *名称:                UART_Init()
 *功能:                串口初始化
 *入口参数:             fd         文件描述符
 *                      baudrate      串口速度
 *                      flow_ctrl  数据流控制
 *                      databits   数据位   取值为 7 或者8
 *                      stopbits   停止位   取值为 1 或者2
 *                      parity     效验类型 取值为N,E,O,,S
 *
 *出口参数:正确返回为1,错误返回为0
 *******************************************************************/
int UART_Init(int fd, int baudrate, int flow_ctrl, int databits, int stopbits,
              int parity) {
  printf("UART_Init\n");
  return set_opt(fd, baudrate, flow_ctrl, databits, stopbits, parity);
}

 

你可能感兴趣的:(Linux)