第二章:配置串口
这一章介绍怎样使用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:启用字符接收器。
波特率常数(CBAUD,B9600,etc.)用于缺少c_ispeed和c_ospeed成员的旧接口。下一节介绍用于设置波特率的POSIX函数。
注:决不能直接初始化c_cflag(或其他flag)。应该使用AND,OR或NOT等位操作符来置1或清0成员中的位。不同的操作系统版本的位操作可能不同,使用位操作符可以避免错误操作一个新串行设备所需要的标志位。
1)设置波特率
不同的操作系统中,波特率储存的位置也不同。旧的接口将波特率按照Table4中的常量保存c_cflag中。新的实现方法提供了c_ispeed和c_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结构。设置了波特率、使能本地模式和串行数据接收后,使用tcsetattr(3)使新的配置生效。常量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_RTSCTS或CRTSCTS常量,那就很可能支持硬件流控制。使用下面的代码可以使能硬件流控制:
options.c_cflag|=CNEW_RTSCTS;/*AlsocalledCRTSCTS*/
关闭硬件流控制:
options.c_cflag&=~CNEW_RTSCTS;
本地选项
本地模式成员c_lflag用于控制串行设备如何管理输入字符。通常可以将c_lflag配置为canonical或raw。
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)字符。选择这个模式的话,你需要选择ICANON,ECHO和ECHOE选项:
options.c_lflag|=(ICANON|ECHO|ECHOE);
选择RawInput
Rawinput是不做任何处理的。输入字符被收到后就直接传送。你需要取消ICANON、ECHO、ECHOE和ISIG选项来选择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,PARMRK和ISTRIP。通常你需要选择INPCK和ISTRIP来使能输入奇偶校验并去掉数据中的校验位:
options.c_iflag|=(INPCK|ISTRIP);
IGNPAR是一个危险的选项,它告诉串口忽略校验错误并让数据通过,就想没用发生错误一样。这在测试通信连接的质量时有用,通常没有实用价值。
PARMRK会使校验错误被标记为“marked",并使用特殊的字符放入输入流中。如果使能IGNPAR,一个空字符(000octal)会被加入到校验错误的前面。否则,DEL(177octal)和NUL字符会和错误字符一起发生。
设置软件流控制
使用IXON、IXOFf和IXANY常量来使能软件流控制:
options.c_iflag|=(IXON|IXOFF|IXANY);
取消软件流控制只需掩掉这些位:
options.c_iflag&=(IXON|IXOFF|IXANY);
XON(开始数据)和XOFF(停止数据)字符定义在下面描述的c_cc数组中。
输出选项
C_oflag成员包含了输出过滤选项。像输入模式一样,你可以选择processed或raw数据输出。
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) | |
本文详细介绍如何使用C语言及POSIX终端接口配置串口,包括设置波特率、字符大小、奇偶校验、硬件流控制等内容,并提供具体示例代码。
2566

被折叠的 条评论
为什么被折叠?



