POSIX操作系统的串口编程指南(2)

本文详细介绍如何使用C语言及POSIX终端接口配置串口,包括设置波特率、字符大小、奇偶校验、硬件流控制等内容,并提供具体示例代码。

第二章:配置串口

这一章介绍怎样使用C语言的POSIX终端接口配置串口。

POSIX终端接口

多数系统支持使用POSIX终端接口改变波特率、字符数等参数。首先要包含头文件<termios.h>;这样就定义了终端控制结构和POSIX控制函数。

两个最重要的POSIX函数是tcgetattr(3)tcsetattr(3),用了获取和设置终端属性。你可以设置一个指向termios结构的指针,这个结构包含了所有可用的串口选项:

Table3-TermiosStructureMembers

Member

Description

c_cflag

Controloptions

c_lflag

Lineoptions

c_iflag

Inputoptions

c_oflag

Outputoptions

c_cc

Controlcharacters

c_ispeed

Inputbaud(newinterface)

c_ospeed

Outputbaud(newinterface)

控制选项

c_cflag用来控制波特率、数据位、奇偶位、停止位和硬件流控制。下面是所有支持的配置的常量:

Table4-Constantsforthec_cflagMember

Constant

Description

CBAUD

Bitmaskforbaudrate

B0

0baud(dropDTR)

B50

50baud

B75

75baud

B110

110baud

B134

134.5baud

B150

150baud

B200

200baud

B300

300baud

B600

600baud

B1200

1200baud

B1800

1800baud

B2400

2400baud

B4800

4800baud

B9600

9600baud

B19200

19200baud

B38400

38400baud

B57600

57,600baud

B76800

76,800baud

B115200

115,200baud

EXTA

Externalrateclock

EXTB

Externalrateclock

CSIZE

Bitmaskfordatabits

CS5

5databits

CS6

6databits

CS7

7databits

CS8

8databits

CSTOPB

2stopbits(1otherwise)

CREAD

Enablereceiver

PARENB

Enableparitybit

PARODD

Useoddparityinsteadofeven

HUPCL

Hangup(dropDTR)onlastclose

CLOCAL

Localline-donotchange"owner"ofport

LOBLK

Blockjobcontroloutput

CNEW_RTSCTS

CRTSCTS

Enablehardwareflowcontrol(notsupportedonallplatforms)

c_cflag有两个选项需要一直使能,CLOCAL:忽略所有调制解调器的状态信号;CREAD:启用字符接收器。

波特率常数(CBAUDB9600,etc.)用于缺少c_ispeedc_ospeed成员的旧接口。下一节介绍用于设置波特率的POSIX函数。

注:决不能直接初始化c_cflag(或其他flag)。应该使用ANDORNOT等位操作符来置1或清0成员中的位。不同的操作系统版本的位操作可能不同,使用位操作符可以避免错误操作一个新串行设备所需要的标志位。

1)设置波特率

不同的操作系统中,波特率储存的位置也不同。旧的接口将波特率按照Table4中的常量保存c_cflag中。新的实现方法提供了c_ispeedc_ospeed来保存实际的波特率值。

cfsetospeed(3)cfsetispeed(3)函数用来设置termios结构中的波特率,从而屏蔽了底层的操作系统。你可以使用下面的代码设置波特率:

Listing2-Settingthebaudrate.

structtermiosoptions;

/*

*Getthecurrentoptionsfortheport...

*/

tcgetattr(fd,&options);

/*

*Setthebaudratesto19200...

*/

cfsetispeed(&options,B19200);

cfsetospeed(&options,B19200);

/*

*Enablethereceiverandsetlocalmode...

*/

options.c_cflag|=(CLOCAL|CREAD);

/*

*Setthenewoptionsfortheport...

*/

tcsetattr(fd,TCSANOW,&options);

tcgetattr(3)函数使用你提供的串口配置参数填充termios结构。设置了波特率、使能本地模式和串行数据接收后,使用tcsetattr3)使新的配置生效。常量TCSANOW指定了新的设置立即生效,不需要等待数据接收或发生结束。还有其他常量,可以等待输入或输出数据结束,或清空缓冲区。

多数操作系统不支持不同的输入和输出速率,为了最好的可移植性,请确保相同的输入和输出速率。

Table5-Constantsfortcsetattr

Constant

Description

