MFC 串口通讯程序
来源:互联网 发布:淘宝定制是要付全款吗 编辑:程序博客网 时间:2024/04/29 21:17
用惯了C#、VB、Java之类东西制作桌面程序,虽然以前自学过VC,却用的极少,基本不知道VC是怎么设计程序的。近期一个项目需要制作一个串口转TCP/IP的功能,决定使用MFC。本文的串口操作类参考的网上源码,特在此感谢同行的付出。
一、建立项目
在VS2012里,新建项目,选择其他语言、Visual C++、MFC,
1.名称填入SerialTest,确定。
应用程序类型选择 :基于对话框
高级功能全不选。
2、设置Unicode
在项目上右键选择属性-配置属性-常规-项目默认值
字符集改为未设置。
二、绘制界面:
主要放置端口combobox、打开/关闭串口按钮,其它还有一些设置项,这里不一一列举。
三、编写程序
从网上查询得知,一般串口通讯有两种方法,一种基于Active控件,一种基于Win32API。本次测试使用API。
1。遍历串口:
void CSerialTestDlg::FindAllCom(){HKEY hKey; int i=0;TCHAR portName[256],commName[256]; DWORD dwLong,dwSize;int rtn = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Hardware\\DeviceMap\\SerialComm",NULL, KEY_READ, &hKey);//打开串口注册表if( rtn == ERROR_SUCCESS) {while(TRUE) {dwLong = dwSize=sizeof(portName); memset(portName, 0, sizeof(portName));memset(commName, 0, sizeof(commName));rtn = RegEnumValue( hKey, i, portName, &dwLong,NULL, NULL, (PUCHAR)commName, &dwSize );if( rtn == ERROR_NO_MORE_ITEMS ) // 枚举串口 break;m_combo_com_list.AddString(commName);i++; } if(m_combo_com_list.GetCount()==0){//没有找到串口}RegCloseKey(hKey); } }
2.打开/关闭串口
//关闭串口virtual void Close(){if(IsOpen()){PurgeComm(_hCommHandle,PURGE_TXABORT | PURGE_TXCLEAR);EndThread();::CloseHandle(_hCommHandle);_hCommHandle = INVALID_HANDLE_VALUE;}} //打开串口bool Open(DWORD dwPort,DWORD dwBaudRate){if(dwPort<1 || dwPort >1024) return false;BindCommPort(dwPort);if(!OpenCommPort()) return false;if(!SetupPort()) return false;return SetState(dwBaudRate);}
3.参数设置
//设置串口参数 DCBbool SetState(DCB *pdcb = NULL){return IsOpen() ? ::SetCommState(_hCommHandle, pdcb == NULL ? &_DCB:pdcb) == TRUE: false;}//设置串口参数:波特率,停止位,等 支持设置字符串 "9600, 8, n, 1"bool SetState(char *szSetStr){if (IsOpen()){if (::GetCommState(_hCommHandle, &_DCB) != TRUE)return false;if (::BuildCommDCB(szSetStr, &_DCB) != TRUE)return false;return ::SetCommState(_hCommHandle, &_DCB) == TRUE;}return false;}//设置串口参数:波特率,停止位,等bool SetState(DWORD dwBaudRate, DWORD dwByteSize = 8, DWORD dwParity =NOPARITY, DWORD dwStopBits = ONESTOPBIT){if (IsOpen()){if (::GetCommState(_hCommHandle, &_DCB) != TRUE)return false;_DCB.BaudRate = dwBaudRate;_DCB.ByteSize = (unsigned char)dwByteSize;_DCB.Parity = (unsigned char)dwParity;_DCB.StopBits = (unsigned char)dwStopBits;return ::SetCommState(_hCommHandle, &_DCB) == TRUE;}return false;}
4.绑定端口
//绑定端口void BindCommPort(DWORD dwPort){assert(dwPort >=1 && dwPort <=1024);char p[5];_dwPort=dwPort;strcpy_s(_szCommStr,"\\\\.\\COM");_ltoa_s(_dwPort,p,10); //转字符串strcat_s(_szCommStr,p); //组合\\.\COM1 类似字符串}
5.读写
//读取串口 dwBufferLength个字符到 Buffer 返回实际读到的字符数 可读任意数据DWORD Read(LPVOID Buffer, DWORD dwBufferLength, DWORD dwWaitTime = 10){if (!IsOpen()) return 0;COMSTAT Stat;DWORD dwError;if (::ClearCommError(_hCommHandle, &dwError, &Stat) && dwError > 0){::PurgeComm(_hCommHandle,PURGE_RXABORT | PURGE_RXCLEAR);return 0;}if (!Stat.cbInQue) return 0; // 缓冲区无数据unsigned long uReadLength = 0;dwBufferLength = dwBufferLength > Stat.cbInQue ? Stat.cbInQue :dwBufferLength;if (!::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength,&_ReadOverlapped)){if (::GetLastError() == ERROR_IO_PENDING){WaitForSingleObject(_ReadOverlapped.hEvent, dwWaitTime);// 结束异步I/Oif (!::GetOverlappedResult(_hCommHandle, &_ReadOverlapped,&uReadLength, false)){if (::GetLastError() != ERROR_IO_INCOMPLETE) uReadLength = 0;}}elseuReadLength = 0;}return uReadLength;}//读取串口 dwBufferLength - 1 个字符到 szBuffer 返回ANSI C 模式字符串指针 适合一般字符通讯char *ReadString(char *szBuffer, DWORD dwBufferLength, DWORD dwWaitTime =20){unsigned long uReadLength = Read(szBuffer, dwBufferLength - 1,dwWaitTime);szBuffer[uReadLength] = '\0';return szBuffer;}//写串口 可写任意数据 "abcd" or "\x0\x1\x2"DWORD Write(LPVOID Buffer, DWORD dwBufferLength){if (!IsOpen())return 0;DWORD dwError;if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);unsigned long uWriteLength = 0;if (!::WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength,&_WriteOverlapped))if (::GetLastError() != ERROR_IO_PENDING)uWriteLength = 0;return uWriteLength;}//写串口 写ANSI C 模式字符串指针 DWORD Write(const char *szBuffer){assert(szBuffer);return Write((void*)szBuffer, strlen(szBuffer));}//读串口 同步应用DWORD ReadSync(LPVOID Buffer, DWORD dwBufferLength){if (!IsOpen())return 0;DWORD dwError;if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0){::PurgeComm(_hCommHandle,PURGE_RXABORT | PURGE_RXCLEAR);return 0;}DWORD uReadLength = 0;::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, NULL);return uReadLength;}//写串口 同步应用DWORD WriteSync(LPVOID Buffer, DWORD dwBufferLength){if (!IsOpen())return 0;DWORD dwError;if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);unsigned long uWriteLength = 0;::WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength, NULL);return uWriteLength;}//写串口 szBuffer 可以输出格式字符串 包含缓冲区长度DWORD Write(char *szBuffer, DWORD dwBufferLength, char *szFormat, ...){if (!IsOpen())return 0;va_list va;va_start(va, szFormat);//_vsnprintf(szBuffer, dwBufferLength, szFormat, va);_vsnprintf_s(szBuffer,dwBufferLength,_TRUNCATE,szFormat,va);va_end(va);return Write(szBuffer);}//写串口 szBuffer 可以输出格式字符串 不检查缓冲区长度 小心溢出DWORD Write(char *szBuffer, char *szFormat, ...){if (!IsOpen()) return 0;va_list va;va_start(va, szFormat);//vsprintf(szBuffer, szFormat, va);int len = _vscprintf( szFormat, szBuffer ) // _vscprintf doesn't count + 1; // terminating '\0'//char * buffer =(char*) malloc( len * sizeof(char) );vsprintf_s(szBuffer,len, szFormat,va);va_end(va);return Write(szBuffer);}
四、DCB结构
typedef struct _DCB{ DWORD DCBlength;DWORD BaudRate; //波特率DWORD fBinary :1; DWORD fParity :1; //是否奇偶校验DWORD fOutxCtsFlow :1; // CTS output flow control 指定CTS是否用于检测发送控制。当为TRUE时CTS为OFF,发送将被挂起。(发送清除)DWORD fOutxDsrFlow :1; // DSR output flow control 指定DSR是否用于检测发送控制。(数据装备好) 当为TRUE是DSR为OFF,发送将被挂起。DWORD fDtrControl :2; // DTR flow control type //DTR_CONTROL_DISABLE值将DTR置为OFF, //DTR_CONTROL_ENABLE值将DTR置为ON, //DTR_CONTROL_HANDSHAKE 允许DTR"握手",DWORD fDsrSensitivity :1; //若为TRUE,通讯驱动程序对DSR信号状态敏感。驱动程序将忽略任何接收的字节数,除非DSR调制解调器的输入线为高。DWORD fTXContinueOnXoff :1; //为TRUE,输入缓冲区内字节已经满XoffLim及驱动程序已经发送XoffChar停止接收字节时,仍然继续发送。为FALSE,输入缓冲区内XonLim是空的,及驱动程序已经发送XonChar字符恢复接收的字节传输后,才会继续接收。DWORD fOutX :1; //发送方的行为定义,为TRUE时,接收到XoffChar之后便停止发送,接收到XonChar之后将重新开始发送;DWORD fInX :1; //接收方的行为定义,为TRUE时,接收缓冲区接收到代表缓冲区满的XoffLim之后,XoffChar发送出去;接收缓冲区空的Buffer达到XonLim之后,XonChar发送出去。DWORD fErrorChar :1; DWORD fNull :1; DWORD fRtsControl :2; // RTS Control Flow//RTS_CONTROL_DISABLE时,RTS置为OFF//RTS_CONTROL_ENABLE时, RTS置为ON//RTS_CONTROL_HANDSHAKE时,//当接收缓冲区小于半满时RTS为ON//当接收缓冲区超过四分之三满时RTS为OFF//RTS_CONTROL_TOGGLE时,//当接收缓冲区仍有剩余字节时RTS为ON ,否则缺省为OFFDWORD fAbortOnError :1; // abort reads/writes on error,为TRUE时,有错误发生时中止读和写操作DWORD fDummy2 :17; WORD wReserved; WORD XonLim; //指定在XON字符发送之前接收缓冲区中空缓冲区可允许的最小字节数WORD XoffLim; //指定在XOFF字符发送这前接收缓冲区中数据缓冲可允许的最小字节数BYTE ByteSize; BYTE Parity; //奇偶校验方式BYTE StopBits; //停止位char XonChar; //请求发送方继续发送时的字符 0x11char XoffChar; //请求发送方停止发送时的字符 0x13char ErrorChar; char EofChar; char EvtChar; WORD wReserved1;} DCB, *LPDCB;
0 0
- MFC 串口通讯程序
- MFC串口通讯
- VC2012/VS2012 MFC串口通讯上位机程序教程笔记
- VC2012/VS2012 MFC串口通讯上位机程序教程笔记
- 串口通讯API程序
- JAVA串口通讯程序
- MATLAB串口通讯程序
- MFC实现串口通讯编程
- 简单的串口通讯程序
- 基于MSCOMM控件串口通讯(MFC)
- 使用SerialPort类设计串口通讯程序
- 使用Win32 API创建串口通讯程序
- 使用Win32创建串口通讯程序
- 串口通讯程序(中断方式)
- 使用SerialPort类设计串口通讯程序
- 使用SerialPort类设计串口通讯程序
- 使用Win32创建串口通讯程序
- 使用SerialPort 类设计串口通讯程序
- linux jdk 安装
- 算法和数据结构面试题(16)-单链表倒置
- Mark 下 android Touch 事件传递顺序
- C语言中位运算符--位移运算符
- ftp上传中文文件夹提示错误550
- MFC 串口通讯程序
- finally一定会执行吗?
- 蓝桥杯试题集 算法训练 区间k大数查询
- 子网划分全面学习
- [Java、Php、Python、Flash、C++、Go、Flash开发工具大集合!!!][ide/最全]
- mysql锁和死锁
- Let the Balloon Rise
- MindManger快捷键
- FTP协议