终端设备
终端设备,又被称作 tty 设备。tty 一词源于 Teletypes,或者 teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘进行阅读和发送信息的媒介,后来被键盘与显示器取代,所以现在叫终端比较合适。终端是一种字符型设备,终端通常用于人机交互,比如我们启动系统后通过串口启动的一个 Shell 界面,就是一个串口终端。
在 SylixOS 中,普通串口终端设备名称为 /dev/ttyS0、/dev/ttyS1 等,而 USB 串口设备名称为 /dev/ttyUSB0、/dev/ttyUSB1 等。通常情况下,/dev/ttyS0 被用于默认的系统 Shell 服务,其他的串口设备可用于一般通信。
下面的程序展示了串口设备的一般使用方法。
#include <SylixOS.h>
#include <fcntl.h>
#include <stdio.h>
#define SERIL_BUF_SIZE 512
#define SERIL_DEV_NAME "/dev/ttyS1"
int main(int argc, char *argv[])
{
int iFd;
char pcBuff[SERIL_BUF_SIZE];
int iRet;
ssize_t sstReadLen;
ssize_t sstWriteLen;
iFd = open(SERIL_DEV_NAME, O_RDWR);
if (iFd < 0) {
fprintf(stderr, "open %s failed.\n", SERIL_DEV_NAME);
return (-1);
}
/*
* 波特率为 : 9600
* 硬件选项为: 8位数据位, 一位停止位,无校验
*/
iRet = ioctl(iFd, SIO_BAUD_SET, 9600);
if (iRet != 0) {
goto __error;
}
iRet = ioctl(iFd, SIO_HW_OPTS_SET, CS8);
if (iRet != 0) {
goto __error;
}
iRet = ioctl(iFd, FIORBUFSET, SERIL_BUF_SIZE);
if (iRet != 0) {
goto __error;
}
while (1) {
sstReadLen = read(iFd, pcBuff, SERIL_BUF_SIZE);
if (sstReadLen < 0) {
fprintf(stderr, "read error.\n");
goto __error;
}
if (sstReadLen == 0) {
continue;
}
sstWriteLen = write(iFd, pcBuff, sstReadLen);
if (sstWriteLen < 0) {
fprintf(stderr, "write error.\n");
goto __error;
}
if (sstWriteLen < sstReadLen) {
printf("write data may be lost.\n");
}
}
close(iFd);
return (0);
__error:
close(iFd);
return (-1);
}
以上为一个简单的串口回显测试程序,由于 /dev/ttyS0 已经被 Shell 使用,因此这里使用 /dev/ttyS1 进行测试。
在读写串口之前,需要设置通信参数,比如波特率、数据位、停止位、是否使能校验等,这些参数必须与通信的另一端完全相同。串口通信参数设置的相关命令位于 <SylixOS/system/util/sioLib.h> 文件。由于串口设备默认的缓冲区大小有限,不一定能满足单次传输的需求,如果发送方发送数据过快,来不及读取的数据将会被覆盖,因此程序中使用 FIORBUFSET(ioctl 命令)命令设置了接收缓冲区大小,这也是使用串口通信必须考虑的一个问题。FIORBUFSET 位于 <SylixOS/system/include/s_option.h> 文件,里面定义了几乎所有的设备控制选项。关于设备缓冲区的操作还有如 FIOWBUFSET、FIORFLUSH、FIOWFLUSH 等,用于设置发送缓冲区大小和清空读写缓冲区等操作。
在 Linux 中,应用程序通常使用 termios 组件操作 tty 设备。SylixOS 兼容 termios 大部分操作,以提高程序兼容性。要使用 termios 操作串口,需要在源文件中包含以下头文件:
#include <termios.h>