一、引例:
在嵌入式系统中,UART时刻用到,在使用时,需要对它进行DIY控制,按需要设置,如:
int com_port(unsigned int com_no)
{
int com_fd;
struct termios com_opt;
char port_path[32];
sprintf(port_path, "/dev/ttySAC%d", com_no);
com_fd = open(port_path, O_RDWR | O_NOCTTY | O_NDELAY); // open serial port
if (com_fd<0){
dbg_print("open %s error!\n",port_path);
break;
}
else {
dbg_print("%s is opened !\n",port_path);
}
tcgetattr(com_fd,&com_opt); /* get serial option */
tcflush(com_fd,TCIFLUSH); /* refresh */
cfsetispeed(&com_opt, UART_SPEED);
cfsetospeed(&com_opt, UART_SPEED);
com_opt.c_cflag |= CS8;
com_opt.c_cflag &= ~PARENB;
com_opt.c_oflag &= ~(OPOST);
com_opt.c_cflag &= ~CSTOPB;
com_opt.c_lflag &= ~(ICANON|ISIG|ECHO|IEXTEN);
com_opt.c_iflag &= ~(INPCK|BRKINT|ICRNL|ISTRIP|IXON);
com_opt.c_cc[VMIN] = 0;
com_opt.c_cc[VTIME] = 0;/* com_opt.c_cc[VTIME] = 5; */
if (tcsetattr(com_fd,TCSANOW,&com_opt) != 0) {
dbg_print("error: SetupSerial !\n");
break;//return -1;
}
return TRUE;
close(com_fd);
return FALSE;
}
这就需要我们对终端的控制及其流程有一定的熟悉。
二、终端特性结构体struct termios:
终端相关的所有特性都在termios结构中,该结构在<termios.h>中定义如下:
struct termios {
/* typedef unsigned int tcflag_t; */
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
};
三、终端操作函数:
终端控制涉及的函数有:
(1)获得和设置终端属性
函数原型:
int tcgetattr(int fds, struct termios *termios_p); /* 获得属性(termios结构) */
int tcsetattr(int fds, int opt, struct termios *termios_p) ; /* 设置属性(termios结构) */
函数参数:
fds——仅代表终端设备的文件符,若 fds 并不引用一个终端设备则出错返回,errno设置为ENOTTY。
termios_p ——返回或设置终端的属性
opt——指定 新设置的属性在什么时候起作用,opt可以使用以下三个常熟中的一个:
—TCSANOW 更改立即发生。
? TCSADRAIN 发送了所有输出后更改才发生。若更改输出参数则应使用此选择项。
? TCSAFLUSH 发送了所有输出后更改才发生。更进一步,在更改发生时未读的所有输入数据都被删除(刷清) 。
(2)波特率函数
speed_t cfgetispeed(const struct termios *termios_p); /* 得到输入速度 */
speed_t cfgetospeed(const struct termios *termios_p); /* 得到输出速度 */
int cfsetispeed(struct termios *,speed_t); /* 设置输入速度 */
int cfsetospeed(struct termios *,speed_t); /* 设置输出速度 */
(3)行控制函数
int tcdrain(int fds); /* 等待所有输出都被输出 */
int tcflow(int fds, int action); /* 挂起输出或接收 */
int tcflush(int fds, int queue); /* 刷清输入/输出 */
int tcsendbreak(int fds, int duration); /* 传送BREAK字符 */
(4)前台进程组ID
pid_t tcgetpgrp(int filedes);
int tcsetpgrp(int filedes, pid_t pgrpid);
(5)终端标识函数
char *ctermid(char *ptr);/* 用来决定控制终端的名字 */
int isatty(int fd); /* 测试一个文件描述符是否终端设备,是的话返回真 */
char *ttyname(int fd); /* 返回文件描述符打开的终端的路径名 */
四、宝贵的废话:
关于终端这部分知识,在《Unix环境高级编程》—【终端I/O】这一章讲的特别详细,值得去读一下。