TCSANOW

Makechangesnowwithoutwaitingfordatatocomplete

TCSADRAIN

Waituntileverythinghasbeentransmitted

TCSAFLUSH

Flushinputandoutputbuffersandmakethechange

2)设置字符大小

与波特率设置不同,没有方便的函数用来设置字符大小,所有必须用位掩码。字符大小用位数指定。

options.c_cflag&=~CSIZE;/*Maskthecharactersizebits*/

options.c_cflag|=CS8;/*Select8databits*/

3)设置奇偶校验

类似设置字符大小,你必须手动设置使能奇偶校验和奇偶校验位数。UNIX的串口设备支持奇、偶和无校验。

Noparity(8N1):

options.c_cflag&=~PARENB

options.c_cflag&=~CSTOPB

options.c_cflag&=~CSIZE;

options.c_cflag|=CS8;

Evenparity(7E1):

options.c_cflag|=PARENB

options.c_cflag&=~PARODD

options.c_cflag&=~CSTOPB

options.c_cflag&=~CSIZE;

options.c_cflag|=CS7;

Oddparity(7O1):

options.c_cflag|=PARENB

options.c_cflag|=PARODD

options.c_cflag&=~CSTOPB

options.c_cflag&=~CSIZE;

options.c_cflag|=CS7;

Spaceparityissetupthesameasnoparity(7S1):

options.c_cflag&=~PARENB

options.c_cflag&=~CSTOPB

options.c_cflag&=~CSIZE;

options.c_cflag|=CS8;

4)硬件流控制

有些UNIX版本支持使用CTS(ClearToSend)RTS(RequestToSend)信号来控制硬件流。如果你的系统定义了CNEW_RTSCTSCRTSCTS常量,那就很可能支持硬件流控制。使用下面的代码可以使能硬件流控制:

options.c_cflag|=CNEW_RTSCTS;/*AlsocalledCRTSCTS*/

关闭硬件流控制:

options.c_cflag&=~CNEW_RTSCTS;

本地选项

本地模式成员c_lflag用于控制串行设备如何管理输入字符。通常可以将c_lflag配置为canonicalraw

Table6-Constantsforthec_lflagMember

ISIG

EnableSIGINTR,SIGSUSP,SIGDSUSP,andSIGQUITsignals

ICANON

Enablecanonicalinput(elseraw)

XCASE

Mapuppercase/lowercase(obsolete)

ECHO

Enableechoingofinputcharacters

ECHOE

EchoerasecharacterasBS-SP-BS

ECHOK

EchoNLafterkillcharacter

ECHONL

EchoNL

NOFLSH

Disableflushingofinputbuffersafterinterruptorquitcharacters

IEXTEN

Enableextendedfunctions

ECHOCTL

Echocontrolcharactersas^charanddeleteas~?

ECHOPRT

Echoerasedcharacterascharactererased

ECHOKE

BS-SP-BSentirelineonlinekill

FLUSHO

Outputbeingflushed

PENDIN

Retypependinginputatnextreadorinputchar

TOSTOP

SendSIGTTOUforbackgroundoutput

选择CanonicalInput

CanonicalInput是以行进行操作的。输入的字符被放在一个可以由用户进行交互编辑的缓冲区,知道收到回车(CR)或换行(LF)字符。选择这个模式的话,你需要选择ICANONECHOECHOE选项:

options.c_lflag|=(ICANON|ECHO|ECHOE);

选择RawInput

Rawinput是不做任何处理的。输入字符被收到后就直接传送。你需要取消ICANONECHOECHOEISIG选项来选择RawInput模式:

options.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);

关于输入回显的说明

决不能在发生命令给一个MODOM或电脑时使能输入回显,那样的话会在两个串口之间形成一个回环。

输入选项

输入模式成员变量c_iflag用于控制串口接收端的字符的处理过程。与c_cflag一样,c_iflag的值也是将需要的选项通过OR运算得到的。

Table7-Constantsforthec_iflagMember

Constant

Description

INPCK

Enableparitycheck

IGNPAR

Ignoreparityerrors

PARMRK

Markparityerrors

ISTRIP

Stripparitybits

IXON

Enablesoftwareflowcontrol(outgoing)

IXOFF

Enablesoftwareflowcontrol(incoming)

IXANY

Allowanycharactertostartflowagain

