一个Linux下基于电话线路的数据通信程序的设计与实现
摘要
本设计基于Linux操作系统,控制本地MODEM通过电话线网向界地终端机所带MODEM拨号,并实现两台MODEM之间数据传输,达到两台计算机之间数据通信的目的。MODEM与计算机RS-232串行端口相连,Linux通过POSIXtermios接口控制计算机串行端口,方便实现了对计算机串行端口的设置和数据读写。计算机(DTE)与MODEM(DCE)之间数据交换,以及计算机对MODEM的控制,就是计算机对串行端口的读写。
本文作者完成了对RS-232串行端的设置和读写操作,利用AT命令控制MODEM拨号,和一个文件传输协议,实现了两台PC机利用MODEM通过公用电话网,传送和接收文件。
本设计旨在使没有安装网络的用户,利用56KMODEM,通过电话线网方便和对方传输数据。和比较Internet网络,电话线网更安全,分布更广泛。本设计就是利用了电话线网的广泛性和安全性。
关键词:Linux;串行端口;MODEM
TheDesign and Implementation of Data Transportation throughTelephone Line in Linux
Abstract
Thepurpose of the design is to control the local MODEM to dial remoteterminal
bytelephone line base on Linux operating system?Atthe same time.it can make the
datatransmit between two MODEMs to achieve the purpose of datatransportation, the MODEM is connected to the computer through theserial port RS-232. Linux can control the serial port of the computerby POSIX termios interface. That can carry out the setting and datareading/writing of the serial port, the data transmit betweencomputers (DTE) and MODEM (DCE), and the control from the computer tothe MODEM, namely, the reading/writing of the serial port from thecompute匚
Theauthor of this paper accomplishes the setting and reading/writingoperation, using the AT commands to control the MODEM dialing, and atransport protocols for files. All of these make two PCs send andreceive files from the public telephone line by using the MODEM. Thedesign is intended to make the user who has not installed the networkto transmit data with others by telephone lines using the 56k MODEM.
Comparedwith the Internet, the telephone line is safer and widelydistributed?The
designmakes use of the universality and the safety of the telephone line.
Keywords:Linux;serial port; MODEM
论文总页数:24页
1 引言.....................................................................1 1.1设计背景...........................................................1 1.2木设计的意义.......................................................1 1.3设计方法...........................................................1
1.4 理论依据...........................................................12 设计理论依据.............................................................1 2.1 Linux.....................................................................................................................................1 2.2 串行端口简介.......................................................2 2.2. 1 串彳亍通迅....................................................2 2.2.2 RS-232-C..................................................................................................................2 2.2.3 异步通迅......................................................3 2.3 MODEM简介........................................................4 2.3. 1 MODEM...................................................................................................................4 2.3. 2 AT命令.......................................................43 系统开发环境.............................................................5 3.1 系统开发环境.......................................................5
3.2 gcc简介............................................................54 程序的设计...............................................................6 4.1 设计概要...........................................................6 4.2 RS-232-C建立与打开..................................................7 4.3 串口设置与读写.....................................................8 4.3. 1 c_cflag控制项设置..............................................8 4.3. 2 ciflag、clflag 和coflag 设置.....................................9 4.3.3 c_cc控制字符设置.............................................10
4.3.4 读写串口.....................................................114.4 MODEM的控制.....................................................124. 4. 1 MODEM的两种工作状态........................................124. 4.2 DTE与DCE的握手...........................................124.4.3 MODEM拨号连接..............................................13
4.5 文件传输协议的设计.................................................145 编码实现.................................................................16 5.1 串口初始化实现.......................................................16 5.2 串口读写的实现.....................................................17 5.3
MODEM初始化的实现...............................................18 5.4 MODEM状态读取的实现..............................................206 程序测试.................................................................20 6.1 串口传输文件测试...................................................20 6.2
MODEM拨号连接并传输数据测试.....................................21结 论...................................................错误!未定义书签。
参考文献....................................................错误!未定义书签。
致谢...................................................错误!未定义书签。
声明...................................................错误!未定义书签。
1引言
1.1设计背景
现在,随着计算机网络技术的发展,国民收入的提高,互联网走进了千家万户,
但仍有很多计算机用户并没有安装宽带或其它网络设备。电话己经发展了一百多年,但
互联网只出现了不到五十年,英特网所分布的范围远远比不上公用电话网。
1.2本设计的意义
如果想传送份文件给对方,却苦恼于无法上互联网,那么用MODEM通过电话线发
送文件就变得非常有用处了。还有些特殊情况,当单位或工厂需要几台计算机之间数
据共亨时,进入互联网有安全隐患,配置局域网费用又很高,而且需要共亨的数据很
小,仅按字节计算,这时候利用MODEM通过公用电话网或电话专线传输数据,既经济,
又安全,维护也非常简单。
1.3设计方法
本设计基于Linux操作系统,用POSTXtermios函数控制计算机串口,使用AT指令操
作MODEM进行初始化及拨号连接,最后用一个自编的文件传输协议传输文件。
整个程序使用C语言实现。此次设计之所以选择Linux,是因为Linux有着丰富的应
用程序和开发工具,可以支持各种硬件平台和外部设备;Linux又是完全开放的操作系
统,很大程度上,Linux的开放性,赋予了其无穷的生命力。GCC的发展与Linux发展息
息相关,相辅相承。所以在Linux平台的基础上,选用GCC编绎代码。AT指令做为MODEM
的标准化语言,提供了丰富的MODEM初始化、拨号、挂机等等命令,AT命令简单的操作
方式,使MODEM控制变得很方便。
1.4理论依据
本次设计所需要的开发环境的搭建并不复杂,可是因为程序直接对计算机硬件进
行操作,需要对RS-232串行端口有比较深入的了解,必须清楚各引脚电信号的作用,
串口的工作方式,针对不同工作的方式,进行不同的设置。MODEM的功能非常丰富,这
给程序的实现也带来一定难度。通过完成本设计,既有助于深入了解计算机接口,又为
硬件控制编程打下了一定基础,而且还能熟悉Linux程序设计。
2设计理论依据
2.1 Linux
Linux操作系统核心最早是由芬兰的LinusTorvalds 1991年8月在芬兰赫尔辛基
大学上学时发布的[那年Torvals25岁],后來经过众多世界顶尖的软件工程师的不断
修改和完善,Linux得以在全球普及开来,在服务器领域及个人桌而版得到越来越多的
应用,在嵌入式开发方而更是具有其它操作系统无可比拟的优势,并以每年100%的用户
递增数量显示了Linux强大的力量。
本设计屮使用的POSIXCUNIX可移植标准)终端控制函数,少量修改就可以运行于 IRIX?,HP-UX, SunOS?, Solaris?, Digital UNIX?, Linux?,和许多其它的类UNIX操作系统。在不同的类UNIX操作系统么间的最大差别是串口设备和锁定文件的名字。并且Linux支持各种体系结构的计算机,所以本设计虽然仅在个人PC机上实现,但它对于不同体系结构的计算机,或者不同的类UNIX操作系统,都有很好的可移植性。
2.2串行端口简介
2.2.1串行通迅
计算机一次传输一位或多位的信息(数据),串行是指一次传输一位数据。串行通讯包括了大多数的网络设备、键盘、麦克风,调制解调器和终端。当进行串行通讯时,传送或接收的每个字(例如:字节或字符)是以每次一位传输的。每位或者为on或者off。有时也能听到以mark表示on状态和space表示off状态。
串行数据的速度常表示为比特每秒(〃bps〃)或波特率(〃波特〃)。这只是用于表示每秒能够传送的1和0的数量。追溯到计算机时代的早期,300波特被认为是很快的速度,但今天的计算机能够控制RS-232速度高达115,200波特!当波特率超过1,000,通常将看到速度被表示为千波特,或kbps(例如9.6k, 19. 2k 等等)。对于超过1,000,000的速度表示为兆波特,或者Mbps(例如1.5Mbps)。
2.2.2 RS-232-C
RS-232-C是标准的串行通讯电气接口,是由美国EIA(电子工业联合会)与BELL等公司一?起开发并于1969年公布的通信协议,这个标准对串行通信接口的有关问题,如信号线功能、电器特性都作了明确规定,它适合于数据传输速率在0~20000bit/s范围内的通信。由于通信设备厂商都生产与RS-232-C制式兼容的通信设备,因此,它作为一种标准,H前已在微机通信屮广泛采用,它不仅己被内置于每一台计算机,同时也已被内置于从微控制器到主机的多种类型的计算机及其相连接的设备。RS-232-C常用于连接到一个MODEM,其他拥有RS-232接口的设备包括打印机、数据采模块、测试装置和控制回路。另外,RS-232也可以直接应用于任何类型计算机之间的简单连接。 EIA-RS-232-C对电器特性、逻辑电平和各种信号线功能都作了规定。
在TxD和RxD±:
?逻辑1(MARK)=-3V~-15VO
?逻辑0(SPACE) =+3V?+15Vo
在RTS、CTS、DSR、DTR和DCD等控制线上:
?信号有效(接通,ON状态,正电压)二+3V?+15V。
?信号无效(断开,OFF状态,负电压)=-3V?-15V。
由于RS-232-C并未定义连接器的物理特性,因此,出现了DB-25、DB-15和DB-9
各种类型的连接器,其引脚的定义也齐不相同,现在最常见的是DB-9连接器。DB-9的信号引脚说明如表1所示:
表1RS-232备引脚含义
RS-232 Signals | |||
Pin | 描述 | Pin | 描述 |
1 DCD - Data Carrier Detect | 6 | DSR - Data Set Ready | |
| RXD - Received Data | 7 | RTS - Request To Send |
| TXD - Transmitted Data | 8 | CTS - Clear To Send |
4 | DTR - Data Terminal Ready | 9 | RI - Ring Detect |
5 | GND - Logic Ground | | |
还有其它两种常见的串行接口标准是RS-422和RS-574°RS-422使用低电压和微分信号,允许线缆长度到1000英尺(300米)。RS-574定义了9-pinPC串行接口和电
压。
2.2.3异步通迅
为使计算机理解进入它的串行数据,它需要一些途径决定哪里是字符的开始和结束。这里仅讨论并步串行数据。
在异步模式下,申行数据线保持在mark(1)状态,直到有字符传送。--位起始start位、字符内容的每一位、一位可选的校验位、以及一位或一位半的终止位。起始位始终是-?个space(0),从而告诉计算机新的串行数据到来。数据能够在任何吋候传送或接受,所以称做异步。
图1异步数据通讯
可选的校验是一个简单数据位的加和,表明了数据位包含偶数或奇数个1。如果是偶校验,当在字符屮的1是偶数个数时,校验位为0;如果是奇校验,当字符屮的1是奇数个时,校验位为0。其它常见的校验如space校验,mark校验,和无校验。Space校验意味着校验始终为0,[fl]' mark校验意味着校验位始终为1。无校验意味校验不存在或不传输。
停止余下的被称为停止位。这可以是1,1.5,或2位停止位在字符之间,始终是1。
位原先是用来给计算机时间处理前而的字符的,但现在只是用来同步计算机和接收字符。异步数据格式通常表示为〃8N1〃,〃7E1〃,诸如此类。它们相应地表示〃8位数
据,无校验,1位停止〃和〃7位数据,偶校验,1位停止〃。
2.3 MODEM 简介
2.3.1MODEM
H前最广泛使用的数据传输通道就是模拟电话线路。计算机所能处理的数字信号不能直接进入这样的模拟通道,MODEM就是用来实现数字信号和模拟信号相互转换的设备。MODEM从发送方串行接收数据,然后经过调制,将数字信号转换为模拟信号,最后通过电话网络传送到接收方,然后接收方的MODEM将电话线上信号解调,将模拟信号转换为数字信号,然后进入计算机通道。即MODEM实现了计算机数据与模拟电话线路适合传输的模拟信号Z间的相互转换。MODEM的分类和型号众多,为了方便Linux操作系统设置,本次设计选用外置56KMODEMoMODEM的工作过程如图2如示:
图2MODEM数模转换
2.3.2 AT 命令
和其它通信标准一样,MODEM通信也有其H己的一套规则和标准。Hayes公司的SmartMODEM系列产品已成为MODEM的事实上的标准,而几乎所有应用于计算机通信的MODEM均号称与HayesSmartMODEM兼容。
所谓Hayes兼容MODEM,主要是指它能识别并执行称为AT命令的某些命令和命令串。H前各厂家生产的MODEM除了可以执行最基本的Hayes命令集外,还有自己特有的命令。AT命令的建立使得DTE(DataTerminal Equipment,用于发送和接收数据的数据终端设备)从以上杂条屮解脱出来,振铃检测、载波检测、速率选择等等都可以由MODEM来完成。此吋TXD和RXD不仅仅是传输数据,还传送AT命令。DTE发送AT命令到MODEM,MODEM执行后通过RXD返回结果给DTE。
这些命令和返回结果符合RS-232C数据格式。MODEM由AT命令和几个特定的S寄存器的状态确定DTE发出的是命令还是数据。
3系统开发环境
3.1系统开发环境
本系统采用的软件工具有:
Windows平台虚拟机:VMw8re-workst8tioii-5.5. 1-19175操作系统:Radhat9.0 编辑器:VI
编译器:gcc3. 2.2 20030222
函数库:glibc2. 3. 2. so
系统头文件:glibcheader
3.2 gcc简介
Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。gcc是可以在多种硬体平台丄编译出可执行程序的超级编译器,其执行效率与一?般的编译器相比平均效率要高20%、30%。
Gcc编译器能将C、C++语言源程序、汇编程序和H标程序编译、连接成可执行文件,如果没有给岀可执行文件的名字,gcc将生成一个名为a.out的文件。在Linux系统屮,可执行文件没有统一的后缀,系统从文件的屈性来区分可执行文件和不可执行文件。血gcc则通过后缀来区别输入文件的类别。
虽然称gcc是C语言的编译器,但使用gcc由C语言源代码文件生成可执行文件的过程不仅仅是编译的过程,而是要经历四个相互关联的步骤:预处理(也称预编译,Preprocessing)> 编译(Compilation)> 汇编(Assembly)和连接(Linking)。
命令gcc首先调用cpp进行预处理,在预处理过程屮,对源代码文件小的文件包含(include)、预编译语句(如宏定义define等)进彳亍分析。接着调用ccl进行编译,这个阶段根据输入文件生成以.0为后缀的H标文件。汇编过程是针对汇编语言的步骤。当 gcc就调用Id来完成最后的关键性工作,这个阶段就是连接。所有的H标文件都生成Z后,
在连接阶段,所有的H标文件被安排在可执行程序屮的恰当的位置,同时,该程序所调用到的库函数也从各自所在的档案库小连到合适的地方。
gcc编译器的调用参数大约有100多个,其屮多数参数可能根本就用不到,开发过程屮使用最多的命令就是:gcc-0 test test, c, test, c是0语言源程序,test是可执行文件,-0是gcc的参数,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程屮进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。
4程序的设计
4.1设计概要
此次设计Z所以选择Linux,是因为Linux支持各种硬件平台和外部设备,Liinix对串口的操作非常简单,功能齐全,且Linux有功能强大的C语言编译器(gcc),使程序的可移植性非常好。Linux又是完全开放的操作系统,很大程度丄,Linux的开放性,赋予了其无穷的生命力。
本设计基于Linux操作系统,利用POSIXtermios函数控制计算机串口,通过AT命令初始化本地MODEM并让本地MMODEM与异地MODEM进行拨号连接。本设计使用的是56KMODEM,不同于现在市面上常见的ADSLMODEMo连接成功后,通过读写计算机串口来实现文件传输一这个过程是用一个自编的文件传输协议来完成的。整个程序使用C语
言实现。总体设想如图3所示:
图3预期设计效果
总体来说,设计可以分成两部分来进行:RS-232-C与MODEM。但这两部分并不,MODEM的初始化及拨号连接等等一切对MODEM的控制和访问,都要通过串口,因为串口是计算机与MODEM的唯--通道。两部分的关系如图4如示:
RS-232-C
图4RS-232-C
所以设计的关键是现实对RS-232-C控制,然后再完成MODEM的部分。
4.2 RS-232-C建立与打开
一个输入/输出仃/0)端口是用来将资料送入计算机及从计算机取出的通道,
有许多种类的输出/输入端口,现在要处理的是串行端口,每一个申行端口必须
有一个输入/输出地址,以及一个屮断号码(TRQ),有四个串口设备对应到COM1-
C0M4:
ttySO(COM1) address 0x3f8 IRQ
ttySl(COM2) address 0x2f8 IRQ
ttyS2(COM3) address 0x3e8 IRQ
ttyS3(COM4) address 0x2e8 IRQ
ttyS*是串口在Linux中的命名方式,COM*是串口在Windows中的命名方式,
Linux是以ttySO开始命名的,与Windows从COM1开始命名不同ottySO和ttyS2使用同一个中断IRQ4,ttySl和ttyS3使用同一个中断IRQ3,所以如果同时使
用了ttySO和ttyS2或者ttySl和ttyS3,就必须重设它们的中断才可以,幸运的是,现在常见的设备都不使用串口,所以连接56KMODEM时,多数情况都不必再重设串口中断,如果是外置MODEM,则它占用的是ttySO,如果是内置MODEM,贝U它占用的很可能是ttyS2oLinux下可以使用Is- 1 /dev/ttyS*来检查系统
是否正确的建立了串口设备。
此次设计是在WindowsVMware Workstation虚拟机环境下安装的Radhat9.0
操作系统,所以在进行设计之前,必须为虚拟机添加出口设备,具体是在设置小点击添加,选择串口设备,然后一直选择下一步即可。如果不设置虚拟机串口设备,在虚拟机下将无法识别到串口。设置成功后,可以像使用真正的操作系统一样使用虚拟机,虚拟机下面的串口是真实的物理串口,而并非是虚拟出来的。
VMwareWorkstation屮设备的使用很多都是真实的,不是模拟出来的。
确定串口正确建立以后,使用open()函数来打开它。像所有的设备一样,Linux提供设备文件来挂载端口。要访问一个串行端口,只要像访问文件一样来访问设备文件即可。串行端口的设备文件名在Linux中是:/dev/ttyS*(*代表0,1, 2…)。以ttySO以例,
intfd;
fd二open(u/dev/ttyS0", 0 RDWR | 0 NOCTTY | 0 NDELAY);
0RDWR代表可读可写,0NOCTTY告诉Linux该程序不想成为那个端口的“控制终端”。如果不指明这个,任何输入都会影响此进程。0NDELAY标志该程序不关心DCD信号的输入状态,即无论另一端端口是否启用和运行。如果不指明这个标志,此进程将休眠,直到另一端发送DCD信号过来。
如果不是以mot身份登陆,在打开审口吋,可能会发生权限不允许的情况,这时候使用chmoda+rw /dev/ttySO命令改变文件权限即可,或者直接用root身份登陆。
4.3串口设置与读写
4.3.1c.cflag控制项设置
在对串口进行读写之前,必须对串口进行设置,这也是串口操作部分最复杂,最
重要的一步。串口技术已经很成熟,相应的它的设置也变得很复杂,但相半一部分功
能是针对已经被淘汰的外部设备,所以这里只用到了其屮一部分的功能。
多数系统支持POSIXtermiOS终端串行接口来改变,例如波特率,字符尺寸等参数。首先必须引入文件<termios.h>。它定义了终端控制结构termios和POSIX控制函数。termios是一个结构体,它的结构成员如表2如示:
表2Termios结构成员
成员 | 描述 |
c cflag | 控制项 |
c_lflag | 线路项 |
ciflag | 输入项 |
c_of1ag | 输出项 |
c_cc | 控制字符 |
c_ispeed | 输入波特(新接口) |
c_ospeed | 输出波特(新接口) |
在对termios成员进行设置之前,首先要使用tcgetattr(fd, feoption)读取当前串口的状态,termios成员设置完之后,再使用tcsetattr(fd, TCSANOW, &option)将设置的内容写入计算机串口,option是termios类型变量,TCSANOW表明所有的改变立即生效,血不等待发送或者接收的数据结束。
ccflag成员控制波特率、数据位、校验、停止位和硬件流控制,所有支持的设
置都有常数对应。对应此次设计的ccflag设置如下:
cfsetispeed(&options, | Bl | //Buadrate 115200 |
cfsetospeed(&options, | 15200); (CLOCAL | CREAD); | |||
options, c cflag | 1= | |||
options. c_cflag | &二 | CSIZE; | //Mask the character size | |
options. c_cflag | 1= | CS8; | bits | //Select 8 data bits |
options, c cflag | &二 | 'PARENB; | //NO | |
options. c_cflag | &二 | CSTOPB; | //One Stop bit | |
cfsetispeed和cfsetospeed函数用于设备波特率,上面设置的是115200波特,可供选择的还有B76800,B19200, B1200等等。有些Linux版本并不支持cfsetispeed和cfsetospeed,但仍可以用options,c cflag | = B115200 这种方式进行设置。
不同于波特率,没有函数可以用来设置字符尺寸,需要使用比特掩码的操作来完成。CL0CAL代表本地线不改变端口的拥有者,CREAD表示接收有效。CL0CALI CREAD将保证这个程序不会成为端口的拥有者,从血不会妨碍控制工作和挂起信号并使串行接口驱动读取进入的数据。
由界步通信可知,串行数据中数据可以有5位、6位、7位、8位,并且可以选择奇偶校验,或者无校验。最后的停止位也可以设置成1位或者2位。CS8,、卩ARENB,'CST0PB将把申行数据设置为:八位数据位,无奇偶校验,1位停止位。CSIZE是数据位数掩码,必须在设置CS8之前使用,起清除的作用,会把之前对数据位数的设置清除掉。 c.cflag还包括对硬件流设备的常数,这里不会用到,可以不予理会。
4.3, 2 c_iflag> c_lflag 和c_oflag设置
options. c_lflag | &二 | | | 、(ICAN0N | ECHO | ECHOE | ISIG) | |
options, c iflag | &二 | 、(INPCK | IGNPAR IIXON |IXOFF |IXANY); | ||
options, c oflag | &二 | OPOST; | |||
输入模式成员c_iflag控制任何在端口接收字符的输入处理,INPCK和IGNPAR分别
代表校验有效和忽略校验错误,但是并没有使用校验位,所以屏蔽这两项。1X07、IXOFF、IXANY分别是软件流控制开启、软件流控制关闭和允许任何字符再次启动流,为简单
起见,设计屮不使用软件流控制串行通迅,所以屏蔽这三项。
Clflag控制输入字符如何被串行驱动使用,它和coflag的设置应该说是整个串口设置当屮最重要的,它直接影响到串口的工作方式。简单讲,串行设备有三种不同的的输入方式,需要为程序选择合适的工作方式:
? 标准输入模式。这是终端设备的标准处理模式,这种方式下,read会传回一
整行完整的输入,一行的结束默认是以NL、文件结束符,或是一个行结束字符。?非标准输入模式。此模式下,可以每次读取固定数量的字符,并允许使用字
符接收时间定时器。这种模式可以用在每次读取固定长度字符串的程序屮,或者所连
接的设备会突然大量字符的情况下。
? 等待来自多信号源的输入。实际上这并不是另一种输入方式,它用于处理来
自多个设备的数据。
非标准输入输岀更适合此次项H,ICAN0N代表标准模式,所以屏蔽它°ECH0和ECH0E是关于回显的选项,如果审口另一端也要求回显的话,那就会造成串口两端反馈死循环,所以屏蔽它们。ISIG是让某些信号起作用,这里不需要这些信号,所以不也不考虑选择ISIGo
血coflag是对输出数据进行处理的成员项,相应的就有标准输岀模式和非标准输岀模式。非标准输岀模式更加灵活,适合做为本次设计的输出模式,而对这种模式的选择是非常简单的,只要屏蔽ccflag的0P0ST项即可,屏蔽0P0ST项,coflag其余的项就都被忽略。如果选择了OPOST项,那么就是标准输岀模式。其余的项大多出于历史原因要追溯到打印机和终端还不能和出行数据流保持一致的时候,现在已经没有使用价值了。
4.3.3 c_cc控制字符设置
options,c cc[VMIN] = 0;
options,c cc[VTIME] = 200;
Ccc的结构是一个字符数组,它包含了控制字符和超时参数。其屮常用到的只有其屮的VMIN和VTIME两个元素。VMIN和VTIME只有在非标准输入时才有效。
在非标准输入模式中,输入的数据并不组合成行,也不会进行erase,k订1、delete等输入处理。这两个参数控制这种模式的输入行为:ccc[VTIME]设定字符输入间隔时间计时器,[ftc ccEVMIN]设置满足读取函数的最少字节数。
MIN> 0, TIME = 0:函数在读到了MIN值的字符数后返回。
MIN= 0, TIME > 0: TIME决定了超时值,读取函数在读到一个字节的字符,或者等待读取时间超TTIME(t = TIME*0. Is)以后返回,也就是说,即使没有从串口读到数据,读取函数会在TIME时间后返回。
MIN> 0, TIME > 0:读取函数会在收到了MIN字节的数据后,或者超TIME时间没
有收到数据后返回。此时计时器会在每次收到字符的吋候重新计时,且只在收到第一
个字节后才启动。所以读取函数最少要读取一个字节才能正常返回。
MIN= 0, TIME = 0:读取函数会立即返回。实际读取到的字符数,或者要读到的
字符数,会作为返回值返回。
设计时考虑到不能让串口接收不到数据陷入无限等待的僵死状态,并且又得让串
口有一定长的等待时间等待数据到来,所以选择了MIN= 0, TIME > 0的组合,即在没有数据到来时,会等待TIME时间,如果超过TIME仍没有数据到来,则读取串口的函数仍可以返回。TIME的值的大小可以根据不同情况血定,但是不能太长,超过30s程序就会报错,这里选择的是200(20s) o MIN和TIME需要配合 fcntl(fd, F SETFL, 0)使用,fcntl(fd, F SETFL, 0)作用是当串口没有接收到字符时,阻塞等待一段时间。这时对MIN,TIME的设置才可以起作用。如果不想让串口阻塞,则可以设置fcntl(fd,F SETFL, FNDELAY),这时它与MIN二0,TIME二0得到的结果相同ofcntl函数是在open函数后而加入的。可以用^include<fcntl. h>将其函数声明加入程序。
最后,将设置的内容存入串口tcsetattr(fd, TCSANOW, ftoption), $口设置
就完成了。
4.3.4读写串口
写数据到串口是很简单的,只需要使用write()系统呼叫去传送数据:
n= write (fd, “ATZ/R” , 4);
if(n < 4 )
printf(uwriteto serial port failed!;
从串口读取数据:
n=read(fd, rdata, 1);
rdata是预先先定义好的字符数组,耍让Tdata足够大,才不会发生数据溢出错误。串口本身有4K的读写缓存,不同的计算机可能缓存大小不一样。不能一次性读写超过串口缓存本身大小的字符数,不过4K已经足够使用了。
向串口写数据往往一次性就能成功,例如一次性往串口写100个字符,但若从串口读这100个字符,根据MIN和TIME设置的不同,可能需要读取两次才能将这100个字符完整读岀来。所以MIN和TIME的设置很重要。同时,串口波特率越高,一次性把串口数
据读完的机率也越小。
4.4 MODEM的控制
4.4.1MODEM的两种工作状态
MODEM的状态可以分为命令状态和在线状态。除了拨号占据短暂的时间Z外,MODEM总是处于其中一种状态。当MODEM启动后,首先处于命令状态,连接后进入在线状态。在命令状态下MODEM以AT命令形式接受命令,例指示MODEM去拨号或当电话响铃时给予自动应答。在在线状态下,MODEM与远端系统通信。这时MODEM不再尝对发送给它的数据进行解释,而是直接将其发送出去。这两种状态之间可以相互转换。
当MODEM处于命令状态时,MODEM不是和远端系统通信,血是准备接受命令,此时MODEM一般处于挂机状态(离线命令状态),但也可以处于摘机状态(在线命令状态)□MODEM接收并解释AT命令,DET只有在命令状态才能对MODEM进行控制。在线状态又称为
联机状态或数据状态,半通信双方握手完成,建立通信链路后,MODEM就可以发送和接收数据,MODEM不再对接收到的数据分析处理,而是直接将其发送岀去。MODEM状态Z间的转换如图5所示:
图5MODEM T.作状态转换
设计的H的就是要让MODEM由开机吋的命令状态转入在线状态,此吋通过串口发给MODEM的数据不经MODEM处理的被传出去,从远处接收到的数据也不经MODEM处理的被传到串口。一旦MODEM进入在线状态,便可以忽略MODEM的存在,就好象两台计算机之
间通过串口连接进行数据通迅-样。
4.4.2 DTE与DCE的握手
DTE(Data Terminal Equipment)与DCE(Dats Communications Equipment) 通过九针RS-232-C连接,其针脚含义如表3所示。
表3RS-232 Signals
RS-232 Signals | |||
Pin | 描述 | Pin | 描述 |
1 DCD - Data Carrier Detect | 6 | DSR - Data Set Ready | |
” RXD - Received Data | 7 | RTS - Request To Send | |
n | TXD 一 Transmitted Data | 8 | CTS 一 Clear To Send |
DTR - Data Terminal Ready | 9 | Rl - Ring Detect | |
r | GND - Logic Ground | | |
DSR、DTR:数据机(DCE)准备好、数据终端(DTE)准备好,只表示设备本身
可用。
首先,通过电话机拨号呼叫对方,电话交换台向对方发出拨号呼叫信号,当对方DCE收到该信号后,使RI(振铃信号)有效,通知DTE,已被呼叫。当对方“摘机”后,两方建立了通信链路
若计算机要发送数据至对方,首先通过接口电路(DTE)发出RTS(请求发送)信号。此时,若DCE(MODEM)允许发送,则向DTE回答DTE回答CTS(允许发送)信号。一般可直接将RTS/CTS接高电平,即只要通信链路己经建立,就可传送信号。(RTS/CTS可只用于半双工系统屮做发送方式和接收方式的切换。)大多数情况下都不需要用RTS/CTS对通信进行控制,所以认为RTS/CTS总是有效的。
当DTE获得CTS信号后,通过TxD线向DCE发出串行信号,DCE(MODEM)将这些数
字信号调制成模拟信号(载波信号),传向对方。
计算机向DTE“数据输出寄存器”传送新的数据前,应检查MODEM的状态和数据输出寄存器为空。出对方的DCE收到载波信号后,向对方的DTE发出DCD信号(数据载波检出),通知其DTE准备接收,同吋,将载波信号解调为数据信号,从RxD线上送给DTE,DTE通过串行接收移位寄存器对接收到的位流进行移位,当收到1个字符的全部位流后,把该字符的数据位送到数据输入寄存器,CPU可以从数据输入寄存器读取字
符。
在串口设置部分,已经设置DCD信号不影响串口工作,即使没有DCD信号串口依然不会睡眠,可以始终保持准备接收状态。所以虽然上面述说了很多关于DTE与DCD数据通信吋握手的方法,但在前面的串口设置屮已经将其统统设置为总是有效,所以在与MODEM通信时可以忽略它们。
4.4.3 MODEM拨号连接
前面对串口的设置大大简化了MODEM部分所需要做的工作,不过在让MODEM拨号之前先要对MODEM进行初始化。这里只使用了“ATEOVO”对MODEM初始化。MODEM的功能已经很完善,除了二进制数据传输以外,现在大部分MODEM都可以收发传
真,语音传输,加ZMODEM对特殊环境的处理(如专线拨号),使MODEM的设置也变得
非常繁杂。但这里使用的是MODEM最常用,最简单的功能,而且是用在公用电话网
丄,所以省去了很多麻烦,直接使用出厂设置都可以。这里对MODEM的初始化只是调
整一下MODEM命令回显数据的格式。
AT命令的种类有很多种,有用户接口命令、拨号呼叫命令、应答命令等等13种Z
多,血有很多拨号连接软件对MODEM的初始化也只限于用户接口方面,因为各利-
MODEM都自带有厂家设置的出厂设置,这对拨号丄网等普通应用已经足够了。
? En
缺省值:1
功能描述:命令回显。该命令控制MODEM在命令状态打开或关闭AT命令回显,很显
然命令回显不利用对MODEM返回数据的判断,所以关闭它。(这个功能只控制命令本身
的回显,血MODEM状态的返回不会因此受到影响)on = 0代表关闭回显。
?Vn
缺省值:1
功能描述:结果码格式。该命令选择MODEM返回给DTE的结果码是数字形还是字符
形式。例如ATMO命令被正确执行后,将返回0(数字型)或0K(字符型)。n二0代表以
数字形显示结果码。(显然数字型更利于判断MODEM返回的结果)
设计屮将MODEM初始化为无命令回显,以数字型返回。
这时候就可以让MODEM拨号了,write(fd,“ATDT12345678\r”,13)□跟
普通的往串口写数据是一样的。D是拨号命令,T修饰D命令,表示拨打的是音频电话,(
P表示脉冲电话,就是己经被淘汰的带拨号盘的电话)后而加要拨打的号码即可。对方
听到铃响,只要往串口写入应答命令(ATA)即可使双方建立起连接。(设置S0寄存器
为n>0,就可以在n声铃响后自动应答;如果S0寄存器为0,则需要手动应答。)
等MODEM连接成功,MODEM会返回CONNECT(数字型号“1”)+波特率,表示两台MODEM
以指定的波特率连接,波特率是值是以低速MODEM的波特率为准的。现在就可以开始传
送数据给对方了。
4?5文件传输协议的设计
丄而的设计已经实现一方写入数据,而另一方能接收到数据的功能了,而且除外
界干扰外,数据不会出错。要实现传送文件的功能,还需要打开文件,将文件屮的字
符一个一个的读取出来等等文件操作的功能,这可以由gcc中提供的文件操作库函数来
完成,血且这些存函数的功能非常强大。
现在要做一个简单的文件传输协议来完成数据传输,不仅仅有对文件的操作,其
屮最重要的是对数据的校验方式的设计。总体思路是:发送方发送一个字符,接收方
收到以后判断此字符是新的字符还是对前一个接收到的字符的修改,如果是对前一个字符的修改,说明前一个字符在传输的过程屮出错,则用这个修改字符覆盖掉前一个字符;如果是新字符,则把它赋值给一个变量,等待往接收文件屮写入,并把前一个字符存入接收文件。接收处理完成之后,还需把接收到的字符返还给发送方。发送方将从接收方送来的字符与原发送字符做比较,如果相等,则说明传输过程屮没有出错,那么就接着发送下一个字符,直到文件结束;如果不相等,则说明传输过程小岀现了错误,那么重新把这个字符发一遍,直到发送方发送的字符和接收到的字符相等为止。
为了在数据屮加入控制信息,将发送文件屮的单字符分成高四位与低四低分别发送,文件本身的4位放在新的八位数据的低4位,新的数据的高4位放控制信息。在新数据高4位屮:
bit4|bit5= 00,表示是新的数据;
bit4|bit5= 01,表示是重新发送的数据;
bit4|bit5= 10,表示文件名结束;
bit4|bit5= 11,表示文件结束。
发送方的发送函数流程如图6如示:
接收方的接收函数流程如图7如示:
图7receive函数流程
5编码实现
5.1串口初始化实现
对串口进行正确的设置,串口才能正常工作,得到期望的结果,对串口设置是通过修改POSTXTermios成员项进彳亍的:
voidinit_port (void)
{
structtermios options;
fcntl (fd, F_SETFL, 0); tcgetattr(fd, &options);
〃读不到数据即阻塞串口〃获得串口的设置
cfsetispeed(&options, | B115200); | //波特率115200 |
cfsetospeed(&opt i crns, | B115200); |
options?c cflag |=
(CL0CAL| OREAD);
options, c cflag | &二 | ~CSIZE; | 〃屏蔽数据位大小 |
options, c cflag | 1 = | CS8; | 〃选择8位数据传输 |
options, c cflag | &二 | 'PARENB; | 〃无奇偶校验 |
options, c cflag | &二 | ~CSTOPB; | //I位停止位 |
/*非标准输入*/
5.2 | options.c iflag | &二 | '(INPCK | | IGNPAR IXON IXOFF |IXANY) | ||||
options.c Iflag | &二 | '(ICANON | | ECHO | ECHOE | ISIG); | |||||
options.c oflag | &二 | 、OPOST; | 〃非标准输岀 | |||||
options, c | = | 0; | ||||||
cc[VMIN_ | 200; | //20s内读不到数据就退出 | ||||||
tcflush(fd, TCIFLUSH); | 〃刷新数据线 | |||||||
tcsetattr (fd, TCSANOW, &options) ; | 〃将新的设置写入串口 | |||||||
串口读写的实现 | ||||||||
对串口的读写是通过"词()和write()來实现的,跟对文件的操作一样(串口是个特殊的文件),
写串口函数流程图如图8如示:
图8write函数流程
读出口函数流程如图9如示:
图9read函数流程
5.3MODEM初始化的实现
intinit MODEM(void)
{
/*如果第一次初始化失败则进行第二次,如果第二次也失败则程序退出*/ write_to_MODEM(/zATE0V0\r,z,7);
if(read_from_MODEM(OK) != 1 )
{
/*第二次初始化*/
write_toJIODEM(/zATE0V0\r,z,7);
if(read^fromJfODEM(OK) !二1)
{
/*二次初始化失败,可能是MODEM木身出了问题*/printf(^Init MODEM failed, check your MODEM"); return 0;
}
}
return1;
}
在前面,已经对串口进行了设置,但当吋的设置,是用于文件传输的.刚才对串口的设置已经不合适用来配合MODEM工作了.之前c_cc[VMIN]二0,c_cc [VMIN]二200的含义是如果超过20s没有读到数据则read()退出,那是为了防止串口始终读不到数据陷入僵死状态.现在,半对MODEM进行控制的吋候,拨号这个过程一般都要超过1分钟,这个过程结束以后MODEM才会把状态返还给串口,所以串口应该有长吋间等待的能力,否则MODEM的状态还没发给串口,串口就已经从read()退岀了?所以当控制MODEM的时候应该对Z前串口的设置进行一些改动.voidinit_port for MODEM()
{
structtermios options;
fcntl(fd, F SETFL, 0);
tcgetattr(fd, &options);
options,c cc[VMIN] = 1;
options, c cc[VTIME] = 0; tcflush(fd, TCIFLUSH);
//至少读到一个数据才返回
tcsetattr(fd, TCSANOW, &options);
}
当拨号结束进入数据通迅阶段Z后,还需要把串口设置恢复:void recover port (void)
{
struct termios options;
fcntl (fd, F SETFL, 0);
tcgetattr(fd, &options);
options, c cc[VMIN] = 0;
options, c cc [VTIME] = 200;
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &options);
}
5.4MODEM状态读取的实现
6程序测试
6.1串口传输文件测试
程序测试的硬件条件:两台56KMODEM,分别接到公用电话网电话线丄;程序测试的软件环境:inux操作系统。
Linux操作系统对内置MODEM的支持非常差,尤其内置软猫,大部分内置软猫在Linux上都无法识别。在进行程序测试吋,我只找到一台外置MODEM和一台内置软猫。
内置软猫只能用在WTNDOWS机上。外置MODEM是即插即用,直接接在Linux机上就可以用,
我的设计的文本传输协议无法在Windows上面工作,所以我不得不把程序测试分成两部分进行?:串口文件传输和MODEM拨号连接并传输数据.
在串口通信测试屮,我首先将程序分别安装到两台装有Linux操作系统的PC机上,把其||咲于MODEM部分的代码注释掉。一台电脑设为接收端(main函数屮调用receive_file()),另一台电脑设为发送端(main函数中调用send_file()),编译连接。再将这两台电 脑的RS-232-C串口连接——让它们的2、3脚交叉连接(RxD、TxD),5脚对接(GND)。这时环境搭建完毕,我先运行接收程序,再运行发送程序,这吋候显示数据通信开始。
等文件传输结束,在接收端可以找到发送端发来的文件。比较接收端与发送端的用于测试的文件之后发现,两个文件是相同的,证明串口通信部分程序工作正常。(注:如果先启动发送端,再启动接收端,两边程序都会被阻塞。发送端先启用的话,数据马
上被送到接收端串口,但接收端串口还没被启动,接收端open()口Z后,Z前被发 来的数据就会丢失了。) 6.2MODEM拨号连接并传输数据测试
在使用WINDOWS操作系统的电脑上安装内置MODEM,用WIN串口调试工具控制串口;在使用Linux操作系统的电脑上安装外置MODEM,让本设计的程序来控制这台电脑的串口。将两台电脑上的MODEM分别与两根电话线接连,硬件环境就搭建完毕。
将程序安装到Linux机屮,把其中有关文件传输协议的部分注释掉,留下MODEM初始化与拨号部分。
我先在WINDOWS端发起拨号连接,半分钟后Linux端振铃响起(我用了IC卡,所以拨号过程有点漫长)。启动Linux端的程序,它会检测并接听外而发起的拨号请求。略等几秒,屏幕上显示CONNECT115200,表示连接成功,这时候MODEM会安静下来。WINDOWS端使用WIN出口调试工具发送字符出,Linux端可以完整接收,并且无差错;同样,Linux端发送字符审,WINDOWS端可以完整接收,并且无差错。
Linux端发起拨号连接‘Windows端应答,仍然成功建立了连接。
在MODEM介绍部分知道,只要MODEM建立起连接,MODEM便将出口发送给它的数据全部转发岀去,血不对其进行解释。丄而的测试,已经证明在双方连接成功的情况下,可以进行字符串的传输,所以基于单个字符传输的文件传送协议也可以正常工作。
Copyright © 2019- aiwanbo.com 版权所有 赣ICP备2024042808号-3
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务