简要说明
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
*********************************************************************************************************/