嵌入式linux的uart驱动

转载来源:吴家伟的博客

原文

一、数据成员
               
                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;
                unsigned char c_cc[NCC];
                };
                二、作用
                这个变量被用来提供一个健全的线路设置集 合, 如果这个端口在被用户初始化前
                使用. 驱动初始化这个变量使用一个标准的数值集, 它拷贝自 tty_std_termios
                变量. tty_std_termos 在 tty 核心被定义为:
               
                struct termios tty_std_termios = {
                 .c_iflag = ICRNL | IXON,
                 .c_oflag = OPOST | ONLCR,
                 .c_cflag = B38400 | CS8 | CREAD | HUPCL,
                 .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
                 ECHOCTL | ECHOKE | IEXTEN,
                 .c_cc = INIT_C_CC
                };
                这个 struct termios 结构用来持有所有的当前线路设置, 给这个 tty 设备的一个特定端口. 这些线路设置控制当前波特率, 数据大小, 数据流控设置, 以及许多其他值.

各个字段的选项如下(不是所有UNIX系统都支持):

c_iflag:
  • BRKINT:接到BREAK时产生SIGINT;
  • ICRNL:将输入的CR转换为NL;
  • IGNBRK:忽略BREAK条件;
  • IGNCR:忽略CR;
  • IGNPAR:忽略奇偶错字符;
  • IMAXBEL:在输入队列空时振铃;
  • INLCR:将输入的NL转换为CR;
  • INPCK:打开输入奇偶校验;
  • ISTRIP:剥除输入字符的第8位;
  • IUCLC:将输入的大写字符转换成小写字符(仅SVR4);
  • IXANY:使任一字符都重新起动输出;
  • IXOFF:使起动/停止输入控制流起作用;
  • IXON:使起动/停止输出控制流起作用;
  • PARMRK:标记奇偶错;
c_oflag:
  • BSDLY:退格延迟屏蔽(仅SVR4);
  • CRDLY:CR延迟屏蔽(仅SVR4);
  • FFDLY:换页延迟屏蔽(仅SVR4);
  • NLDLY:NL延迟屏蔽(仅SVR4);
  • OCRNL:将输出的CR转换为NL(仅SVR4);
  • OFDEL:填充符为DEL,否则为NUL(仅SVR4);
  • OFILL:对于延迟使用填充符(仅SVR4);
  • OLCUC:将输出的小写字符转换为大写字符(仅SVR4);
  • ONLCR:将NL转换为CR-NL;
  • ONLRET:NL执行CR功能(仅SVR4);
  • ONOCR:在0列不输出CR(仅SVR4);
  • ONOEOT:在输出中删除EOT字符(仅4.3+BSD);
  • OPOST:执行输出处理;
  • OXTABS:将制表符扩充为空格(仅4.3+BSD);
  • TABDLY:水平制表符延迟屏蔽(仅SVR4);
  • VTDLY:垂直制表符延迟屏蔽(仅SVR4);
c_cflag:
  • CCTS_OFLOW:输出的CTS流控制(仅4.3+BSD);
  • CIGNORE:忽略控制标志(仅4.3+BSD);
  • CLOCAL:忽略解制解调器状态行;
  • CREAD:启用接收装置;
  • CRTS_IFLOW:输入的RTS流控制(仅4.3+BSD);
  • CSIZE:字符大小屏蔽;
  • CSTOPB:送两个停止位,否则为1位;
  • HUPCL:最后关闭时断开;
  • MDMBUF:经载波的流控输出(仅4.3+BSD);
  • PARENB:进行奇偶校;
  • PARODD:奇校,否则为偶校;
