引言 在现代工业监测和控制领域中,正确对前端设备进行 监控在整个生产过程中起着十分重要的作用 本研究在 VC++环境下,采用WindowsAPI函数研究开发了现场温 度实时监控系统,通过RS485接口在上位机端完成温度控 制器现场数据的实时采集,同时将采集到的数据存储在 Excel中,以方便查询和后续处理 ![]() 1 串口通信模块 串口通信作为计算机与外部设备之间常用的通信方 法之一,在工业控制领域 数据采集和实时监控系统中得 到广泛应用 目前,在Windows环境下实现串行通信主要 有以下两种方式: (1)采用MSComm串行通信控件 这种方 法在编程时非常方便,其优点在于使用者不必花费大量时 间去了解复杂的 API函数,但控件占用的资源多,灵活性 差; (2)调用WindowsAPI函数 由于 API函数具有比较强 的通信功能,可以与多线程技术和自定义消息机制的异步 串口通信相结合,能提高串口通信的效率和程序的灵活 性 所以,本系统采用API函数编写串口通信程序,需要建 立串口通信类CCommPort,在主对话框中调用类的对象来 完成数据的接收处理和存储任务 1.1 打开串口 Win32系统使用CreateFile()函数来打开串口 打开 串口的通信方式有两种:一种是同步方式;另一种是异 步方式 在同步方式下, API函数会阻塞直到操作完成 后才能返回;而在异步方式下, API函数会立即返回,操 作在后台进行,避免线程阻塞,故采用异步方式打开 为了使用异步I/O方式打开串口,在打开串口时,必须 指定文件的属性为FILE_FLAG_OVERLAPPED[1] : HANDLEm_hComm; //定义端口句柄 m_hComm=CreateFile("Coml", GENERIC_READ| GENERIC_WRITE, 0, NULL, OPEN_EXISTING,FILE_ ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL); if(m_hComm==INVALID_HANDLE_VALUE|| m_hComm==NULL) { m_hComm=NULL; returnFALSE; } return TRUE; 2 配置串口 在打开通讯设备句柄后,常需要对串口进行一些初 始化配置工作 这需要通过一个DCB结构来进行 DCB 结构包含了诸如波特率 数据位数 奇偶校验和停止位数 等信息 一般用CreateFile打开串口后,可以调用Get- CommState(m_hComm, &dcb)读取当前串口设备控制块 DCB设置,要修改串口的配置,应该首先修改DCB结构, 然后再通过SetCommState(m_hComm, &dcb)将其写入[2] 在用ReadFile和WriteFile函数读写串口时,需要考 虑超时问题 进行异步读写超时控制设置时,通过 COMMMTIMEOUTS结构设置超时,再用 SetCommTime- outs(m_hComm, &stComTimeOuts)将结果写入 本程序中 对COMMMTIMEOUTS配置的代码如下: COMMTIMEOUTSstComTimeOuts; stComTimeOuts.ReadIntervalTimeout=0; stComTimeOuts.ReadTotalTimeoutMultiplier=0; stComTimeOuts.ReadTotalTimeoutConstant=20; stComTimeOuts.WriteTotalTimeoutMultiplier=0; stComTimeOuts.WriteTotalTimeoutConstant=20; SetCommTimeouts(m_hComm,&stComTimeOuts); 1.3 读写串口 本程序采用ReadFile()函数和WriteFile()函数读写串 口值,如果操作成功,这两个函数都返回TRUE 需要注 意的是,当 ReadFile和 WriteFile的返回值为 FALSE 时, 不一定就是操作失败,线程应该调用 GetLastError()函数 分析返回的结果 例如,在异步I/O方式时如果操作还未 完成函数就返回,那么函数就返回 FALSE,而且当 Get- LastError 函数返回 ERROR_IO_PENDING,这说明读写 操作还未完成,即操作转入后台继续运行[2] 有两种方法 可以等待操作完成:一种方法是用 WaitForSingleObject 等待函数来等待 OVERLAPPED结构的 hEvent成员;另 一种方法是调用GetOverlappedResult函数等待 主要代 码如下: charlpInBuffer[1024]; DWORDdwBytesRead=1024; B0OLbReadStat; OVERLAPPEDm_osRead; bReadStat=ReadFile(m_hComm, lpInBuffer, dwBytes- Read, &dwBytesRead, &m_osRead); if(!bReadStat)//如果ReadFile函数返回FALSE { if(GetLastError()==ERROR_IO_PENDING) { GetOverlappedResult(m_hComm,&m_osRead,&dw- BytesRead,TRUE);//GetOverlappedResult函数的最后一个 参数设为TRUE,函数会一直等待,直到读操作完成或由 于错误而返回 return((int)dwBytesRead); } |