符合POSIX标准的UART应用例程

简要说明

POSIX(Portable Operating System Interface,可移植操作系统接口,X表明其对Unix API的传承)是IEEE为要在各种类UNIX操作系统上运行软件,而定义API的一系列互相关联的标准的总称,其正式称呼为IEEE Std 1003。POSIX标准意在期望获得源代码级别的软件可移植性。换句话说,为一个POSIX兼容的操作系统编写的程序,应该可以在任何其它的POSIX操作系统上编译执行。

上一篇《应用层使用uart设备》中列举了sylixos应用层简单调用uart设备的例子,值得注意的是这个例子中包含了SylixOS.h这个头文件,同时还用到了SIO_BAUD_SET,SIO_HW_OPTS_SET,SIO_BAUD_115200等宏定义,这些都是sylixos特有的,移植到其他系统是会报错的。

sylixos也是一个类Unix操作系统,为了提高应用程序的可移植性丰富应用生态,设计了一个POSIX兼容层,能提供绝大部分的POSIX接口支持。对于串口的操作,POSIX标准主要是通过termios模块来实现的,sylixos中也提供来该模块,故而符合POSIX标准的串口操作应用程序可以直接在sylixos下编译通过。

termios 结构是在POSIX规范中定义的标准接口,它类似于系统V中的termio接口,通过设置termios类型的数据结构中的值和使用一小组函数调用,你就可以对终端接口进行控制。termios 函数族提供了一个常规的终端接口,用于控制非同步通信端口。下面是一些termios介绍和说明的资料:

  • linux下termios说明: http://man7.org/linux/man-pages/man3/termios.3.html
  • freebsd下termios说明: https://www.freebsd.org/cgi/man.cgi?query=termios&sektion=4
  • termios 详解:https://blog.csdn.net/lizuobin2/article/details/51775277
  • linux tty之termios 详解: https://blog.csdn.net/u010444107/article/details/79234471

程序源码

注意:下面的示例程序在sylixos和Linux下都是可以编译通过的。

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                       SylixOS(TM)
**
**                               Copyright  All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: uartExample.c
**
** 创   建   人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2018 年 01 月 11 日
**
** 描        述: 串口测试程序,收到一组数据后将此组数据通过串口返回
*********************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
/*********************************************************************************************************
** 函数名称: set_speed
** 功能描述: 设置串口波特率
** 输    入: fd    串口操作句柄
**         : speed 串口设置的波特率
** 输    出: NONE
*********************************************************************************************************/
static  int  set_speed (int  fd, int  speed)
{
    int             ret;
    struct termios  opt;

    ret = tcgetattr(fd, &opt);                                          /*  获取串口的 termios 信息     */
    if (ret !=  0) {
        printf("Get Serial speed failed");
        return  (1);
    }
    tcflush(fd, TCIOFLUSH);                                             /*  刷新输入输出数据            */

    cfsetispeed(&opt, speed);                                           /*  设置输入波特率              */
    cfsetospeed(&opt, speed);                                           /*  设置输出波特率              */
    /*
     * 用于设置终端的相关参数, TCSANOW 不等数据传输完毕就立即改变属性
     */
    ret = tcsetattr(fd, TCSANOW, &opt);                                 /*  设置串口属性                */
    if (ret != 0) {
        printf("Setup Serial speed failed");
        return  (2);
    }
    return  (0);
}
/*********************************************************************************************************
** 函数名称: set_parity
** 功能描述: 设置串口的通信参数
** 输    入: fd        串口操作句柄
**         : databits  数据位
**         : stopbits  停止位
**         : parity    校验位
** 输    出: 0 设置成功,-1 设置失败
*********************************************************************************************************/
static  int  set_parity (int  fd, int  databits, int  stopbits, int  parity)
{
    int             ret;
    struct termios  options;

    ret = tcgetattr(fd, &options);
    if (ret !=  0) {
        printf("Setup Serial failed");
        return  (1);
    }

    options.c_cflag &= ~CSIZE;
    switch (databits) {                                                 /*  设置数据位数                */

    case 5:
        options.c_cflag |= CS5;
        break;

    case 6:
        options.c_cflag |= CS6;
        break;

    case 7:
        options.c_cflag |= CS7;
        break;

    case 8:
        options.c_cflag |= CS8;
        break;

    default:
        printf("Unsupported data size\n");
        return  (2);
    }

    switch (parity) {                                                   /*  设置校验方式                */

    case 'n':
    case 'N':
        options.c_cflag &= ~PARENB;
        options.c_iflag &= ~INPCK;
        break;

    case 'o':
    case 'O':
        options.c_cflag |= (PARODD | PARENB);
        options.c_iflag |= INPCK;
        break;

    case 'e':
    case 'E':
        options.c_cflag |= PARENB;
        options.c_cflag &= ~PARODD;
        options.c_iflag |= INPCK;
        break;

    default:
        printf("Unsupported parity\n");
        return  (3);
    }

    switch (stopbits) {                                                 /* 设置停止位                   */

    case 1:
        options.c_cflag &= ~CSTOPB;
        break;

    case 2:
        options.c_cflag |= CSTOPB;
        break;

    default:
        printf("Unsupported stop bits\n");
        return  (4);
    }

    tcflush(fd, TCIOFLUSH);                                             /* 清楚串口收发缓冲去           */
    /*
     * 用于设置终端的相关参数, TCSANOW 不等数据传输完毕就立即改变属性
     */
    ret = tcsetattr(fd, TCSANOW, &options);                             /*  设置串口属性                */
    if (ret != 0) {
        printf("Setup Serial failed");
        return  (5);
    }
    return  (0);
}
/*********************************************************************************************************
** 函数名称: mainExampleStart
** 功能描述: uart 测试启动函数
** 输    入: 设备号,使用方式 ./uart_test /dev/ttyS1
** 输    出: 无
*********************************************************************************************************/
int  main (int  argc, char  *argv[])
{
    int       ret;
    int       nread;
    int       fd_tty;
    char      buff[64];

    /*
     * 参数个数小于2则返回
     */
    if (argc < 2) {
        printf("useage: %s dev\n", argv[0]);
        return  (-1);
    }

    fd_tty = open(argv[1], O_RDWR);                                     /*  打开串口                    */
    if (fd_tty < 0) {
        printf("open device %s faild\n", argv[1]);
        return  (-1);
    }

    ret = set_speed(fd_tty, B115200);                                   /*  设置串口波特率              */
    if (ret != 0) {
        close(fd_tty);
        return  (-1);
    }

    ret = set_parity(fd_tty, 8, 1, 'n');                                /*  数据位 8,停止位 1,无校验  */
    if (ret != 0) {
        close(fd_tty);
        return  (-1);
    }

    /*
     * 在 while 循环中,不断的检查数据,若收到数据,将数据通过此串口发送回主机
     */
    while(1) {
        nread = read(fd_tty, buff, sizeof(buff));
        if (nread > 0) {                                                /*  接收数据                    */
            write(fd_tty, buff, nread);                                 /*  将接收的数据通过原串口输出  */
        }
    }

    close(fd_tty);

    return  (0);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/


发布了39 篇原创文章 · 获赞 6 · 访问量 5063

猜你喜欢

转载自blog.csdn.net/ScilogyHunter/article/details/104287964
今日推荐