c_lflag:
  • ALTWERASE:使用替换WERASE算法(仅4.3+BSD);
  • ECHO:进行回送;
  • ECHOCTL:回送控制字符为^(char);
  • ECHOE:可见擦除符;
  • ECHOK:回送kill符;
  • ECHOKE:kill的可见擦除;
  • ECHONL:回送NL;
  • ECHOPRT:硬拷贝的可见擦除方式;
  • FLUSHO:刷清输出;
  • ICANON:规范输入;
  • IEXTEN:使扩充的输入字符处理起作用;
  • ISIG:使终端产生的信号起作用;
  • NOFLSH:在中断或退出键后不刷清;
  • NOKERNINFO:STATUS不使内核输出(仅4.3+BSD);
  • PENDIN:重新打印;
  • TOSTOP:对于后台输出发送SIGTTOU;
  • XCASE:规范大/小写表示(仅SVR4);
字符 说明 c_cc下标 起作用,由: 典型值 POSIX.1SVR44.3+BSD
字段标志 扩充
CR 回车 不能更改 c_lflag ICANON /r YES    
DISCARD 擦除输出 VDISCARD c_lflag IEXTEN ^O   YES YES
DSUSP 延迟挂起(SIGTSTP) VDUSP c_lflag ISIG ^Y   YES YES
EOF 文件结束 VEOF c_lflag ICANON ^D YES    
EOL 行结束 VEOL c_lflag ICANON   YES    
EOL2 替换的行结束 VEOL2 c_lflag ICANON     YES YES
ERASE 擦除字符 VERASE c_lflag ICANON ^H YES    
INTR 中断信号(SIGINT) VINTR c_lflag ISIG ^?, ^C YES    
KILL 擦行 VKILL c_lflag ICANON ^U YES    
LNEXT 下一个字列字符 VLNEXT c_lflag IEXTEN ^V   YES YES
NL 新行 不能更改 c_lflag ICANON /n YES    
QUIT 退出信号(SIGQUIT) VQUIT c_lflag ISIG ^/ YES    
REPRINT 再打印全部输入 VREPRINT c_lflag ICANON ^R   YES YES
START 恢复输出 VSTART c_lflag IXON/IXOFF ^Q YES    
STATUS 状态要求 VSTATUS c_lflag ICANON ^T     YES
STOP 停止输出 VSTOP c_lflag IXON/IXOFF ^S YES    
SUSP 挂起信号(SIGTSTP) VSUSP c_lflag ISIG ^Z YES    
WERASE 擦除字 VWERASE c_lflag ICANON ^W   YES YES

4.POSIX终端I/O函数

tcgetattr 取属性(termios结构);
tcsetattr 设置属性(termios结构);
cfgetispeed     得到输入速度;
cfgetospeed 得到输出速度;
cfsetispeed 设置输入速度;
cfsetospeed 设置输出速度;
tcdrain 等待所有输出都被传输;
tcflow 挂起传输或接收;
tcflush 刷清未决输入和/或输出;
tcsendbreak 送BREAK字符;
tcgetpgrp 得到前台进程组ID;
tcsetpgrp 设置前台进程组ID

5.tcgetattr和tcsetattr

#include <termios.h> int tcgetattr(int filedes, struct termios *termptr); int tcsetattr(int filedes, int opt, const struct termios *termptr); 两个函数返回:若成功则为0,若出错则为-1

这两个函数都有一个指向termios结构的指针作为其参数,它们返回当前终端的属性,或者设置该终端的属性。因为这两个函数只对终端设备进行操作,所以若filedes并不引用一个终端设备则出错返回,errno设置为ENOTTY。

tcsetattr的参数opt使我们可以指定在什么时候新的终端属性才起作用。opt可以指定为下列常数中的一个:

  • TCSANOW:更改立即发生;
  • TCSADRAIN:发送了所有输出后更改才发生。若更改输出参数则应使用此选择项。
  • TCSAFLUSH:发送了所有输出后更改才发生。更进一步,在更改发生时未读的所有输入数据都被删除(刷清)。

