基于WIN32API的串口调试助手.docx
- 文档编号:6893842
- 上传时间:2023-01-12
- 格式:DOCX
- 页数:14
- 大小:19.60KB
基于WIN32API的串口调试助手.docx
《基于WIN32API的串口调试助手.docx》由会员分享,可在线阅读,更多相关《基于WIN32API的串口调试助手.docx(14页珍藏版)》请在冰豆网上搜索。
基于WIN32API的串口调试助手
基于WIN32API的串口通讯软件的设计收藏
串口调试助手源代码:
1、串口的应用
随着计算机技术的发展及工业自动化水平的提高,在许多场合采用单机控制已不能满足现场要求,因而必须采用多机控制的形式。
串行通信作为计算机之间常用的通信方法之一,由于其通信编程灵活、硬件简洁并遵循统一的标准,而在工业控制领域得到了广泛的应用。
2、串口的属性
2.1波特率
波特率即数据传送速率,表示每秒钟传送二进制代码的位数,他的单位是bit/s。
波特率对于CPU与外界的通信是很重要的。
通讯过程中,必须保证上位机和下位机的波特率一致。
如果不一致的话,就有可能出现乱码甚至出现丢包。
这个就好如一个蓄水池的进水管道和出水管道,如果进水管道流入水的速度太快而出水管道的出水太慢,这样时间长了水就会溢出,反映在串口通讯上就是丢包。
2.2数据帧
在异步通信中,数据是一帧一帧(包括一个字符或一个字节数据)传送的,每一帧数据的格式如下表所示。
起始位
数据位
奇偶校验位
停止位
0
5-8位
可省
1
在帧格式中,一个字符由四个部分组成:
起始位、数据位、奇偶校验位和停止位。
首先是一个起始位(0),然后是5-8位数据(规定低位在前,高位在后),接下来是奇偶校验位(可省略),最后是停止位
(1)。
起始位(0)信号只占用一位,用来通知设备一个待接收的数据准备到达。
线路上在不传送字符时应保持为1。
接收端不断检测线路的状态,若连续为以后又测得一个0,就知道后来一个新字符,应该马上接收。
字符的起始位还被用作同步接收端的时钟,以保证以后的接收能正确进行。
奇偶校验位只占一位,但在字符中也可以规定不用奇偶校验位,这一位可以省去。
也可以用这一位来确定这一帧中的字符所代表信息的性质(地址数据等)。
停止位用来表示数据的结束,它一定四高电位
(1)。
停止位可以是1位、1.5位或2位。
接收端收到停止位后,知道上一字符已传送完毕,同时为准备接收下字符作好准备。
只要接收到0,就是新的字符的起始位。
若停止位以后不是紧接着传送下一个字符,则使电路电平保持高电平
(1)。
存在空闲位,正是异步通信的特征之一。
2.3通讯协议
要想保证通讯成功,通讯双方必须有一系列的约定。
作为发送方,必须知道应该什么时候发送,发什么,对方是否接收到,收到的内容有没有错,要不要重发,怎样通知对方结束等等;作为接收方,必须知道对方是否发送了信息,发的是什么,收到的信息有没有错,如果有错,怎样通知对方重发。
这种约定就叫做通信规程或协议,它必须在编程之前确定下来。
然后双方必须严格按照预先规定的协议,进行通讯。
比如通讯的起始头、地址位、数据长度、数据段、数据校验位、结束尾等。
数据校验算法有CRC算法、异或算法。
代码如下:
1./*
2.将16进制的字符转化为对应的十进制整数
3.*/
4.HRESULTCCrc:
:
strHexToInt(BYTEbyRecv,int&nData)
5.{
6.nData=0;
7.
8.if(byRecv>=48&&byRecv<=57)
9.{
10.nData=byRecv-48;
11.}
12.elseif(byRecv>=65&&byRecv<=70)
13.{
14.nData=byRecv-55;
15.}
16.else
17.{
18.return-1;
19.}
20.returnS_OK;
21.}
22./*
23.对字符串所对应的ASCII码进行CRC校验
24.*/
25.HRESULTCCrc:
:
CRCCheck(BYTEucChar[],intcommandLength,intnCRCData)
26.{
27.WORDchCRC=0XFFFF;//初始化CRC校验
28.for(inti=3;i 29.{ 30.chCRC=chCRC^ucChar[i]; 31.for(intbits=0;bits<8;bits++) 32.{ 33.if(chCRC&0X0001) 34.{ 35.chCRC=chCRC>>1; 36.chCRC=chCRC^nCRCData; 37.} 38.else 39.chCRC=chCRC>>1; 40.} 41.} 42.WORDCRC,CRC2;//原校验码 43.CRC2=chCRC>>8; 44.CRC2+=chCRC<<8; 45.CRC=ucChar[commandLength-3]; 46.CRC=CRC<<8; 47.CRC=CRC+ucChar[commandLength-2]; 48.if(CRC==CRC2) 49.returnS_OK; 50.else 51.return-1; 52.} 3串口通讯例程序 有了上面的基础知识,我们来开发一个类似串口调试助手的小工具,以便对于WIN32API的有一个直观认识,现在让我们开始我们的旅程吧! 打开串口,串口在WINDOWS32位操作系统下也被认识是一种文件资源,但是这个文件资源不允许共享。 代码如下: 1.BOOLCSerialPort: : OpenComm(CStringstrComm) 2.{ 3.if(m_hComm==NULL) 4.{ 5.m_hComm=CreateFile((char*)(LPCSTR)strComm,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING, 6.FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,0); 7.if(m_hComm==INVALID_HANDLE_VALUE) 8.{ 9.intnError=GetLastError(); 10.m_hComm=NULL; 11.AfxMessageBox("打开串口失败! "); 12.returnFALSE; 13.} 14.} 15.returnTRUE; 16.} 设置串口的属性,包括波特率、帧格式、超时属性等,代码如下: 1.BOOLCSerialPort: : SetCommState(DWORDdwBaudrate,BYTEbyParity,BYTEbyByteSize,BYTEbyStopBits) 2.{ 3.DCBdcbOld; 4.intret=: : GetCommState(m_hComm,&dcbOld); 5.if(ret==0) 6.{ 7.CloseHandle(m_hComm); 8.m_hComm=NULL; 9.returnFALSE; 10.} 11.dcbOld.BaudRate=dwBaudrate; 12.dcbOld.ByteSize=byByteSize; 13.dcbOld.Parity=byParity; 14.dcbOld.StopBits=byStopBits; 15.ret=: : SetCommState(m_hComm,&dcbOld); 16.if(ret==0) 17.{ 18.CloseHandle(m_hComm); 19.m_hComm=NULL; 20.returnFALSE; 21.} 22.returnTRUE; 23.} 设置缓冲大小,代码如下: 1.BOOLCSerialPort: : SetupComm(DWORDdwInQueue,DWORDdwOutQueue) 2.{ 3.return: : SetupComm(m_hComm,dwInQueue,dwOutQueue); 4.} 清楚错误状态后,设置监视事件,代码如下: 1.BOOLCSerialPort: : PurgeComm(DWORDdwFlags) 2.{ 3.return: : PurgeComm(m_hComm,dwFlags); 4.} 5. 6.BOOLCSerialPort: : SetCommMask(DWORDdwEvtMask) 7.{ 8.return: : SetCommMask(m_hComm,dwEvtMask); 9.} 串口设置完后,可以进行读写操作了,代码如下: 1.BOOLCSerialPort: : WriteFile(LPCVOIDlpBuffer,DWORDnNumberOfBytesToWrite,LPDWORDlpNumberOfBytesWritten,LPOVERLAPPEDlpOverlapped) 2.{ 3.return: : WriteFile(m_hComm,lpBuffer,nNumberOfBytesToWrite,lpNumberOfBytesWritten,lpOverlapped); 4.} 5. 6.BOOLCSerialPort: : ReadFile(LPVOIDlpBuffer,DWORDnNumberOfBytesToRead,LPDWORDlpNumberOfBytesRead,LPOVERLAPPEDlpOverlapped) 7.{ 8.return: : ReadFile(m_hComm,lpBuffer,nNumberOfBytesToRead,lpNumberOfBytesRead,lpOverlapped); 9.} 总体的调用代码如下: 1.//打开串口,并设置属性 2.voidCCommDemoDlg: : OnBnClickedBtnCommcontrol() 3.{ 4.CButton*pBtnCommControl=(CButton*)GetDlgItem(IDC_BTN_COMMCONTROL); 5.if(! m_bIsOpen) 6.{ 7.CComboBox*pComboComm=(CComboBox*)GetDlgItem(IDC_COMBO_COMM); 8.intnSel=pComboComm->GetCurSel(); 9.CStringstrComm; 10.pComboComm->GetLBText(nSel,strComm); 11.m_bIsOpen=m_serialPort.OpenComm(strComm); 12.if(m_bIsOpen) 13.{ 14.pBtnCommControl->SetWindowText("关闭串口"); 15.CComboBox*pComboBaudrate=(CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE); 16.intnSel=pComboBaudrate->GetCurSel(); 17.DWORDdwBaudrate=pComboBaudrate->GetItemData(nSel); 18. 19.CComboBox*pComboCheckbit=(CComboBox*)GetDlgItem(IDC_COMBO_CHECKBIT); 20.nSel=pComboCheckbit->GetCurSel(); 21.BYTEbyParity=(BYTE)pComboCheckbit->GetItemData(nSel); 22. 23.CComboBox*pComboDatabit=(CComboBox*)GetDlgItem(IDC_COMBO_DATABIT); 24.nSel=pComboDatabit->GetCurSel(); 25.BYTEbyDataSize=(BYTE)pComboDatabit->GetItemData(nSel); 26. 27.CComboBox*pComboStopbit=(CComboBox*)GetDlgItem(IDC_COMBO_STOPBIT); 28.nSel=pComboStopbit->GetCurSel(); 29.BYTEbyStopBits=(BYTE)pComboStopbit->GetItemData(nSel); 30. 31.BOOLbRet=m_serialPort.SetCommState(dwBaudrate,byParity,byDataSize,byStopBits); 32.if(! bRet) 33.{ 34.m_serialPort.CloseComm(); 35.AfxMessageBox("设置COMM属性出错! "); 36.return; 37.} 38. 39.bRet=m_serialPort.SetupComm(1024,1024); 40.if(! bRet) 41.{ 42.m_serialPort.CloseComm(); 43.AfxMessageBox("设置COMM输入输出缓冲区出错! "); 44.return; 45.} 46. 47.bRet=m_serialPort.PurgeComm(PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); 48.if(! bRet) 49.{ 50.m_serialPort.CloseComm(); 51.AfxMessageBox("无法清除COMM的错误状态! "); 52.return; 53.} 54. 55.bRet=m_serialPort.SetCommMask(EV_RXCHAR); 56.if(! bRet) 57.{ 58.m_serialPort.CloseComm(); 59.AfxMessageBox("设置COMM的事件出错! "); 60.return; 61.} 62.} 63.else 64.{ 65.pBtnCommControl->SetWindowText("打开串口"); 66. 67.} 68.} 69.else 70.{ 71.m_bIsOpen=FALSE; 72.AfxMessageBox("已经有一个串口正在运行中,请关闭该串口! "); 73.m_serialPort.CloseComm(); 74.pBtnCommControl->SetWindowText("打开串口"); 75.} 76.} 77. 78.//发送数据 79.voidCCommDemoDlg: : OnBnClickedBtnSend() 80.{ 81.if(m_serialPort.m_hComm==NULL) 82.{ 83.AfxMessageBox("请打开串口后发送数据! "); 84.return; 85.} 86.CEdit*pEditSend=(CEdit*)GetDlgItem(IDC_EDIT_SEND); 87.CEdit*pEditRecv=(CEdit*)GetDlgItem(IDC_EDIT_RECV); 88.DWORDdwWrite=0; 89.CStringstrSend,strRecv; 90.pEditSend->GetWindowText(strSend); 91.if(strSend.IsEmpty()) 92.{ 93.return; 94.} 95.OVERLAPPEDm_OverlappedWrite; 96.ZeroMemory(&m_OverlappedWrite,sizeof(OVERLAPPED)); 97.m_OverlappedWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); 98.m_serialPort.WriteFile((LPVOID)strSend.GetBuffer(strSend.GetLength()+1),strSend.GetLength()+1,&dwWrite,&m_OverlappedWrite); 99.pEditSend->SetWindowText(""); 100.pEditRecv->GetWindowText(strRecv); 101.strRecv+=strSend; 102.pEditRecv->SetWindowText(strRecv); 103.Sleep(10); 104.} 105. 106.//读线程 107.UINTCThreadSvr: : ReadProc(LPVOIDlpParameter) 108.{ 109.Sleep(100); 110.CThreadSvr*pThreadSvr=(CThreadSvr*)lpParameter; 111.intnLength=0; 112.while(! pThreadSvr->bMainThreadExit) 113.{ 114.Sleep(100); 115.EnterCriticalSection(&pThreadSvr->cs); 116.CCommDemoDlg*pCommDemoDlg=(CCommDemoDlg*)AfxGetApp()->m_pMainWnd; 117.if(pCommDemoDlg==NULL) 118.{ 119.continue;//对话框还没有创建成功,须等待其创建成功。 120.} 121.if(pCommDemoDlg->m_serialPort.m_hComm==NULL) 122.{ 123.continue; 124.} 125. 126.COMSTATcomStat; 127.DWORDdwError=0; 128.BOOLret=TRUE; 129.DWORDdwRead=0; 130.charrecvTemp[512]; 131.ZeroMemory(recvTemp,512); 132.charrecvBuf[4096]; 133.ZeroMemory(recvBuf,4096); 134. 135.pCommDemoDlg->m_serialPort.ClearCommError(&dwError,&comStat); 136.if(comStat.cbInQue>0) 137.{ 138.if(comStat.cbInQue<512) 139.{ 140.ret=pCommDemoDlg->m_serialPort.ReadFile(recvTemp,comStat.cbInQue,&dwRead,&pThreadSvr->m_OverlappedRead); 141.} 142.else 143.{ 144.ret=pCommDemoDlg->m_serialPort.ReadFile(recvTemp,500,&dwRead,&pThreadSvr->m_OverlappedRead); 145.} 146.if(comStat.cbInQue>=dwRead) 147.{ 148.memcpy(recvBuf+nLength,recvTemp,dwRead); 149.nLength+=dwRead; 150.} 151.if(comStat.cbInQue>=dwRead) 152.{ 153.nLength=0; 154.CEdit*pEditRecv=(CEdit*)pCommDemoDlg->GetDlgItem(IDC_EDIT_RECV); 155.CStringstrRecv; 156.pEditRecv->GetWindowText(strRecv); 157.strRecv+=recvBuf; 158.pEditRecv->SetWindowText(strRecv); 159.} 160.if(! ret) 161.{ 162.if(ERROR_IO_PENDING==GetLastError()) 163.{ 164.while(! ret) 165.{ 166.ret=pCommDemoDlg->m_serialPort.GetOverlappedResult(&pThreadSvr->m_OverlappedRead,&dwRead,TRUE); 167.if(GetLastError()! =ERROR_IO_INCOMPLETE) 168.{ 169.pCommDemoDlg->m_serialPort.ClearCommError(&dwError,&comStat); 170.break; 171.} 172.} 173.} 174.} 175.} 176.LeaveCriticalSection(&pThreadSvr->cs); 177.} 178.returnTRUE; 179.} 最后调试助手的效果如下: 本文来自CSDN博客,转载请标明出处:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 WIN32API 串口 调试 助手