VC++串口编程之基于Win32 API文档格式.docx
- 文档编号:18121886
- 上传时间:2022-12-13
- 格式:DOCX
- 页数:15
- 大小:71.11KB
VC++串口编程之基于Win32 API文档格式.docx
《VC++串口编程之基于Win32 API文档格式.docx》由会员分享,可在线阅读,更多相关《VC++串口编程之基于Win32 API文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。
如果进行I/O操作的API在没有完成操作的情况下返回,我们可以通过调用GetOverLappedResult()函数阻塞到I/O操作完成后返回。
配置串口
配置串口是通过改变设备控制块DCB(DeviceControlBlock)的成员变量值来实现的,接收缓冲区和发送缓冲区的大小可通过SetupComm函数来设置。
DCB结构体定义为:
typedefstruct_DCB{//dcb
DWORDDCBlength;
//sizeof(DCB)
DWORDBaudRate;
//currentbaudrate
DWORDfBinary:
1;
//binarymode,noEOFcheck
DWORDfParity:
//enableparitychecking
DWORDfOutxCtsFlow:
1;
//CTSoutputflowcontrol
DWORDfOutxDsrFlow:
//DSRoutputflowcontrol
DWORDfDtrControl:
2;
//DTRflowcontroltype
DWORDfDsrSensitivity:
//DSRsensitivity
DWORDfTXContinueOnXoff:
//XOFFcontinuesTx
DWORDfOutX:
//XON/XOFFoutflowcontrol
DWORDfInX:
//XON/XOFFinflowcontrol
DWORDfErrorChar:
//enableerrorreplacement
DWORDfNull:
//enablenullstripping
DWORDfRtsControl:
//RTSflowcontrol
DWORDfAbortOnError:
//abortreads/writesonerror
DWORDfDummy2:
17;
//reserved
WORDwReserved;
//notcurrentlyused
WORDXonLim;
//transmitXONthreshold
WORDXoffLim;
//transmitXOFFthreshold
BYTEByteSize;
//numberofbits/byte,4-8
BYTEParity;
//0-4=no,odd,even,mark,space
BYTEStopBits;
//0,1,2=1,1.5,2
charXonChar;
//TxandRxXONcharacter
charXoffChar;
//TxandRxXOFFcharacter
charErrorChar;
//errorreplacementcharacter
charEofChar;
//endofinputcharacter
charEvtChar;
//receivedeventcharacter
WORDwReserved1;
//reserved;
donotuse
}DCB;
而SetupComm函数的原型则为:
BOOLSetupComm(
HANDLEhFile,//handletocommunicationsdevice
DWORDdwInQueue,//sizeofinputbuffer
DWORDdwOutQueue//sizeofoutputbuffer
以下程序将串口设置为:
波特率为9600,数据位数为7位,停止位为2位,偶校验,接收缓冲区和发送缓冲区大小均为1024个字节,最后用PurgeComm函数终止所有的后台读写操作并清空接收缓冲区和发送缓冲区:
DCBdcb;
dcb.BaudRate=9600;
//波特率为9600
dcb.ByteSize=7;
//数据位数为7位
dcb.Parity=EVENPARITY;
//偶校验
dcb.StopBits=2;
//两个停止位
dcb.fBinary=TRUE;
dcb.fParity=TRUE;
if(!
SetCommState(hCom,&
dcb))
MessageBox("
串口设置出错!
"
}
SetupComm(hCom,1024,1024);
PurgeComm(hCom,PURCE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
超时设置
超时设置是通过改变COMMTIMEOUTS结构体的成员变量值来实现的,COMMTIMEOUTS的原型为:
typedefstruct_COMMTIMEOUTS
DWORDReadIntervalTimeout;
//定义两个字符到达的最大时间间隔,单位:
毫秒
//当读取完一个字符后,超过了ReadIntervalTimeout,仍未读取到下一个字符,就会
//发生超时
DWORDReadTotalTimeoutMultiplier;
DWORDReadTotalTimeoutConstant;
//其中各时间所满足的关系如下:
//ReadTotalTimeout=ReadTotalTimeOutMultiplier*BytesToRead+ReadTotalTimeoutConstant
DWORDWriteTotalTimeoutMultiplier;
DWORDWriteTotalTimeoutConstant;
}COMMTIMEOUTS,*LPCOMMTIMEOUTS;
设置超时的函数为SetCommTimeouts,其原型中接收COMMTIMEOUTS的指针为参数:
BOOLSetCommTimeouts(
LPCOMMTIMEOUTSlpCommTimeouts//pointertocommtime-outstructure
以下程序将串口读操作的超时设定为10毫秒:
COMMTIMEOUTSto;
memset(&
to,0,sizeof(to));
to.ReadIntervalTimeout=10;
SetCommTimeouts(hCom,&
to);
与SetCommTimeouts对应的GetCommTimeouts()函数的原型为:
BOOLGetCommTimeouts(
HANDLEhFile,//handleofcommunicationsdevice
事件设置
在读写串口之前,需要用SetCommMask()函数设置事件掩模来监视指定通信端口上的事件,其原型为:
BOOLSetCommMask(
HANDLEhFile,//标识通信端口的句柄
DWORDdwEvtMask//能够使能的通信事件
有了Set当然还会有Get,与SetCommMask对应的GetCommMask()函数的原型为:
BOOLGetCommMask(
LPDWORDlpEvtMask//addressofvariabletogeteventmask
串口上可以发生的事件可以是如下事件列表中的一个或任意组合:
EV_BREAK、EV_CTS、EV_DSR、EV_ERR、EV_RING、EV_RLSD、EV_RXCHAR、EV_RXFLAG、EV_TXEMPTY。
我们可以用WaitCommEvent()函数来等待串口上我们利用SetCommMask()函数设置的事件:
BOOLWaitCommEvent(
LPDWORDlpEvtMask,//addressofvariableforeventthatoccurred
LPOVERLAPPEDlpOverlapped,//addressofoverlappedstructure
WaitCommEvent()函数一直阻塞,直到串口上发生我们用所SetCommMask()函数设置的通信事件为止。
一般而言,当WaitCommEvent()返回时,程序员可以由分析*lpEvtMask而获得发生事件的类别,再进行相应的处理。
读串口
对串口进行读取所用的函数和对文件进行读取所用的函数相同,读函数原型如下:
BOOLReadFile(
HANDLEhFile,//handleoffiletoread
LPVOIDlpBuffer,//pointertobufferthatreceivesdata
DWORDnNumberOfBytesToRead,//numberofbytestoread
LPDWORDlpNumberOfBytesRead,//pointertonumberofbytesread
LPOVERLAPPEDlpOverlapped//pointertostructureforoverlappedI/O
写串口
对串口进行写入所用的函数和对文件进行写入所用的函数相同,写函数原型如下:
BOOLWriteFile(
HANDLEhFile,//handletofiletowriteto
LPCVOIDlpBuffer,//pointertodatatowritetofile
DWORDnNumberOfBytesToWrite,//numberofbytestowrite
LPDWORDlpNumberOfBytesWritten,//pointertonumberofbyteswritten
关闭串口
利用API函数实现串口通信时关闭串口非常简单,只需使用CreateFile函数返回的句柄作为参数调用CloseHandle即可:
BOOLCloseHandle(
HANDLEhObject//handletoobjecttoclose
2.例程
在笔者的《深入浅出Win32多线程程序设计之综合实例》中我们已经给出一个利用WINAPI进行串口通信的例子,这里再给出一个类似的例子,以进一步加深理解。
对话框上控件对应的资源文件(.RC)中的内容如下:
BEGIN
EDITTEXTIDC_RECV_EDIT,28,119,256,46,ES_AUTOHSCROLL
GROUPBOX"
发送数据"
IDC_STATIC,19,15,282,70
接收数据"
IDC_STATIC,19,100,282,80
EDITTEXTIDC_SEND_EDIT,29,33,214,39,ES_AUTOHSCROLL
PUSHBUTTON"
清除"
IDC_CLEAR_BUTTON,248,33,50,14
发送"
IDC_SEND_BUTTON,248,55,50,14
END
而整个对话框的消息映射(描述了消息及其对应的行为)如下:
BEGIN_MESSAGE_MAP(CSerialPortAPIDlg,CDialog)
//{{AFX_MSG_MAP(CSerialPortAPIDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_CLEAR_BUTTON,OnClearButton)
ON_BN_CLICKED(IDC_SEND_BUTTON,OnSendButton)
ON_MESSAGE(COM_RECVDATA,OnRecvData)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
我们为IDC_SEND_EDIT和IDC_RECV_EDIT编辑框控件分别添加了一个CString变量m_recv和m_send,下面的代码描述了这一行为:
classCSerialPortAPIDlg:
publicCDialog
//Construction
public:
CSerialPortAPIDlg(CWnd*pParent=NULL);
//standardconstructor
//DialogData
//{{AFX_DATA(CSerialPortAPIDlg)
enum{IDD=IDD_SERIALPORTAPI_DIALOG};
CStringm_recv;
//IDC_RECV_EDIT控件对应的变量
CStringm_send;
//IDC_SEND_EDIT控件对应的变量
//}}AFX_DATA
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CSerialPortAPIDlg)
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);
//DDX/DDVsupport
//}}AFX_VIRTUAL
//Implementation
BOOLOpenSerialPort1();
HICONm_hIcon;
//Generatedmessagemapfunctions
//{{AFX_MSG(CSerialPortAPIDlg)
virtualBOOLOnInitDialog();
afx_msgvoidOnSysCommand(UINTnID,LPARAMlParam);
afx_msgvoidOnPaint();
afx_msgHCURSOROnQueryDragIcon();
afx_msgvoidOnClearButton();
afx_msgvoidOnSendButton();
afx_msgvoidOnRecvData(WPARAMwParam,LPARAMlParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CSerialPortAPIDlg:
:
CSerialPortAPIDlg(CWnd*pParent/*=NULL*/)
CDialog(CSerialPortAPIDlg:
IDD,pParent)
//{{AFX_DATA_INIT(CSerialPortAPIDlg)
//在构造函数中初始化变量
m_recv=_T("
//在构造函数中初始化变量
m_send=_T("
//}}AFX_DATA_INIT
//NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32
m_hIcon=AfxGetApp()->
LoadIcon(IDR_MAINFRAME);
//建立编辑框控件和变量之间的映射
voidCSerialPortAPIDlg:
DoDataExchange(CDataExchange*pDX)
CDialog:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSerialPortAPIDlg)
DDX_Text(pDX,IDC_RECV_EDIT,m_recv);
DDX_Text(pDX,IDC_SEND_EDIT,m_send);
//}}AFX_DATA_MAP
在对话框的OnInitDialog()函数中,我们启动窗口监听线程并将主窗口句柄传递给线程控制函数:
BOOLCSerialPortAPIDlg:
OnInitDialog()
OnInitDialog();
//Add"
About..."
menuitemtosystemmenu.
//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&
0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<
0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->
AppendMenu(MF_SEPARATOR);
AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'
smainwindowisnotadialog
SetIcon(m_hIcon,TRUE);
//Setbigicon
SetIcon(m_hIcon,FALSE);
//Setsmallicon
//TODO:
Addextrainitializationhere
//启动串口监视线程
DWORDthreadID;
hCommThread=:
CreateThread((LPSECURITY_ATTRIBUTES)NULL,0,
(LPTHREAD_START_ROUTINE)SerialPort1ThreadProcess,
AfxGetMainWnd()->
m_hWnd,0,&
threadID);
if(hCommThread==NULL)
:
AfxMessageBox("
创建串口1处理线程失败"
PostQuitMessage(0);
returnTRUE;
//returnTRUEunlessyousetthefocustoacontrol
//"
按钮函数
OnClearButton()
Addyourcontrolnotificationhandlercodehere
m_send="
;
UpdateData(false);
//发送数据函数("
按钮函数)
OnSendButton()
UpdateData(true);
DWORDwCount=0;
WriteFile(hCom,m_send,m_send.GetLength(),&
wCount
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VC+串口编程之基于Win32 API VC 串口 编程 基于 Win32