tcsetattr函数的返回值易于产生混淆。如果它执行了任意一种所要求的动作,即使未能执行所有要求的动作,它也返回0(表示成功)。如果该函数返回0,则我们有责任检查该函数是否执行了所有要求的动作。这就意味着,在调用tcsetattr设置所希望的属性后,需调用tcgetattr,然后将实际终端属性与所希望的属性相比较,以检测两者是否有区别。

6.波特率函数

波特率(baud rate)是一个历史沿用的术语,现在它指的是“位/每秒”。虽然大多数终端设备对输入和输出使用同一波特率,但是只要硬件许可,可以将它们设置为两个不同值。

#include <termios.h> speed_t cfgetispeed(const struct termios *termptr); speed_t cfgetospeed(const struct termios *termptr); 两个函数返回:波特率值 int cfsetispeed(struct termios *termptr, speed_t speed); int cfsetospeed(struct termios *termptr, speed_t speed); 两个函数返回:若成功为0,出错为-1

两个cfget函数的返回值,以及两个cfset函数的speed参数都是下列常数之一:B50、B75、B110、B134、B150、B200、B300、B600、B1200、B1800、B2400、B4800、B9600、B19200或B38400。常数B0表示“挂断”。在调用tcsetattr时将输出波特率指定为B0,则调制解调器的控制线就不再起作用。

使用这些函数时,应当理解输入、输出波特率是存放在termios结构中的。在调用任一cfget函数之前,先要用tcgetattr获得设备的termios结构。与此类似,在调用任一cfset函数后,应将波特率设置到termios结构中。为使这种更改影响到设备,应当调用tcsetattr函数。如果所设置的波特率有错,则在调用tcsetattr之前,不会发现这种错误。

7.行控制函数

#include <termios.h> int tcdrain(int filedes); int tcflow(int filedes, int action); int tcflush(int filedes, int queue); int tcsendbreak(int filedes, int duration); 四个函数返回:若成功则为0,若出错则为-1

其中,参数filedes引用一个终端设备,否则出错返回,errno设置为ENOTTY。

tcdrain函数等待所有输出都被发送。

tcflow用于对输入和输出流控制进行控制。action参数应当是下列四个值之一:

  • TCOOFF:输出被挂起;
  • TCOON:以前被挂起的输出被重新起动;
  • TCIOFF:系统发送一个STOP字符。这将使终端设备暂停发送数据;
  • TCION:系统发送一个START字符。这将使终端恢复发送数据。

tcflush函数刷清(抛弃)输入缓存(终端驱动程序已接收到,但用户程序尚未读)或输出缓存(用户程序已经写,但尚未发送)。queue参数应当是下列三个常数之一:

  • TCIFLUSH:刷清输入队列;
  • TCOFLUSH:刷清输出队列;
  • TCIOFLUSH:刷清输入、输出队列;

tcsendbreak函数在一个指定的时间区间内发送连续的0位流。若duration参数为0,则此种发送延续0.25~ 0.5秒之间。POSIX.1说明若duration非0,则发送时间依赖于实现。

 

8.终端标识函数

POSIX.1提供了一个运行时函数,可被调用来决定控制终端的名字:

#include <stdio.h> char * ctermid(char *ptr);

如果ptr是非空,则它被认为是一个指针,指向长度至少为L_ctermid字节的数组,进程的控制终端名存放在该数组中。常数L_ctermid定义在<stdio.h>中。若ptr是一个空指针,则该函数为数组(通常作为静态变量)分配空间。同样,进程的控制终端名存放在该数组中。

在这两种情况中,该数组的起始地址被作为函数值返回。因为大多数UNIX系统都使用/dev/tty作为控制终端名,所以此函数的主要作用是帮助提高向其他操作系统的可移植性。

其他终端标识函数还有:

#include <unistd.h> int isatty(int filedes); 返回:若为终端设备则为1(真),否则为0(假) char *ttyname(int filedes); 返回:指向终端路径名的指针,若出错则为NULL

如果文件描述符引用一个终端设备,则isatty返回真,而ttyname则返回在该文件描述符上打开的终端设备的路径名。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值