1、第 1 页 共 8 页串口基本信息用一台电脑实验串口自发自收,实验前要将串口(以 9 针为例)的发送引脚(2 脚)和接受引脚(3脚)短接。三线连接:适用于计算机之间尤其是 PC 机和单片机之间的数据通信。其连接信号对为( TxD,RxD) 、(RxD,TxD) 、 (SG,SG ) 。即发送数据 TxD 端和接受数据 RxD 端交叉连接,信号地 SG 对应连接。七线交叉连接:适用于同型号的计算机之间的连接,如 PC 机间的数据通信。其连接信号对为:(TxD,RxD) 、 (RxD,TxD) 、 (SG,SG) 、 (RTS,CTS ) 、 ( CTS,RTS) 、 (DSR.DTR) 、 (D
2、TR,DSR ) 。其中,TxD、RxD、SG 与前面信号的含义相同,RTS 为请求发送,CTS 为准许发送,DSR 为数据装置准备好,DTR 为数据终端准备好。在本地连接的微机系统中,RTS 、CTS 、DTR、DSR 用作硬件联络控制信号。目前使用的串口连接线有 DB9 和 DB25 两种连接器,用户可以国家使用的具体机器选择相应的连接器。一个串口通讯类在 http:/ 机的 RS-232 接口的电平标准是-12V 标示“1” ,和+12V 表示“0” ,有些单片机的信号电平时TTL 型,即大于 2.4v 表示“1” ,小于 0.5v 表示“0” ,因此采用 RS-232 总线进行异步通信
3、是,发送端和接受端要有一个电平转换接口。串口通讯方法的三种实现串口是计算机上一种非常通用的设备通信协议。大多数计算机包含两个基于的串口。串口同时也是仪器仪表设备通用的通信协议;很多兼容的设备也带有一口。同时,串口通信协议也可以用于获取远程采集设备的数据。串口通信(Serial Communication) ,是指外设和计算机间,通过数据信号线、地线、控制线等,按位进行传输数据的一种通讯方式。串口通信方便易行,应用广泛。在 Windows 应用程序的开发中,我们常常需要面临与外围数据源设备通信的问题。计算机和单片机(如 MSC51)都具有串行通信口,可以设计相应的串通信程序,完成二者之间的数据通
4、信任务。串口通讯原理串口通信的原理非常简单,串口按位(bit)发送和接收字节。尽管比按字节( byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如 IEEE488 定义并行通行状态时,规定设备线总常不得超过米,并且任意两个设备间的长度不得超过米;而对于串口而言,长度可达米。典型地,串口用于 ASCII 码字符的传输。通信使用根线完成:()地线, ()发送, ()接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其它线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对
5、于两个进行通信的端口,这些参数必须匹配。串口通讯实现在.net 平台下使用 C#语言实现串口通信的方法主要有三种:第一种方法是采用 VB6.0 中提供的控件,这种方法编程简单但 MSComm 控件在使用前需要在系统中注册;第二种方法是采用微软在.net2.0 及其以后版本提供的内置的串口操作类System.IO.SerialPort,使用简单,但欠灵活;第三种方法是 Windows 的 API 函数,虽然编程难度高,但这种方法可以清楚地掌握串口通信的机制,并且高效、自由、灵活。无论那种采用方式实现串口通讯,都需要通过以下四个步骤来完成:)打开串口MSComm 控件是通过设置 PortOpen
6、属性值来打开和关闭串口具体语法为:MSComm. PortOpenTrue/False.SerialPort 类则是调用类的 Open()和 Close()方法来实现串口的打开和关闭。函数是通过来打开串口因为在系统中,串口被看作一个文件,使用与文件相同的操作方式进行操作。第 2 页 共 8 页)配置串口在打开通讯设备句柄后,需要对串口进行一些初始化配置工作。串口通讯最常用的参数就是通讯端口号及通讯格式(波特率、数据位、停止位和校验位) 。在 MSComm 中,通过属性 Comport 和 Settings 来进行端口号和通讯格式设置,例如:MSComm1.Comport,设定通讯端口为 Com
7、1,MSComm1.Settings”9600,n,8,1” ,设置波特率,无校验,位数据位,位停止位。SerialPort 类是通过 PortName 属性获取或设置通信端口,并分别通过BaudRate、Parity、DataBits、StopBits 属性来对通讯格式中的波特率、数据位、停止位和校验位进行设置,其中的 Parity 和 StopBits 属性都是枚举类型,Parity 类型中枚举了 Odd(奇) 、Even(偶) 、Mark、None、Space 共个枚举成员StopBits 类型中枚举了、共个枚举成员。使用,则需要通过一个 DCB 结构(包含了诸如波特率、数据位数、奇偶校
8、验和停止位数等信息)来进行,将串口的几个重要参数如波特率、数据位、停止位、校验位改成符合实际设计要求的值。)读写串口设置工作完成后,对串口进行读写操作。MSComm 控件通过 Input 属性返回和删除接收缓冲区中的字符,通过 Output 属性将字符串写入发送缓冲区。SerialPort 类则是通过调用重载的 Write 和 WriteLine 方法发送数据,其中 WriteLine 可发送字符串并在字符串末尾加入换行符。SerialPort 类对于串口缓冲区的读取方法有许多,其中除了 ReadExisting 和 Readto之外,其余的方法都是同步调用,即,方法调用时,线程将被阻塞,直到
9、缓冲区有相应的数据或读超时(大于ReadTimeOut 属性设定的时间值后,引发 ReadExisting 异常) 。API 函数是分别通过 ReadFile 和 Writefile 对串口进行读写操作。)关闭串口串口是非共享资源,某应用程序打开串行口后,即独占该资源,使其它应用程序无法再访问,直到该应用程序释放串口。所以对串口操作完成后,一定要关闭串口。MSComm 控件通过将 PortOpen 属性值设置为 False 来关闭串口。SerialPort 类则是调用 Close()方法来关闭串口。API 函数是通过使用 CloseHandle()来关闭串口,该函数唯一参数即为用 Create
10、File 打开串口时所创建的句柄。结束语在.NET 平台下,通过 SerialPort 类可以实现与 MSComm 控件相同的串口通讯程序,比起复杂的API,SerialPort 类使用方便,开发快速在今后工业控制中SerialPort 类必将广泛地应用于串口通讯程序的设计中。MSComm 控件串行端口的本质功能是作为和串行设备间的编码转换器。在发送数据时,字节数据转换为串行的位。在接收数据时,串行的位被转换为字节数据。利用微机口进行串行通信的一般步骤如下:()打开串口在位中,串口和其他通信设备都被作为文件进行处理,在使用前必须先将其打开。()配置串口串口配置主要包括波特率、数据位数、停止位数
11、、奇偶校验、发送缓冲区大小、接收缓冲区大小等。()超时设置在串口通信时如果数据传输突然中断,对串口的读写操作可能会进入无限期的等待状态,为避免这种情况发生,必须设置串口读写操作的等待时间。若等待时间超过后,第 3 页 共 8 页串口的读写操作将被主动放弃。()数据读写对串口的读写操作可采用查询、同步、异步和事件驱动等方式。()关闭串口在串口使用完后应将其关闭,否则其他应用程序就无法打开或使用它。VS2003 下要先注册 mscomm32.ocx 组件才能使用。在 光盘下面有目录 ,此目录中有一个包含所有 控件授权信息的注册表文件:。我们通过将中的控件注册信息添加到注册表中,从而注册这些控件。如
12、果机器上已经安装过 就不用上述步骤了常用控件属性Vc+.net 中控件 Mscomm32 的主要属性有:CommPort 属性,设置返回通信端口号;Settings 属性,设置返回波特率、奇偶校验、数据位和停止位参数;PortOpen 属性,设置返回通信端口的状态(开或关) 。InBuffercount 属性,返回接受缓冲区中等待的字符数,也可以用他来清除输入缓冲区。InBufferSize 属性,设置并返回接受缓冲区的字节数。Input 属性,返回并删除接收缓冲区中的数据流。OutBufferCount 属性,返回在传输缓冲区中等待的字符数。也可以用它来清除输出缓冲区。OutBufferSi
13、ze 属性,以字节的形式设置并返回传输缓冲区的大小。Output 属性,将数据写入发送缓冲区Rthrehold 属性,设置并返回 Rthrehold 数值;InputMode 属性,设置返回 Input 属性所检取数据的类型;CommEvent 属性,返回最近的通信事件或错误通信方式的选择Mscomm32 控件提供了两种处理通信问题的方法:事件驱动法和查询法。事件驱动法利用 OnComm 事件捕获并处理通信中发生的事件,实时性强,可靠性高。每当有新字符到达,或端口状态改变,或发生错误时,Mscomm 控件将触发 OnComm 事件,应用程序在捕获该事件后,通过检查 Mscomm 控件的 Com
14、mEvent 属性可获知所发生的事件(包括错误)并采取相应的操作。查询法适合于应用程序较小、实时性要求不是很高的系统。在这种情况下,每当应用程序执行完某一串口操作后,将不断检查 Mscomm 控件的 CommEvent 属性以检查执行结果或者检查某一事件是否发生基于 API 的串行口通信软件设计串行口的硬件使用 3 线结构,即: RXD ,TXD 和 GND, 在开发 PC 上位机的通信程序中常用的编程语言可分为 3 类: 1) 直接面向底层硬件系统的汇编语言; 2) DOS 环境下的高级编程语言如 C 语言; 3) Windows 环境下的高级编程语言,如 Visual C+ + 6. 0,
15、 而这 3 种方式中 Windows 环境下的串口编程以其设备无关性、可移植性以及界面友好而得到广泛应用, 开发 Windows 环境下的通信程序,主要有以下两种方式:1) 利用 Windows API ( Application Program Interface 用户程序接口 ) 函数2) 利用 ActiveX 控件, MSComm 控件对于简单的串行口操作 MSComm 控件使用方便、控制简单,但是对于较为复杂的串行口操作,它不够灵活,它常用在对话框中,这也限制了它的使用。基于 API 的串口编程,其功能强大,控制手段更为灵活 配合 Win32 的重叠 I/O 操作和多线程设计 就可以编
16、写出高效、灵活的通信程序,串口的打开与初始化第 4 页 共 8 页串口的打开是通过 Win32 的文件操作函数 CreateFile 完成的, 该函数的原型如下,Handle CreateFile (LPCTSTR lpFileName /指向文件名称DWORD dwDeSiredAcceSS /存取模式 ( 读或写) DWORD dwShareMode /共享模式LPSECURITY_ATTRIBUTES lpSecurityAttributeS /指向安全属性结构DWORD dwCreationDiSpoSition /创建方式DWORD dwFlagSAndAttributeS /文件属
17、性和标志Handle hTemplateFile /临时文件句柄通常为 NULL)如果调用成功, 则该函数返回文件的句柄, 否则, 返回 INVALID_HANDLE_VALUE, 注意在打开一个通信端口的时候, 应该以独占方式打开, 即 dwShareMode 应该为 O, 另外, 应该指定存取模式为 GENERIC_READ|GENERIC_WRITE, 允 许 对 端 口 读 和 写, 因 为 串 口 是 存 在 的, 所 以,dwCreationDisposition 应该为 OPEN_EXISTING, 此外, 应该指定 FILE_ATTRIBUTE_NORMAL 属性, 如果要打开
18、重叠 I/O, 则应该指定 FILE_FLAG_OVERLAPPED 属性, 这里, 重叠 I/O 的概念很重要。在使用 ReadFile 和 WriteFile 读写串口的时候, 既可以使用同步方式 , 也可以使用异步 ( 重叠) 方式, 使用同步方式的时候, 函数直到操作完成后才返回, 这就意味着在执行同步方式时 , 线程将被阻塞, 导致效率下降, 如果通信出现错误, 将导致系统挂起的危险出现, 而使用重叠方式的时候, 费时的 I/O 操作在后台进行, 主线程则完成别的事情而不用担心效率会降低 , 而 ReadFile 和 WriteFile 是否执 行 重 叠 I/O 操 作 则 是 由
19、 CreateFile 决 定 的, CreateFile 中 如 果 指 定 了 FILE_FLAG_OVERLAPPEDA 标志, 那么执行重叠操作, 否则执行同步操作, 比如, 要用重叠方式打开 COM1, 则应该这样使用 CreateFile 函数。HANDLE M_hCOm = CreateFile (OPEN_EXISTING,”COM1”,FILE_ATTRIBUTE_NORMAL |FILE_GENERIC_READ|generic_write,flag_overlapped,0,null,null,); 当 通 信 设 备 的 句 柄 创 建 成 功 后, 接 下 来 就 要
20、 完 成 串 行 口 的 初 始 化 操 作 了, 初 始 化 是 通 过 DCB( Device Control Block) 结构和 COMMTIMEOUTS 结构来实现的, 此外还利用 SetupComm 函数设置输入与接收缓冲区大小等。DCB 结构包含了波特率、数据位、奇偶校验位、停止位、文本方式或二进制方式等信息。 串口打开后, 调用 GetCommState 函数可以获取串口当前的配置 , 修改完 DCB 结构后, 调用 SetCommState 函数, 用新的 DCB 设置重新配置串口, 比如, 设置波特率位 56 OOO, 8 位数据位, 无校验, 1 位停止位,二进制方式。i
21、f ( m_hCOmm = = NULL ) return;DCB dcb;GetCOmmState (m_hComm, dcb. BaudRate= 56OOO;dcb. ByteSize= DATABITS_8;dcb. Parity= FALSE;dcb. StopBits= ONESTOPBIT;dcb. fBinary= TRUE;SetCommState ( m_hComm, 在用 ReadFile 和 WriteFile 读写串口时, 还需要考虑超时问题 , 如果在指定的时间内没有读出或写入指定数量的字符, 那么 ReadFile 和 WriteFile 将立即返回。调用 Get
22、COmmTimeOuts 可以获取当前的超 时 设 置, 该 函 数 将 填 充 一 个 COMMTIMEOUTS 结 构, 调 用 SetCommTimeouts 可 以 用 某 个 COMMTIMEOUTS 结构来设置超时, 该结构定义如下, typedef struct COMMTIMEOUTS DWORD ReadIntervalTimeOut ; /读间隔超时DWORD ReadTOtalTimeOutMultiplier; 读时间系数DWORD ReadTOtalTimeOutCOnstant; 读时间常量DWORD WriteTOtalTimeOutMultiplier; 写时间
23、系数第 5 页 共 8 页DWORD WriteTOtalTimeOutCOnstant 写时间常量 COMMTIMEOUTS, e LPCOMMTIMEOUTS;有两种超时, 间隔超时和总超时, 他们之间的设置是不相关的, 写操作只支持总超时, 读操作两种超时都支持, 间隔超时是指接收时两个字符之间的最大延迟时间, 总超时是指读/ 写操作总共花费的最大时间, COMMTIMEOUTS 结构的所有成员都是以毫秒为单位 , 总超时的计算公式为总超时= 读/ 写时间系数 要求读/ 写的字符数 + 读/ 写时间常量如果超时为 O, 那么就不用该超时 , 比如读间隔超时为 O, 则不用读间隔超时, 如
24、果所有写操作参数均为 O, 则不用写超时。如果读间隔超时为 MAXDWORD, 且读总超时为 O, 那么在读一次缓冲区中的内容后读操作就立即完成, 而不管是否读入了要求的字符数。除了 DCB 设置和超时设置外, 还需要设定 I/O 缓冲区的大小 , Windows 用 I/O 缓冲区来暂存串口输入和输出的数据, 如果通信速率较高, 则应该设置较大的缓冲区大小, 调用 SetupComm 函数可以设置串口输入和输出缓冲区的大小。自此, 串行口打开并且完成了初始化, 通信管道已建立起来, 可以对端口进行读写操作串口的读写操作串口的读写是通过 Readfile 和 Writefile 来实现的, 这
25、两个函数的参数几乎是一样的, 这里只列出Readf ile 的原型。BOOL Readfile (HANDLE hfile, 文件句柄LPVOID lpBuffer, 数据缓冲区DWORD nNumberOfByteSToRead, 要求读入的字节数LPDWORD lpNumberofByteSRead, 实际读入的字节数LPOVERLAPPED lpoverlapped 指向一个 OVERLAPPED 结构) ;注 意 这 里 的 lpoverlapped 指 针, 在重叠操作 时 应 该 指 向 一个 OVERLAPPED 结 构, 如 果 为 NULL, 那么函数将进行同步操作, 而不管
26、句柄是否由 FILE_FLAG_OVERLAPPED 标志建立。在使用重叠操作时, 需要建立一个 OVERLAPPED 结构, 而 OVERLAPPED 结构最重要的成员是hEvent, 它是一个事件对象句柄, 它将作为线程的同步对象使用。这里提出了线程的概念。 在很多工业控制系统中, 常常通过扩展串口连接多个外设, 各外设发送数据的频率不同, 这就要求后台要实时无差错捕捉、采集、处理和记录各端口数据, 从而需要创建串口监视线程, 以实时监控串口事件的发生, 并且通知相应的窗口进行处理。Win32 区分两种不同类型的线程, 一种是用户界面 ( UI, USer Interface) 线程, 它
27、包含消息循环或消息泵, 用于处理接收到的消息 ; 另一种是工作者 ( Worker) 线程, 它没有消息循环, 用于执行后台任务。 串口监视线程就属于工作者线程。工作者线程的创建可以通过 AfxBeginThread 实现, 其声明为:CWinThreade * AfxBeginThread ( AFX_THREADPROC pfnThreadProc, / / 指向工作者线程的函数的指针LPVOID pParam, / / 传递给线程函数的参数int nPriority = THREAD_PRIORITY_NORMAL, / / 线程优先级UINT nStackSize = 0, / / 线
28、程堆栈尺寸DWORD dwCreateflags =0 / / 线程初始状态, 为 0 则创建后立即执行, 为create_suspended则创建后被挂起, 知道调用 ResumeThread 才开始运行LPSECURITY_ATTRIBUTES lpSecurityAttrS = NULL /线程保密性) ;线程函数的声明必须如下,UINT MyControllingFunction ( LPVOID pParam );其中 pParam 是创建线程时的第 2 个参数, 如下例, 传递的参数为指向 CECLView 的 this 指针;void CECLView:CreateCommRec
29、eiveThread () CWinThread * m_pReadCommThread;m_pReadCommThread=AfxBeginThread(ReadcommThreadProc,this,THREAD_PRIORITY_NOMAL,第 6 页 共 8 页0,CREATE_SUSPENDED,NULL);m_pReadCommThread-:ResumeThread();UNIT ReadcommThreadProc(LPVOID pPrarm) CECLView *pView=(CECLView *)pParam;Return 0;多线程的使用会带来一些问题, 主要是如何保证线
30、程之间的协调运行, 从而提出了同步对象。 同步对象主要有事件、 mutex 和信号灯 3 种。 事件对象是最简单的同步对象 , 它包括有信号和无信号两种状态。 事件对象是用 CreateEvent 创建的。该函数可以指定事件对象的类型和初始状态。如果是手工重置, 则它总是保持有信号状态, 直到用 ResetEvent 函数重置成无信号的事件; 如果是自动重置, 则它的状态在单个等待线程释放后会自动变为无信号的。 用 SetEvent 可以把事件对象设置成有信号状态。串口监视线程需要等待主线程完成串口数据的读取后才能运行, 此时, 该线程需要暂时挂起, 以减少对 CPU 的占用时间, 提高程序的
31、执行效率。 当主线程完成了串口数据的读取后 , 将同步事件对象置为有信号, 从而激活串口监视线程监测串口事件的发生, 保证串口监视线程与主线程之间的同步, 避免错误的发生。在读取串口数据的时候, 使用了 ReadFile, 该函数的返回值是 BOOL 值。 若该函数返回 TRUE, 则表示操作成功。 但是, 需要注意 , 该函数因为超时也将返回 TRUE。 另外, 如果返回值为 FALSE, 也不表示操作就失败了, 应该调用 GetLastError 函数分析返回的结果。 如果 GetLastError 返回 ERROR_IO_PENDING, 则说明重叠操作还未完成 , 需要等待操作结束,
32、目前有两种等待方法。Win32 API 提供了一组能使线程阻塞其自身执行的等待函数。这些函数只有在作为其参数的一个或多个同步对象产生信号时才返回。 在超过规定的等待时间后, 函数将立即返回, 而不管有无信号。 在等 待函数未返回时, 线程处于等待状态 , 此时线程只消耗很少的 CPU 时间。 最常 用 的 等 待 函 数 是WaitForSingleObject,其声明为:DWORD WaitForSingleObject(HANDLE hHandle, /同步对象句柄DWORD dwMilliseconds /超时间隔,单位为微妙。) 。如果超时间隔为 0, 则该函数立即返回, 如果为 IN
33、FINITE, 则超时间隔无限。该函数返回值如表1所示。用GetOverlappedResult函数等待。如果指定该函数的bWait参数为True ,那么该函数将等待OVERLAPPED结构的hEvent 事件。GetOverlappedResult可以返回一个OVERLAPPED结构来报告包括实际传输字节在内的重叠操作作结果。在调用 ReadFile 和 WriteFile 之前, 线程应该调用 ClearCommError 函数清除错误标志。该函数负责报告指定的错误和设备的当前状态。调用 PurgeComm 函数可以终止正在进行的读写操作, 该函数还会清除输入或输出缓冲区中的内容。第 7
34、页 共 8 页API 和 MSComm32 的应用比较性能两者均可使用码或二进制形式的数据。但是如果使用的是 MSComm32 控件,无论是在PC 机读取上传数据时还是在机发送下行命令时,都只能使用数据类型。所以不论是码还是二进制,发送前都要转换一下。如果下位机是单片机,则在单片机的程序中不需要做其他额外的转换。使用函数则不需要做这种转换。扩展在使用函数进行串口通讯时,常常用一个类为每一个申口添加一个控件。MSComm32 控件的源码是不公开的,所有的修改必须在它的外面,以至于代码的重用性比较差。编程复杂性从上面的这两个例子可以看出,用函数编写通讯程序,涉及的函数比较多,一次代码编写比较复杂,
35、而 MSComm32 控件则比较简单。而且 MSComm32 控件的文档说明详细,在中文版中,还可以找到中文的使用帮助。控件的可靠性很高,调试时完全可以不考虑这一部分的错误的可能,这又能节省一部分时间。所以在开发周期上,MSComm32 控件远胜过 API 函数。至今为止,使用函数编写通讯类的实际工作也做的比较多,已经出现了一些功能强大的共享类,这就使我们不需要重头做起,降低了首次编写时的难度, 。比如 http:/ 中的一个串口通讯类就值得参考。移植性API 函数是各种 windows 编程工具所共同支持的,但是各种语言可能有不同的表示方法,所以,API串口通讯类只可用在其他的平台上,如 C
36、+ Builder。如果是在中开发程序,并用到了某些中已经包装过的类或数据,则不能直接在其他编程环境下运行。API 函数编出来的类是源代码级的共享,而控件是基于二进制代码级的共享,所以可以在,Dephi, C+ Builder 中使用此控件,但是具体的实现代码则需要有所更改。需要注意的是,因为不能确保每一台计算机上都有 MSComm32 控件,所以在使用前要注意有个注册的过程。这个工作可以在应用程序中做,也可以在用于应用程序发布的安装程序中做。两者均可以使用文本或二进制数据。MSComm32 控件能满足比较基本的需要,而且上手比较快,调试起来也方便。使用函数缩写的类自己扩展的余地大,比较灵活,
37、容易添加一些特定的功能。我们认为,如果注重的是开发周期,请选用控件来进行串行通讯,如果注重的是功能强大,或有特殊来封装所有功能。一般说来,这个类除了初始化串需要,请使用函数。CSerialPot 串口类的使用CSerialPort 串口类可以很方便地实现上位机和仪表的串口通讯,串口类可从 Remon Spekreijse 免费得到。该类是基于多线程的,其接收数据工作流程如下:首先初始化串口,再开启串口监测工作线程,当串口监测工作线程监测到串口接收到的数据、流控制事件或其他串口事件后,就以消息方式通知主程序,激发消息处理函数进行数据处理。数据可直接向串口发送。实现串口通信的过程中,要用到几个成员
38、函数。InitPort():初始化串口,即设置串口的通信参数:串口号、波特率、校验方式、数据位、停止位等。StartMonitoring():启动串口检测线程。WriteToPort()函数:向串口发送字符。ClosePort(): 关闭串口。CSerialPort 串口类在数据采集过程中的使用方法如下:()串口类的引用先将串口类的头文件 SerialPort.h 和源文件 SerialPort.cpp 复制到所建工程的文件夹中,在环境下,通过菜单 Project/Add To Project/files 选中两文件加入到工程中。 CMainFrame.h 中引入了SerialPort.h 并
39、定义了公共 CSerialPort 类对象 m_serialport.()串口的初始化本系统对串口的初始设置为:端口为,波特率为 9600,数据位为,无数据校验位;停止位为,接受缓冲区为字节。第 8 页 共 8 页If(m_serialport.InitPort(this,1,9600,N,8,2,EV_RXFLAG|EV_RXCHAR,512)/串口初始化/启动串口检测线程M_serialport.StartMonitoring();Settime(1,200,null); ElseMessagebox(“没有发现此串口或串口已被占用”,”注意”,);()添加串口事件响应函数在 CSeria
40、lPort 类中有多个串口事件可以响应,所有的消息均需要人工添加消息处理函数,在一般串口编程中,只需处理 WM_COMM_RXCHA 消息就可以了。此处将处理函数定义为() 。LONG CMainFrame:ONComm(WPARAM ch,LPARAM port)/将接受的字符赋给 Public 型 m_recedate 变量m_recedata+=cn;return 0; ()向串口发迭字符系统用定时器方法以为周期向串口发送读数据的命令,实现对温度的实时采集:首先建立定时器 SetTime(1,200,null),定时器用按周期触发的 Ontime(UINT nIDEvent)函数中的_s
41、erialport 调用 WriteToPort().SerialPort 类提供了同步 /和事件驱动的 I/O、对管脚和中断状态的访问以及对串行驱动程序属性的访问。SerialPort 类的常用属性和常用方法如表所示。利用表中的属性和方法,实现智能化汽车衡系统中上位机与下位机的数据传输。利用 MicorSoft.NetFramework 2.0 中的 SerialPort 类,实现汽车衡称重系统上位机与下位机串口通信接收功能的主要程序如下:Private void SerialPort1_dataReceived(object sender,System.IO.Ports.serialdat
42、areceivedEventArgs e)If(flag=false)/flag 初始值为 false,用于标示是否处理数据值if(this.serialport1.readbyte()=0x0a)/判断受到询问信号0Athis.serialport1.wire(0x0B,0,1);flag=!flag)/回复确认信号0bElse if(flag)system.threading.thread.sleep(100);/线程中断 100 毫秒This.serialport1.read(rec_barray,0,4)/读取缓冲区数据Rec_barray_data=crcdata(rec_barra
43、y,2)/对接受 crc 编码解码Temp=convert.todouble(rec_barray_data0*256+rec_barray_data1);/按规约处理数据Rec_dou=temp/100;/单位转换Rec_strarray=convert.tostring(rec_dou);Flag=!flag;Settext(rec_strarray/显示数据。)每当上位机串口缓冲区收到新数据时,即触发此函数。为了提高汽车衡称重系统串口通信的抗干扰能力和降低误码率,上位机与下位机通信采用了编码技术,并设计了一种握手协议,即对于每 32bit 数据,由下位机向上位机发送数据传输询问信号,上位机接收到 信号后,向下位机发送 确认信号。下位机接收到0后传输 2bit 数据信息,上位机将数据按约定规则处理后显示。若下位机没有受到0 确认信号,下位机将持续向上位机发送询问信号,上位机数据信息保持不变,避免因干扰而产生数据大幅振荡。若此状态超过s,系统将弹出串口通信异常警告对话框。实验表明,采用这种方法后,数据通信误差由实施前的0.05%降低到0.01%