串口是常用的计算机与外部串行设备之间的数据传输通道,由于串行通信方便易行,所以应用广泛。现在国际上不断有串口新技术及新规格推出,结合社会各方面需要,串口通信发展的空间庞大。串口通讯技术因其自身的优势和特性,及计算机技术的广泛应用深入到生活和生产的各个领域,世界上数以亿计的通讯设备都以串口通讯的方式。在进行着数据的传输。在一个应用系统中,同时使用Windows和Linux操作系统,合理地分配资源,各取所长,是实现系统高性能的有效途径。为了使两个不同操作系统能协同工作,实现资源和数据共享,需要在两者问进行通信。本课题分别研究Linux操作系统与Window操作系统平台下串口通信程序设计。串口通信程序设计的主要模块分别采用Visual C++6.0编程环境与Unux进行开发。本文同时给出了两种编程环境中串口通信程序设计相同点与相异点,以及它们的比较。
1、开发环境
1.1硬件环境
能运行Windows 9X/2000/XP和Linux系统的PC机,配有两个串行口或者是两台配有串行口的PC机,RS232串口连接线。
1.2软件环境
Visual C++6.0,GCC编程器,Windows9X/2000/XP操作系统和Liunx操作系统。
1.3设计原理图
PCI运行Windows系统,PCII运行Linux系统。他们通过RS232串行线连接实现跨平台间的串口通信。
2 、Windows平台下串口通信程序设计
2·1 打开串口
嵌入式软件开发,系统集成。用CreateFile函数来打开串El句柄,首先看到,该类中的串口句柄为HANDLE in—hComm;该句柄在应用CreateFile()函数创建后,就得到了指定了的串口句柄,其后,几乎所有的函数要对串口进行操作时,必须通过ITI—hComm进行。因为串口句柄在打开时,设置了异步(重叠)I/O操作方式,冈此,必须对串口的超时做出说明,并在对超时变量进行设置。
2.2设置串口
在打开通讯设备句柄后,常常需要对串口进行一些初始化配置工作。这需要通过一个DCB结构来进行。DCB结构包含了诸如波特率、数据位数、奇偶校验和停止位数等信息。在查询或配置串口的属性时,都要用DCB结构来作为缓冲区。一般用CreateFile打开串口后,可以调用GetCommState函数来获取串口的初始配置。要修改串口的配置,应该先修改DCB结构,然后再调用SetCommState函数设置串口。
2.3建立线程
在主线程中写数据,因为写是可以控制的,而读的时候不知道数据什么时候会到,所以要建立一个线程专门用来读线程。在这个线程中,循环地用ReadFile函数读串口,同时用WaitCommEvent函数检测线路状态。建立读线程需要用到的函数较多:ReadFile,如果要检测通信状态,如CTS信号,Ringln等等,则用SetCommMask,WaitCommEvent,ClearCommError。在SerialPor类中,监测线程函数为CommThread函数。在SerialPort::CommThread()函数中:首先利用PurgeComm函数清空缓冲区,调用通信事件监测函数。在监测事件时,如果异步操作不能立即完成,则该函数返回FALSE(0),并GetLastError函数返回ERROR—IO—PENDING,表明该操作在后台执行。发生这种情况时,系统在WaitCommEvent函数返回之前将OVERLAPPED结构中的成员hEvent参数值设置为无信号状态,之后等到特定通信事件或发生错误时,系统再将其设置为有信号状态。所以只要有字符到达,就会产生事件。当监测到是读事件的时候,就调用ReceiveChar函数去接收数据;当监测到是写事件的时候,就调用WriteChar函数就发送数据。调用EnterCriticalSection函数来获得串口的Critical Section,保证本进程中没有其他函数或线程使用本串口资源。用ReadFile函数读出缓冲区中的字节数,ReadFile(HANDLE nl—hcom,LPVOID RXBuff,DWORD dwlenth.LPDWORD&BytesRead,LPOVERLAPPED
mov);参数RXBuff指向接收缓冲区,dwlenth指明要从串口读取的字节数,在此设置为1,BytesRead指明实际从串口设备中读出的字节数,ITI—OV指向异步I/0结构。
2.4读写串口
使用ReadFile和WriteFile读写串口,在用ReadFile和WriteFile读写串口时,既可以同步执行,也可以重叠执行。在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费时的I/0操作在后台进行。ReadFile函数只要在串口输入缓冲区中读人指定数量的字符,就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲区,而且要等这些字符从串行口送出去后才算完成操作。
如果操作成功,这两个函数都返回TRUE。需要注意的是,当ReadFile和WriteFile返回FALSE时。不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR—IO—PENDING。
2.5关闭串口
调用ClosePort()函数来关闭串口。
3 、Linux平台下串口通信程序设计
3.1打开串口
在Linux下串口文件是位=J=/dev下,串口l为/dev/ttySO,串口2为/dev/ttySl,通过调用open()打开串口设备,返回一个整形文件句柄,以后所有的端口操作都针对这个句柄进行。如果open()出错,则返回.1。open()函数带有2个参数,其中参数1为要打开的设备文件名,参数2为打开方式。
3.2设置串口
进行串口操作之前,先要对串口通讯的波特率、校验位、输A/输出方式等参数进行设置。Linux下的串口设置实际上是根据POSIX规范来设置的。POSIX规范是由IEEE提出的,用于定义一系列可移植的操作系统接口。串口设置的所有参数都包含在Termios结构中。Linux提供了两个函数对termios进行操作,它们是tcgetattr()和tcsetattr()。tcgetattr()函数获得指定串口的设置情况,tesetattr()函数用来设置串口的参数。
3.3读写串口
串口配置完成后,把串口当作文件来读写。调用write()函数读写端口,返回实际读写的字节数,如果有错误发生则返回一1。在主线程中写数据,因为写是可以控制的,write
(fd,&WriteData,sizeof(WriteData));而读的时候不知道数据什么时候会到,所以要建立一个线程专门用来读数据,在这个线程中,循环地用Read读串口。在程序结束时关闭串口close(fd)。串口配置完成后,把串口当作文件来读写。调用read()函数读写端口,返回实际读写的字节数,如果有错误发生则返回一1。
3.4关闭串口
关闭串口就是关闭文件。使用close()关闭打开的串口,唯一的参数是打开串口的文件描述符。
4 、Windows和Linux串口通信的异同
4.1 Windows和Linux串口通信的相同点
Windows和Linux启动时均自动检测到标准的串口设备,而且对串口的打开、关闭、读取和写人所用的函数与操作文件的函数都是相同的。访问串口的几个简单步骤是:
(1)打开串口设备,获取Handle;
(2)设置串口通信参数(Windows是设置结构体DCB,Linux是设置结构体Termios),串口通信初始化设置,包括数据位、波特率、流量控制等参数;
(3)准备发送/接收数据;
(4)数据的发送/接收;
(5)关闭使用的串口设备。
此外,在Linux下有许多XWindows开发工具。
4.2 Windows和Linux串口通信的不同点
在Linux下实现串口通信编程和Windows环境不太一样:Linux的串口结合了很多终端特性(比如在,I,IY模式下会自动处理某些字符终端控制符),与Windows的方式有很大的差异。添加扩展的多口串行通信卡时,Windows则是通过控制面板添加新硬件来完成的,Linux下是通过在系统启动的配置脚本中配置/ete/serial.conf文件完成的。在打开串口时,Windows则需要提供串口的逻辑名,如COMl;Linux需要提供的是串口的路径及名称,且区分大小写,女fl/dev/ttySO。Linux支持NONE,EVEN,ODD和SPACE四种校验,而Windows除此之外还支持MASK。在Linux下,奇偶产生和检测(PARENB)及输入奇偶性检验(INPCK)是不同的两件事:奇偶位的产生和检测是对输出字符产生奇偶位;输入奇偶性检验则是对输入字符验证其奇偶性。Windows的停止位只有1位、1.5位和2位三种,Linux没有1.5位。Linux支持输入和输出的波特率不同,可以分开设置。在通过串口传输文件的时候要注意,Linux中的文件行结束符是换行符(ASCIll3),而在Windows下是回车换行符(ASCIIIO/ASCIll3)。
参考链接:http://d.g.wanfangdata.com.cn/Periodical_kxjsygc200903041.aspx