vc Win32 API实现串行通信Word文档下载推荐.docx
《vc Win32 API实现串行通信Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《vc Win32 API实现串行通信Word文档下载推荐.docx(15页珍藏版)》请在冰豆网上搜索。
WRITE,0,NULL,OPEN?
EXISTING,FILE?
ATTRIBUTE?
NORMAL,NULL))==INVALID?
HANDLE?
VALUE)
returnFALSE;
//设置超时控制
SetCommTimeouts(hComDev,&timeouts);
//设置接收缓冲区和输出缓冲区的大小
SetupComm(hComDev,1024,512);
//获取缺省的DCB结构的值
GetCommState(hComDev,&dcb);
//设定波特率为9600bps
dcb.BaudRate=CBR?
9600;
//设定无奇偶校验
dcb.fParity=NOPARITY;
//设定数据位为8
dcb.ByteSize=8;
//设定一个停止位
dcb.StopBits=ONESTOPBIT;
//监视串口的错误和接收到字符两种事件
SetCommMask(hComDev,EV?
ERR|EV?
RXCHAR);
//设置串行设备控制参数
SetCommState(hComDev,&dcb);
bOpen=TRUE;
//创建人工重设、未发信号的事件
hEvent=CreateEvent(NULL,FALSE,FALSE,
“WatchEvent”);
//创建一个事件监视线程来监视串口事件
AfxBeginThread(CommWatchProc,pParam);
}
在设置串口DCB结构的参数时,不必设置每一个值。
首先读出DCB缺省的参数设置,然后只修改必要的参数,其他参数都取缺省值。
由于对串口进行的是同步I/O操作,所以除非指定进行监测的事件发生,否则WaitCommEvent()函数不会返回。
在串行设备初始化的最后要建立一个单独的监视线程来监视串口事件,以免挂起当前调用线程,其中pParam可以是一个对事件进行处理的窗口类指针。
如果要进行异步I/O操作,打开设备句柄时,CreateFile的第6个参数应增加FILE?
FLAG?
OVERLAPPED标志。
数据发送
数据发送利用WriteFile()函数实现。
对于同步I/O操作,它的最后一个参数可为NULL;
而对异步I/O操作,它的最后一个参数必需是一个指向OVERLAPPED结构的指针,通过OVERLAPPED结构来获得当前的操作状态。
BOOLWriteComm(LPCVOIDlpSndBuffer,DWORDdwBytesToWrite)
{
//lpSndBuffer为发送数据缓冲区指针,
dwBytesToWrite为将要发送的字节长度
//设备已打开
BOOLbWriteState;
//实际发送的字节数
DWORDdwBytesWritten;
//设备未打开
if(!
bOpen)returnFALSE;
bWriteState=WriteFile(hComDev,lpSndBuffer,dwBytesToWrite,&dwBytesWritten,NULL);
bWriteState||dwBytesToWrite!
=dwBytesWritten)
//发送失败
returnFALSE;
else
//发送成功
returnTRUE;
}
数据接收
接收数据的任务由ReadFile函数完成。
该函数从串口接收缓冲区中读取数据,读取数据前,先用ClearCommError函数获得接收缓冲区中的字节数。
接收数据时,同步和异步读取的差别同发送数据是一样的。
DWORDReadComm(LPVOIDlpInBuffer,DWORDdwBytesToRead)
//lpInBuffer为接收数据的缓冲区指针,dwBytesToRead为准备读取的数据长度(字节数)
//串行设备状态结构
COMSTATComStat;
DWORDdwBytesRead,dwErrorFlags;
bOpen)return0;
//读取串行设备的当前状态
ClearCommError(hComDev,&dwErrorFlags,&ComStat);
//应该读取的数据长度
dwBytesRead=min(dwBytesToRead,ComStat.cbInQue);
if(dwBytesRead>
0)
//读取数据
if(!
ReadFile(hComDev,lpInBuffer,dwBytesRead,&dwBytesRead,NULL))
dwBytesRead=0;
returndwBytesRead;
事件监视线程
事件监视线程对串口事件进行监视,当监视的事件发生时,监视线程可将这个事件发送(SendMessage)或登记(PostMessage)到对事件进行处理的窗口类(由pParam指定)中。
UINTCommWatchProc(LPVOIDpParam)
DWORDdwEventMask=0;
//发生的事件;
while(bOpen)
{
//等待监视的事件发生
WaitCommEvent(hComDev,&dwEventMask,NULL);
if((dwEventMask&EV?
RXCHAR)==EV?
RXCHAR)
……//接收到字符事件后,可以将此消息登记到由pParam有指定的窗口类中进行处理
if(dwEventMask&EV?
ERR)==EV?
ERROR)
……//发生错误时的处理
}
SetEvent(hEvent);
//发信号,指示监视线程结束
return0;
关闭串行设备
在整个应用程序结束或不再使用串行设备时,应将串行设备关闭,包括取消事件监视,将设备打开标志bOpen置为FALSE以使事件监视线程结束,清除发送/接收缓冲区和关闭设备句柄。
voidCloseSynComm()
{
bOpen)return;
//结束事件监视线程
bOpen=FALSE;
SetCommMask(hComDev,0);
//取消事件监视,此时监视线程中的WaitCommEvent将返回
WaitForSingleObject(hEvent,INFINITE);
//等待监视线程结束
CloseHandle(hEvent);
//关闭事件句柄
//停止发送和接收数据,并清除发送和接收缓冲区
PurgeComm(hComDev,PURGE?
TXABORT|PURGE?
RXABORT|PURGE?
TXCLEAR|PURGE?
RXCLEAR);
//关闭设备句柄
CloseHandle(hComDev);
二、编程步骤
1、启动VisualC++6.0,生成一个基于对话框的的应用程序,将该程序命名为“SerealCom”;
2、按照图一的界面设计对话框,具体设置参见代码部分;
3、使用ClassWizard为对话框的按钮添加鼠标单击消息响应函数;
4、添加代码,编译运行程序。
三、程序代码
//////////////////////////////////////////////////////////////
#if!
defined(_COMM_ACCESS_FUNCTIONS_AND_DATA)
#define_COMM_ACCESS_FUNCTIONS_AND_DATA
#if_MSC_VER>
1000
#pragmaonce
#endif//_MSC_VER>
#defineEVENTCHAR0x0d
#defineMAXBLOCKLENGTH59
externBYTEXwCom;
externBYTEsCom1[5],sCom2[MAXBLOCKLENGTH+12];
externsCom3[MAXBLOCKLENGTH+12];
externBYTEopation;
externshortComNum;
#defineFC_DTRDSR0x01
#defineFC_RTSCTS0x02
#defineFC_XONXOFF0x04
#defineASCII_BEL0x07
#defineASCII_BS0x08
#defineASCII_LF0x0A
#defineASCII_CR0x0D
#defineASCII_XON0x11
#defineASCII_XOFF0x13
classCComStatus
public:
HANDLEm_hCom;
BYTEm_bComId;
BYTEm_bByteSize;
BYTEm_bStopBits;
BYTEm_bParity;
DWORDm_dwBaudRate;
//WORDm_fChEvt;
charm_bEvtChar;
DWORDm_fBinary;
BOOLm_bConnected;
BOOLm_fXonXoff;
BOOLm_bFlowCtrl;
OVERLAPPEDm_rdos;
OVERLAPPEDm_wtos;
//functions
CComStatus();
CComStatus(BYTEbComId,BYTEbByteSize,BYTEbStopBits,BYTEbParity,
DWORDdwBaudRate,/*WORDfChEvt,*/charbEvtChar,DWORDfBinary);
BOOLOpenConnection();
BOOLCloseConnection();
BOOLSetupConnection();
BOOLIsConnected();
};
UINTCommWatchProc(LPVOIDlpData);
BOOLWriteCommBlock(CComStatus&
comDev,LPSTRlpByte,DWORDdwBytesToWrite);
intReadCommBlock(CComStatus&
comDev,LPSTRlpszBlock,intnMaxLength);
intReadCommBlockEx(CComStatus&
comDev,LPSTRlpszBlock,intnMaxLength,DWORDdwTimeOut);
#endif
///////////////////////////////////////////////////////////////////////
#include"
stdafx.h"
com232.h"
BYTEXwCom=0x40;
BYTEsCom1[5],sCom2[MAXBLOCKLENGTH+12],sCom3[MAXBLOCKLENGTH+12];
BYTEopation;
shortComNum;
CComStatus:
:
CComStatus()
m_hCom=NULL;
m_bComId=(char)ComNum;
//COM1
m_bByteSize=8;
m_bStopBits=ONESTOPBIT;
m_bParity=NOPARITY;
m_dwBaudRate=9600;
m_bEvtChar=EVENTCHAR;
m_fBinary=1;
m_bConnected=FALSE;
m_bFlowCtrl=FC_XONXOFF;
m_fXonXoff=FALSE;
CComStatus(BYTEbComId,BYTEbByteSize,BYTEbStopBits,BYTEbParity,DWORDdwBaudRate,/*WORDfChEvt,*/charbEvtChar,DWORDfBinary)
m_bComId=bComId;
m_bByteSize=bByteSize;
m_bStopBits=bStopBits;
m_bParity=bParity;
m_dwBaudRate=dwBaudRate;
m_bEvtChar=bEvtChar;
m_fBinary=fBinary;
BOOLCComStatus:
OpenConnection()
charcsCom[10];
COMMTIMEOUTSCommTimeOuts;
if((m_bComId<
0)||(m_bComId>
4))
//从COM1到COM4
if(m_hCom)//ifalreadyopen
//OVERLAPPED包含异步I/O信息
m_rdos.Offset=0;
m_rdos.OffsetHigh=0;
m_rdos.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(m_rdos.hEvent==NULL)
m_wtos.Offset=0;
m_wtos.OffsetHigh=0;
m_wtos.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(m_wtos.hEvent==NULL)
CloseHandle(m_rdos.hEvent);
}
wsprintf(csCom,"
COM%d"
m_bComId);
m_hCom=CreateFile(csCom,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,ILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL);
if(m_hCom==INVALID_HANDLE_VALUE){
//dwError=GetLastError();
//handleerror
else
SetCommMask(m_hCom,EV_RXCHAR);
//getanyearlynotifications
SetupComm(m_hCom,4096,4096);
//setupdevicebuffers
//purgeanyinformationinthebuffer
PurgeComm(m_hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
//setupforoverlappedI/O
DWORDdwTemp=1000/(this->
m_dwBaudRate/8);
CommTimeOuts.ReadIntervalTimeout=0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier=0;
//((dwTemp>
0)?
dwTemp:
1);
CommTimeOuts.ReadTotalTimeoutConstant=1000;
//CBR_9600isapproximately1byte/ms.Forourpurposes,allow
//doubletheexpectedtimepercharacterforafudgefactor.
CommTimeOuts.WriteTotalTimeoutMultiplier=2*CBR_9600/this->
m_dwBaudRate;
//(npTTYInfo);
CommTimeOuts.WriteTotalTimeoutConstant=0;
//1000;
SetCommTimeouts(m_hCom,&
CommTimeOuts);
SetupConnection())
CloseConnection();
EscapeCommFunction(m_hCom,SETDTR);
m_bConnected=TRUE;
returnTRUE;
CloseConnection()
if(NULL==m_hCom)
return(TRUE);
//setconnectedflagtoFALSE
//disableeventnotificationandwaitforthread
//tohalt
SetCommMask(m_hCom,0);
EscapeCommFunction(m_hCom,CLRDTR);
//purgeanyoutstandingreads/writesandclosedevicehandle
PurgeComm(m_hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
CloseHandle(m_hCom);
//changetheselectableitemsinthemenu
CloseHandle(m_rdos.hEvent);
CloseHandle(m_wtos.hEvent);
return(TRUE);
SetupConnection()
BOOLfRetVal;
BYTEbSet;
DCBdcb;
if(m_hCom==NULL)
dcb.DCBlength=sizeof(DCB);
GetCommState(m_hCom,&
dcb);
dcb.BaudRate=this->
dcb.ByteSize=this->
m_bByteSize;
dcb.Parity=this->
m_bParity;
dcb.StopBits=this->
m_bStopBits;
dcb.EvtChar=this->
m_bEvtChar;
//setuphardwareflowcontrol
bSet=(BYTE)((m_bFlowCtrl&
FC_DTRDSR)!
=0);
dcb.fOutxDsrFlow=bSet;
if(bSet)
dcb.fDtrControl=DTR_CONTROL_HANDSHAKE;
dcb.fDtrControl=DTR_CONTROL_ENABLE;
FC_RTSCTS)!
dcb.fOutxCtsFlow=bSet;