一个linux下基于电话线路的数据通信程序的设计与实现—免费毕业设计论文内容摘要:

的步骤 ∶ 预处理 (也称预编译, Preprocessing)、编译 (Compilation)、汇编 (Assembly)和连接(Linking)。 命令 gcc 首先调用 cpp 进行预处理,在预处理过程中,对源代码文件中的文件包含 (include)、预编译语句 (如宏定义 define 等 )进行分析。 接 着调用 cc1进行编译,这个阶段根据输入文件生成以 .o 为后缀的目标文件。 汇编过程是针对汇编语言的步骤。 当所有的目标文件都生成之后, gcc 就调用 ld 来完成最后的关键性工作,这个阶段就是连接。 在连接阶段,所有的目标文件被安排在可执行程序中的恰当的位置,同时,该程序所调用到的库函数也从各自所在的档案库中连到合适的地方。 gcc 编译器的调用参数大约有 100 多个,其中多数参数可能根本就用不到 ,开发过程中使用最多的命令就是: gcc O test , 是 C 语言源程序, test 是可执行文件, O 是 gcc 的参数, 对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行 第 7 页 共 24页 文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。 4 程序的设计 设计概要 此次设计之所以选择 Linux,是因为 Linux 支持各种硬件平台和外部设备,Linux 对串口的操作非常简单,功能齐全,且 Linux 有功能强大的 C语言编译器(gcc),使程序的可移植性非常好。 Linux 又是完全开放的操作系统,很大程度上, Linux 的开放性,赋予了其无穷的生命力。 本设计基于 Linux 操作系统,利用 POSIX termios 函数控制计算机串口,通过 AT 命令初始化本地 MODEM 并让本地 MMODEM 与异地 MODEM 进行拨号连接。 本设计使用的是 56K MODEM,不同于现在市面上常见的 ADSL MODEM。 连接成功后,通过读写计算机串口来实现文件传输 这个过程是用一个自编的文件传输协议来完成的。 整个程序使用 C 语言实现。 总体设想如图 3 所示: 图 3 预期设计效果 总体来说,设计可以分成两部分来进行: RS232C 与 MODEM。 但这两部分并不独立, MODEM 的初始化及拨号连接等等一切对 MODEM 的控 制和访问,都要通过串口,因为串口是计算机与 MODEM 的唯一通道。 两部分的关系如图 4 如示: 第 8 页 共 24页 图 4 RS232C 所以设计的关键是现实对 RS232C控制,然后再完成 MODEM 的部分。 RS232C 建立与打开 一个输入 /输出 (I/O)端口是用来将资料送入计算机及从计算机取出的通道,有许多种类的输出 /输入端口,现在要处理的是串行端口,每一个串行端口必须有一个输入 /输出地址,以及一个中断号码 (IRQ),有四个串口设备对应到 COM1 COM4: ttyS0 (COM1) address 0x3f8 IRQ 4 ttyS1 (COM2) address 0x2f8 IRQ 3 ttyS2 (COM3) address 0x3e8 IRQ 4 ttyS3 (COM4) address 0x2e8 IRQ 3 ttyS*是串口在 Linux 中的命名方式, COM*是串口在 Windows 中的命名方式,Linux 是以 ttyS0 开始命名的,与 Windows 从 COM1 开始命名不同。 ttyS0 和 ttyS2使用同一个中断 IRQ4, ttyS1 和 ttyS3 使用同一个中断 IRQ3,所以如果同时使用了 ttyS0 和 ttyS2 或者 ttyS1 和 ttyS3,就必须重设它们的中断才可以,幸运的是,现在常见的设备都不使用串口,所以连接 56K MODEM 时,多数情况都不必再重设串口中断,如果是外置 MODEM,则它占用的是 ttyS0,如果是内置 MODEM,则它占用的很可能是 ttyS2。 Linux 下可以使用 ls – l /dev/ttyS*来检查系统是否正确的建立了串口设备。 此次设计是在 Windows VMware Workstation虚拟机环境下安装的 操作系统,所以在进行设计之前,必须为虚拟机添加串口设备,具体是在设置中点击 添加,选择串口设备,然后一直选择下一步即可。 如果不设置虚拟机串口设备,在虚拟机下将无法识别到串口。 设置成功后,可以像使用真正的操作系统一样使用虚拟机,虚拟机下面的串口是真实的物理串口,而并非是虚拟出来的。 第 9 页 共 24页 VMware Workstation 中设备的使用很多都是真实的,不是模拟出来的。 确定串口正确建立以后,使用 open()函数来打开它。 像所有的设备一样,Linux 提供设备文件来挂载端口。 要访问一个串行端口,只要像访问文件一样来访问设备文件即可。 串行端口的设备文件名在 Linux 中是: /dev/ttyS*(*代 表 0,1, 2„ )。 以 ttyS0 以例, int fd。 fd = open(“ /dev/ttyS0” , O_RDWR | O_NOCTTY | O_NDELAY)。 O_RDWR 代表可读可写, O_NOCTTY 告诉 Linux 该程序不想成为那个端口的“控制终端”。 如果不指明这个,任何输入都会影响此进程。 O_NDELAY 标志该程序不关心 DCD 信号的输入状态,即无论另一端端口是否启用和运行。 如果不指明这个标志,此进程将休眠,直到另一端发送 DCD 信号过来。 如果不是以 root 身份登陆,在打开串口时,可能会发生权限不允 许的情况,这时候使用 chmod a+rw /dev/ttyS0 命令改变文件权限即可,或者直接用 root身份登陆。 串口设置与读写 c_cflag 控制项设置 在对串口进行读写之前,必须对串口进行设置,这也是串口操作部分最复杂,最重要的一步。 串口技术已经很成熟,相应的它的设置也变得很复杂,但相当一部分功能是针对已经被淘汰的外部设备,所以这里只用到了其中一部分 的功能。 多数系统支持 POSIX termios 终端串行接口来改变,例如波特率,字符尺寸等参数。 首先必须引入文件。 它定义了终端控制结构 termios 和POSIX 控制函数。 termios 是一个结构体,它的结构成员如表 2如示: 表 2 Termios 结构成员 成员 描述 c_cflag 控制项 c_lflag 线路项 c_iflag 输入项 c_oflag 输出项 c_cc 控制字符 c_ispeed 输入波特 (新接口 ) c_ospeed 输出波特 (新接口 ) 在对 termios 成员进行设置之前,首先要使用 tcgetattr(fd, amp。 option)读取 当 前 串 口 的 状 态 , termios 成 员 设 置 完 之 后 , 再 使 用 tcsetattr (fd,TCSANOW,amp。 option)将设置的内容写入计算机串口, option 是 termios 类型 第 10 页 共 24页 变量, TCSANOW 表明所有的改变立即生效,而不等待发送或者接收的数据结束。 c_cflag 成员控制波特率、数据位、校验、停止位和硬件流控制,所有支持的设置都有常数对应。 对应此次设计的 c_cflag 设置如下: cfsetispeed(amp。 options, B115200)。 //Buadrate 115200 cfsetospeed(amp。 options, B115200)。 |= (CLOCAL | CREAD)。 amp。 = ~CSIZE。 //Mask the character size bits |= CS8。 //Select 8 data bits amp。 = ~PARENB。 //NO amp。 = ~CSTOPB。 //One Stop bit cfsetispeed 和 cfsetospeed 函数用于设备波特率,上面设置的是 115200波特,可供选择的还有 B76800, B19200, B1200 等等。 有些 Linux 版本并不支持cfsetispeed 和 cfsetospeed,但仍可以用 |= B115200这种方式进行设置。 不同于波特率,没有函数可以用来设置字符尺寸,需要使用比特掩码的操作来完成。 CLOCAL 代表本地线不改变端口的拥有者, CREAD 表示接收有效。 CLOCAL | CREAD 将保证这个程序不会成为端口 的拥有者,从而不会妨碍控制工作和挂起信号并使串行接口驱动读取进入的数据。 由异步通信可知,串行数据中数据可以有 5 位、 6 位、 7 位、 8 位,并且可以选择奇偶校验,或者无校验。 最后的停止位也可以设置成 1位或者 2位。 CS8,~PARENB, ~CSTOPB 将把串行数据设置为:八位数据位,无奇偶校验, 1 位停止位。 CSIZE 是数据位数掩码,必须在设置 CS8之前使用,起清除的作用,会把之前对数据位数的设置清除掉。 c_cflag 还包括对硬件流设备的常数,这里不会用到,可以不予理会。 c_iflag、 c_lflag 和 c_oflag 设置 amp。 = ~(ICANON | ECHO | ECHOE | ISIG) amp。 = ~(INPCK | IGNPAR |IXON |IXOFF |IXANY)。 amp。 = ~OPOST。 输入模式成员 c_iflag 控制任何在端口接收字符的输入处理, INPCK 和IGNPAR 分别代表校验有效和忽略校验错误,但是并没有使用校验位,所以屏蔽这两项。 IXON、 IXOFF、 IXANY 分别是软件流控制 开启、软件流控制关闭和允许任何字符再次启动流,为简单起见,设计中不使用软件流控制串行通迅,所以屏 第 11 页 共 24页 蔽这三项。 c_lflag 控制输入字符如何被串行驱动使用,它和 c_oflag 的设置应该说是整个串口设置当中最重要的,它直接影响到串口的工作方式。 简单讲,串行设备有三种不同的的输入方式,需要为程序选择合适的工作方式: ◆ 标准输入模式。 这是终端设备的标准处理模式,这种方式下, read 会传回一整行完整的输入,一行的结束默认是以 NL、文件结束符,或是一个行结束字符。 ◆ 非标准输入模式。 此模式下,可以每次读取固定数 量的字符,并允许使用字符接收时间定时器。 这种模式可以用在每次读取固定长度字符串的程序中,或者所连接的设备会突然大量字符的情况下。 ◆ 等待来自多信号源的输入。 实际上这并不是另一种输入方式,它用于处理来自多个设备的数据。 非标准输入输出更适合此次项目, ICANON 代表标准模式,所以屏蔽它。 ECHO和 ECHOE 是关于回显的选项,如果串口另一端也要求回显的话,那就会造成串口两端反馈死循环,所以屏蔽它们。 ISIG 是让某些信号起作用,这里不需要这些信号,所以不也不考虑选择 ISIG。 而 c_oflag 是对输出数据进行 处理的成员项,相应的就有标准输出模式和非标准输出模式。 非标准输出模式更加灵活,适合做为本次设计的输出模式,而对这种模式的选择是非常简单的,只要屏蔽 c_cflag 的 OPOST 项即可,屏蔽 OPOST项, c_oflag 其余的项就都被忽略。 如果选择了 OPOST 项,那么就是标准输出模式。 其余的项大多出于历史原因要追溯到打印机和终端还不能和串行数据流保持一致的时候,现在已经没有使用价值了。 c_cc控制字符设置 [VMIN] = 0。 [VTIME] = 200。 c_cc 的结构是一个字符数组,它包含了控制字符和超时参数。 其中常用到的只有其中的 VMIN 和 VTIME 两个元素。 VMIN 和 VTIME 只有在非标准输入时才有效。 在非标准输入模式中,输入的数据并不组合成行,也不会进行 erase、 kill、delete 等输入处理。 这两个参数控制这种模式的输入行为: c_cc[VTIME]设定字符输入间隔时间计时器,而 c_cc[VMIN]设置满足读取函数的最少字节数。 MIN 0, TIME = 0: 函数在读到了 MIN值的字符数后返回。 MIN = 0, TIME 0: TIME 决定了超时值,读取函数在读到一个字节的字符,或者等待读取时间超了 TIME(t = TIME*)以后返回,也就是说,即使没有从 第 12 页 共 24页 串口读到数据,读取函数会在 TIME 时间后返回。 MIN 0, TIME 0: 读取函数会在收到了 MIN 字节的数据后,或者超 TIME时间没有收到数据后返回。 此时计时器会在每次收到字符的时候重新计时,且只在收到第一个字节后才启动。 所以读取函数最少要读取一个字节才能正常返回。 MIN = 0, TIME = 0: 读取函数会立即返回。 实际读取到的字符数, 或者要读到的字符数,会作为返回值返回。 设计时考虑到不能让串口接收不到数据陷入无限等待的僵死状态,并且又得让串口有一定长的等待时间等待数据到来,所以选择了。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。