1详解linux下的串口通讯开发分类:O3->Linux_驱动开发A4->总线通信2010-09-2321:05153人阅读评论(0)收藏举报串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。常用的串口是RS-232-C接口(又称EIARS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。串口通讯指的是计算机依次以位(bit)为单位来传送数据,串行通讯使用的范围很广,在嵌入式系统开发过程中串口通讯也经常用到通讯方式之一。Linux对所有设备的访问是通过设备文件来进行的,串口也是这样,为了访问串口,只需打开其设备文件即可操作串口设备。在linux系统下面,每一个串口设备都有设备文件与其关联,设备文件位于系统的/dev目录下面。如linux下的/ttyS0,/ttyS1分别表示的是串口1和串口2。下面来详细介绍linux下是如何使用串口的:1.串口操作需要用到的头文件#includestdio.h/*标准输入输出定义*/#includestdlib.h/*标准函数库定义*/#includeunistd.h/*Unix标准函数定义*/#includesys/types.h#includesys/stat.h#includefcntl.h/*文件控制定义*/#includetermios.h/*POSIX终端控制定义*/#includeerrno.h/*错误号定义*/#includestring.h/*字符串功能函数*/2.串口通讯波特率设置波特率的设置定义在asm/termbits.h,其包含在头文件termios.h里。常用的波特率常数如下:B0-------0B1800-------1800B50-----50B2400------2400B75-----75B4800------4800B110----110B9600------9600B134----134.5B19200-----19200B200----200B38400------38400B300----300B57600------57600B600----600B76800------76800B1200---1200B115200-----115200假定程序中想要设置通讯的波特率,使用cfsetispeed()和cfsetospeed()函数来操作,获取波特率信息是通过cfgetispeed()和cfgetospeed()函数来完成的。比如可以这样来指定串口通讯的波特率:#includestdio.h//头文件定义.......................structtermiosopt;/*定义指向termios结构类型的指针opt*/2/***************以下设置通讯波特率****************/cfsetispeed(&opt,B9600);/*指定输入波特率,9600bps*/cfsetospeed(&opt,B9600);/*指定输出波特率,9600bps*//************************************************/...................一般来说,输入、输出的波特率应该是一致的。3.串口属性配置在程序中,很容易配置串口的属性,这些属性定义在结构体structtermios中。为在程序中使用该结构体,需要包含文件termbits.h,该头文件定义了结构体structtermios。该结构体定义如下:#defineNCCS19structtermios{tcflag_tc_iflag;/*输入参数*/tcflag_tc_oflag;/*输出参数*/tcflag_tc_cflag;/*控制参数*/tcflag_tc_ispeed;/*输入波特率*/tcflag_tc_ospeed;/*输出波特率*/cc_tc_line;/*线控制*/cc_tc_cc[NCCS];/*控制字符*/};其中成员c_line在POSIX(PortableOperatingSystemInterfaceforUNIX)系统中不使用。对于支持POSIX终端接口的系统中,对于端口属性的设置和获取要用到两个重要的函数是:(1).inttcsetattr(intfd,intopt_DE,*ptr)该函数用来设置终端控制属性,其参数说明如下:fd:待操作的文件描述符opt_DE:选项值,有三个选项以供选择:TCSANOW:不等数据传输完毕就立即改变属性TCSADRAIN:等待所有数据传输结束才改变属性TCSAFLUSH:清空输入输出缓冲区才改变属性*ptr:指向termios结构的指针函数返回值:成功返回0,失败返回-1。(2).inttcgetattr(intfd,*ptr)该函数用来获取终端控制属性,它把串口的默认设置赋给了termios数据数据结构,其参数说明如下:fd:待操作的文件描述符*ptr:指向termios结构的指针函数返回值:成功返回0,失败返回-1。4.打开串口在前面已经提到linux下的串口访问是以设备文件形式进行的,所以打开串口也即是打开文件的操作。函数原型可以如下所示:intopen(“DE_name”,intopen_Status)参数说明:(1).DE_name:要打开的设备文件名3比如要打开串口1,即为/dev/ttyS0。(2).open_Status:文件打开方式,可采用下面的文件打开模式:O_RDONLY:以只读方式打开文件O_WRONLY:以只写方式打开文件O_RDWR:以读写方式打开文件O_APPEND:写入数据时添加到文件末尾O_CREATE:如果文件不存在则产生该文件,使用该标志需要设置访问权限位mode_tO_EXCL:指定该标志,并且指定了O_CREATE标志,如果打开的文件存在则会产生一个错误O_TRUNC:如果文件存在并且成功以写或者只写方式打开,则清除文件所有内容,使得文件长度变为0O_NOCTTY:如果打开的是一个终端设备,这个程序不会成为对应这个端口的控制终端,如果没有该标志,任何一个输入,例如键盘中止信号等,都将影响进程。O_NONBLOCK:该标志与早期使用的O_NDELAY标志作用差不多。程序不关心DCD信号线的状态,如果指定该标志,进程将一直在休眠状态,直到DCD信号线为0。函数返回值:成功返回文件描述符,如果失败返回-1例如假定以可读写方式打开/dev/ttyS0设备,就可以这样操作:#includestdio.h//头文件包含............intfd;/*文件描述符*/fd=open(/dev/ttyS0,O_RDWR|0_NOCTTY);/*以读写方式打开设备*/if(fd==-1)perror(CannotopenSerial_Port1/n!);/*打开失败时的错误提示*/................5.串口读操作(接收端)用open函数打开设备文件,函数返回一个文件描述符(filedescriptors,fd),通过文件描述符来访问文件。读串口操作是通过read函数来完成的。函数原型如下:intread(intfd,*buffer,length);参数说明:(1).intfd:文件描述符(2).*buffer:数据缓冲区(3).length:要读取的字节数函数返回值:读操作成功读取返回读取的字节数,失败则返回-1。6.串口写操作(发送端)写串口操作是通过write函数来完成的。函数原型如下:write(intfd,*buffer,length);参数说明:(1).fd:文件描述符(2).*buffer:存储写入数据的数据缓冲区4(3).length:写入缓冲去的数据字节数函数返回值:成功返回写入数据的字节数,该值通常等于length,如果写入失败返回-1。例如:向终端设备发送初始化命令#includestdio.h//头文件包含............intnsbuf[]={Hello,thisisaSerial_Porttest!/n};//待发送数据intlen_send=sizeof(sbuf);//发送缓冲区字节数定义n=write(fd,sbuf,len_send);//写缓冲区if(n==-1){printf(Wirtesbuferror./n);}............7.关闭串口对设备文件的操作与对普通文件的操作一样,打开操作之后还需要关闭,关闭串口用函数close()来操作,函数原型为:intclose(intfd);参数说明:fd:文件描述符函数返回值:成功返回0,失败返回-1。NAMEtermios,tcgetattr,tcsetattr,tcsendbreak,tcdrain,tcflush,tcflow,cfmakeraw,cfgetospeed,cfgetispeed,cfsetispeed,cfsetospeed-获取和设置终端属性,行控制,获取和设置波特率SYNOPSIS总览#includetermios.h#includeunistd.hinttcgetattr(intfd,structtermios*termios_p);inttcsetattr(intfd,intoptional_actions,structtermios*termios_p);inttcsendbreak(intfd,intduration);inttcdrain(intfd);5inttcflush(intfd,intqueue_selector);inttcflow(intfd,intaction);intcfmakeraw(structtermios*termios_p);speed_tcfgetispeed(structtermios*termios_p);speed_tcfgetospeed(structtermios*termios_p);intcfsetispeed(structtermios*termios_p,speed_tspeed);intcfsetospeed(structtermios*termios_p,speed_tspeed);DESCRIPTION描述termios函数族提供了一个常规的终端接口,用于控制非同步通信端口。这里描述的大部分属性有一个termios_p类型的参数,它是指向一个termios结构的指针。这个结构包含了至少下列成员:tcflag_tc_iflag;/*输入模式*/tcflag_tc_oflag;/*输出模式*/tcflag_tc_cflag;/*控制模式*/tcflag_tc_lflag;/*本地模式*/cc_tc_cc[NCCS];/*控制字符*/c_iflag标志常量:IGNBRK忽略输入中的BREAK状态。BRKINT如果设置了IGNBRK,将忽略BREAK。如果没有设置,但是设置了BRKINT,那么BREAK将使得输入和输出队列被刷新,如果终端是一个前台进程组的控制终端,这个进程组中所有进程将收到SIGINT信号。如果既未设置IGNBRK也未设置BRKINT,BREAK将视为与NUL字符同义,除非设置了PARMRK,这种情况下它被视为序列/377/0/0。IGNPAR忽略桢错误和奇偶校验错。PARMRK如果没有设置IGNPAR,在有奇偶校验错或桢错误的字符前插入/377/0。如果既没有设置IGNPAR也没有设置PARMRK,将有奇偶校验错或桢错误的字符视为/0。INPCK启用输入奇偶检测。ISTRIP去掉第八位。INLCR将输入中的NL翻译为CR。IGNCR忽略输入中的回车。ICRNL6将输入中的回车翻译为新行(除非设置了IGNCR)。IUCLC(不属于POSIX)将输入中的大