IGNBRK

Ignorebreakcondition

BRKINT

SendaSIGINTwhenabreakconditionisdetected

INLCR

MapNLtoCR

IGNCR

IgnoreCR

ICRNL

MapCRtoNL

IUCLC

Mapuppercasetolowercase

IMAXBEL

EchoBELoninputlinetoolong

设置输入奇偶校验选项

如果已经在c_cflag中使能了奇偶校验,那你可以使能输入奇偶校验。与输入奇偶校验相关的常量是INPCK,IGNPAR,PARMRKISTRIP。通常你需要选择INPCK和ISTRIP来使能输入奇偶校验并去掉数据中的校验位:

options.c_iflag|=(INPCK|ISTRIP);

IGNPAR是一个危险的选项,它告诉串口忽略校验错误并让数据通过,就想没用发生错误一样。这在测试通信连接的质量时有用,通常没有实用价值。

PARMRK会使校验错误被标记为“marked",并使用特殊的字符放入输入流中。如果使能IGNPAR,一个空字符(000octal)会被加入到校验错误的前面。否则,DEL177octal)和NUL字符会和错误字符一起发生。

设置软件流控制

使用IXONIXOFfIXANY常量来使能软件流控制:

options.c_iflag|=(IXON|IXOFF|IXANY);

取消软件流控制只需掩掉这些位:

options.c_iflag&=(IXON|IXOFF|IXANY);

XON(开始数据)和XOFF(停止数据)字符定义在下面描述的c_cc数组中。

输出选项

C_oflag成员包含了输出过滤选项。像输入模式一样,你可以选择processedraw数据输出。

Table8-Constantsforthec_oflagMember

Constant

Description

OPOST

Postprocessoutput(notset=rawoutput)

OLCUC

Maplowercasetouppercase

ONLCR

MapNLtoCR-NL

OCRNL

MapCRtoNL

NOCR

NoCRoutputatcolumn0

ONLRET

NLperformsCRfunction

OFILL

Usefillcharactersfordelay

OFDEL

FillcharacterisDEL

NLDLY

Maskfordelaytimeneededbetweenlines

NL0

NodelayforNLs

NL1

Delayfurtheroutputafternewlinefor100milliseconds

CRDLY

Maskfordelaytimeneededtoreturncarriagetoleftcolumn

CR0

NodelayforCRs

CR1

DelayafterCRsdependingoncurrentcolumnposition

CR2

Delay100millisecondsaftersendingCRs

CR3

Delay150millisecondsaftersendingCRs

TABDLY

MaskfordelaytimeneededafterTABs

TAB0

NodelayforTABs

TAB1

DelayafterTABsdependingoncurrentcolumnposition

TAB2

Delay100millisecondsaftersendingTABs

TAB3

ExpandTABcharacterstospaces

BSDLY

MaskfordelaytimeneededafterBSs

BS0

NodelayforBSs

BS1

Delay50millisecondsaftersendingBSs

VTDLY

MaskfordelaytimeneededafterVTs

VT0

NodelayforVTs

VT1

Delay2secondsaftersendingVTs

FFDLY

MaskfordelaytimeneededafterFFs

FF0

NodelayforFFs

FF1

Delay2secondsaftersendingFFs

选择Processed输出

通过设置c_oflag中的OPOST选项来选择Processed输出:

options.c_oflag|=OPOST;

在所有的选项中,你大概只需要用ONLCR选项将换行符映射到CR-LF上。

选择Raw输出

c_oflag中重新设置OPOST选项就选择了Raw输出:

Options.c_oflag&=~OPOST;

取消OPOST选项时,c_oflag中的其他选项都将被忽略。

控制字符

c_cc字符数组包含控制字符的定义和超时参数。数组的元素都定义了常量。

Table9-ControlCharactersinthec_ccMember

Constant

Description

Key

VINTR

Interrupt

CTRL-C

VQUIT

Quit

CTRL-Z

VERASE

Erase

Backspace(BS)

VKILL

Kill-line

CTRL-U

VEOF

End-of-file

CTRL-D

VEOL

End-of-line

Carriagereturn(CR)

VEOL2

Secondend-of-line

Linefeed(LF)

VMIN

Minimumnumberofcharacterstoread

VTIME

Timetowaitfordata(tenthsofseconds)

<!--EndFragment-->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值