VC++ .net 串口操作(简单的上位机串口操作)

来源:互联网 发布:淘宝卖家规则及处罚 编辑:程序博客网 时间:2024/05/16 09:03

因为我一直使用的是嵌入式芯片,比较擅长C,一直想写点简单的windows程序,发现用C只能使用MFC或者c#,直到发现了VC++ .NET后,觉得这个最简单了,既有C的灵活,又有.net托管界面,因此非常方便,就不用学别的语言,虽然简单,但是C语言用来通信以及内存操作还是非常简单的了,我是用的是VS2010,对于工程建立以及界面就不多说了,比较简单,多折腾几次就会了.


自己写的底层串口相关的函数


#include "StdAfx.h"#include "UART.h"#include "WinReg.h"#include "WINDOWS.h"#include "tChar.h"#include "stdio.h"#pragma comment(lib, "advapi32.lib")//关闭串口//UartHandle;串口句柄BOOL UART_TYPE::UART_Close(HANDLE UartHandle){return CloseHandle(UartHandle);}//初始化串口//ComNum:串口编号,0-255,对应串口COM1-COM256,串口名称在缓冲区pUartNoBuff中//返回:0:初始化失败;其他:串口句柄//BuffSize:收发缓冲区大小//pError:返回的错误HANDLE UART_TYPE::UART_Init(BYTE ComNum, DWORD BaudRate, DWORD BuffSize, DWORD *pError){HANDLE hCom;//串口句柄TCHAR WcharStr[16];char CharStr[16];WORD len = 0;*pError = 0;if(ComNum > (this->UartNum-1)) return 0;if(pUartNoBuff[ComNum]>=9){sprintf_s(CharStr,15,"\\\\.\\COM%d",this->pUartNoBuff[ComNum]+1);//格式化字符串,生成COM1-COM256}else{sprintf_s(CharStr,15,"COM%d",this->pUartNoBuff[ComNum]+1);//格式化字符串,生成COM1-COM256}len = strlen(CharStr);//计算输入字符串长度len = MultiByteToWideChar( CP_ACP, 0, CharStr,  len, WcharStr, len); //将char转换为WCHARWcharStr[len] = 0;//添加结束符hCom = CreateFile((LPTSTR)WcharStr, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);//同步模式打开串口if(hCom == INVALID_HANDLE_VALUE)//打开串口失败{//dwError = GetLastError();//::MessageBox(NULL,(LPCTSTR)_T("打开串口失败!"), (LPCTSTR)_T("提示"), MB_YESNO);*pError = GetLastError();return 0;}else//打开串口成功{if((MYUART_Setting(hCom, BaudRate) == TRUE) && (MYUART_SetBuff(hCom, BuffSize, BuffSize) == TRUE))//设置串口成功{MYUART_ClearTxBuff(hCom);//清除发送缓冲区MYUART_ClearRxBuff(hCom);//清除接收缓冲区MYUART_SetTimeOut(hCom);//设置串口超时时间 }else//设置串口失败{//this->dwError = GetLastError();*pError = GetLastError();//::MessageBox(NULL,(LPCTSTR)_T("设置串口失败!"), (LPCTSTR)_T("提示"), MB_YESNO);return 0;}}return hCom;}//设置串口//8个数据位,1个起始位,1个停止位,无奇偶校验//hCom:串口句柄//BaudRate:串口波特率//返回:FALSE:设置失败,TRUE:设置成功BOOL UART_TYPE::MYUART_Setting(HANDLE hCom, int BaudRate){DCB dcb;dcb.BaudRate = BaudRate;//设置波特率dcb.fBinary = TRUE;//二进制数据模式dcb.fParity = FALSE;//无奇偶校验,无错误报告dcb.fOutxCtsFlow = FALSE;//关闭CTS流控dcb.fOutxDsrFlow = FALSE;//关闭DSR流控dcb.fDtrControl = DTR_CONTROL_DISABLE;//禁用DTR流控dcb.fDsrSensitivity = FALSE;//DSR忽略dcb.fTXContinueOnXoff = FALSE;//接收缓冲区满后停止接收dcb.fOutX = FALSE;//关闭字符流控制dcb.fInX = FALSE;//关闭接收字符流控制dcb.fErrorChar = FALSE;//关闭奇偶校验错误替换指定字节dcb.fNull = FALSE;//保留空字节,也就是接收数据0dcb.fRtsControl = RTS_CONTROL_DISABLE;//关闭发送请求流控dcb.fAbortOnError = FALSE;//忽略错误dcb.wReserved = 0;//保留,必须为0dcb.XonLim = FALSE;//关闭流量控制dcb.XoffLim = FALSE;//关闭流量控制dcb.ByteSize = 8;//数据位数为8dcb.Parity = NOPARITY;//无奇偶校验dcb.StopBits = ONESTOPBIT;//一个停止位dcb.XonChar = 0;//传输开始字符,无效dcb.XoffChar = 0;//传输结束字符,无效dcb.ErrorChar = 0;//替代奇偶校验错误字节,无效dcb.EofChar = 0;//数据结束信号,无效dcb.EvtChar = 0;//使用的字符值的信号事件return SetCommState(hCom, &dcb);//配置,并返回状态}//获取串口接收计数器//hCom:串口句柄//返回:接收缓冲区接收的数据数量DWORD UART_TYPE::MYUART_GetRxCnt(HANDLE hCom){DWORD ComError;COMSTAT ComStat;ClearCommError(hCom, &ComError, &ComStat);return ComStat.cbInQue;//返回接收到的数据数量}//清除接收缓冲区//hCom:串口句柄//返回:TRUE:成功,FALSE;失败BOOL UART_TYPE::MYUART_ClearRxBuff(HANDLE hCom){return PurgeComm(hCom, PURGE_RXABORT | PURGE_RXCLEAR);//清除输入缓冲器}//清除发送缓冲区//hCom:串口句柄//返回:TRUE:成功,FALSE;失败BOOL UART_TYPE::MYUART_ClearTxBuff(HANDLE hCom){return PurgeComm(hCom, PURGE_TXABORT | PURGE_TXCLEAR);//清除输入缓冲器}//设置缓冲区大小//hCom:串口句柄//RxBuffSize:接收缓冲区大小;TxBuffSize:发送缓冲区大小//返回:TRUE:成功,FALSE;失败BOOL UART_TYPE::MYUART_SetBuff(HANDLE hCom, DWORD RxBuffSize, DWORD TxBuffSize){return SetupComm(hCom, RxBuffSize, TxBuffSize);//设置输入输出缓冲区}//设置串口超时BOOL UART_TYPE::MYUART_SetTimeOut(HANDLE hCom){COMMTIMEOUTS to;to.ReadIntervalTimeout = 10;//字节超时to.ReadTotalTimeoutMultiplier = 100;to.ReadTotalTimeoutConstant=100;to.WriteTotalTimeoutMultiplier = 10;to.WriteTotalTimeoutConstant = 10;return SetCommTimeouts(hCom, &to);}//读取串口接收到的数据DWORD UART_TYPE::MYUART_ReadData(HANDLE hCom, BYTE *pBuff, DWORD BuffSize){DWORD cnt;OVERLAPPED lpOverlapped;lpOverlapped.hEvent = 0;//事件句柄设置为无效if(ReadFile(hCom, pBuff, BuffSize, &cnt, &lpOverlapped) == TRUE)return cnt;elsereturn 0;}//串口发送数据BOOL UART_TYPE::MYUART_SendData(HANDLE hCom, BYTE *pBuff, DWORD DataLen){DWORD cnt;OVERLAPPED lpOverlapped;lpOverlapped.hEvent = 0;//事件句柄设置为无效MYUART_ClearTxBuff(hCom);return WriteFile(hCom, pBuff, DataLen, &cnt, &lpOverlapped);}//复制长字符串2到1static void TcharCopy(TCHAR *Str1, TCHAR *Str2){while(*Str2 != 0x0000){*Str1++ = *Str2++;}*Str1 = 0;//添加结束符}//冒泡排序,用来排列串口,将串口编号从小到大排列static void Bubble(BYTE *pBuff, WORD n){WORD i, j;BYTE temp;    for(i = 0;i < (n - 1);i ++)//排序{for(j = i + 1;j < n;j ++){if(pBuff[i] > pBuff[j])//升序排列{temp = pBuff[i];pBuff[i] = pBuff[j];pBuff[j] = temp;}}}  } //获取系统中存在的串口,通过读取注册表获得//pComNumBuff:获取的串口编号存储缓冲区,0-255对应COM1-COM256//ComCnt:最大需要获取的串口数量//返回系统串口数量void UART_TYPE::MYUART_GetComNum(void){HKEY hKey;DWORD result;WORD i=0;WCHAR WcharStr[16];char CharStr[16];WORD temp;WORD len;result = RegOpenKeyEx( HKEY_LOCAL_MACHINE,_T( "Hardware\\DeviceMap\\SerialComm" ),NULL,KEY_READ,&hKey );if(ERROR_SUCCESS == result)//打开串口注册表{TCHAR portName[ 0x100 ];DWORD dwLong, dwSize;this->UartNum = 0;for(i = 0;i < 256;i ++){dwSize = sizeof( portName ) / sizeof( TCHAR );dwLong = dwSize;result = RegEnumValue( hKey, i, portName, &dwLong, NULL, NULL, ( LPBYTE )WcharStr, &dwSize );//枚举串口if( ERROR_NO_MORE_ITEMS == result ){break;   //串口名字"COM2"}WideCharToMultiByte( CP_ACP, 0, WcharStr, -1, CharStr, wcslen(WcharStr), NULL, NULL );  CharStr[wcslen(WcharStr)] = '\0';temp = (WORD)atof(&CharStr[3]);//获取串口编号,跳过COM,获得串口编号为0-256;if(temp > 256) break;if(temp == 0) break;this->pUartNoBuff[i] = temp-1;//获取串口编号-1,从1-256变为0-255;}RegCloseKey( hKey ); //关闭注册表}else return;this->UartNum = i;//串口数量Bubble(this->pUartNoBuff, this->UartNum);//对串口号进行冒泡排序for(i = 0;i < this->UartNum;i ++)//循环更新串口{sprintf_s(CharStr,15,"COM%d",this->pUartNoBuff[i]+1);//格式化字符串,生成COM1-COM256len = strlen(CharStr);len = MultiByteToWideChar( CP_ACP, 0, CharStr,  len, this->pUartName[i], len); //将char转换为WCHARthis->pUartName[i][len] = 0;//添加结束符}}


头文件

#ifndef _MY_PRO_#define _MY_PRO_#include "windows.h"class UART_TYPE{public://变量WORD UartNum;//串口数量,存储系统当前串口数量,由MYUART_GetComNum()获取BYTE *pUartNoBuff;//串口编号缓冲区,存放当前系统串口的编号的,比如串口1-串口256 分别为0,1 .. 255,刚好一个字节WCHAR (*pUartName)[16];//串口名称,如COM1-COM256//函数BOOL UART_TYPE::UART_Close(HANDLE UartHandle);//关闭串口HANDLE UART_TYPE::UART_Init(BYTE ComNum, DWORD BaudRate, DWORD BuffSize, DWORD *pError);//初始化串口BOOL MYUART_ClearTxBuff(HANDLE hCom);//清除发送缓冲区BOOL MYUART_ClearRxBuff(HANDLE hCom);//清除接收缓冲区BOOL MYUART_Setting(HANDLE hCom, int BaudRate);//配置串口BOOL MYUART_SetBuff(HANDLE hCom, DWORD RxBuffSize, DWORD TxBuffSize);//设置缓冲区大小BOOL MYUART_SetTimeOut(HANDLE hCom);//设置串口超时DWORD MYUART_ReadData(HANDLE hCom, BYTE *pBuff, DWORD BuffSize);//读取串口接收到的数据BOOL MYUART_SendData(HANDLE hCom, BYTE *pBuff, DWORD DataLen);//串口发送数据DWORD MYUART_GetRxCnt(HANDLE hCom);//获取串口接收计数器void MYUART_GetComNum(void);//构造UART_TYPE(){this->pUartNoBuff = new BYTE[256];//申请内存this->pUartName = new WCHAR[256][16];//申请内存//获取系统串口初始MYUART_GetComNum();}//析构~UART_TYPE(){delete pUartNoBuff;//释放内存delete [16]pUartName;//释放内存}};//extern UART_TYPE UARTx;//全局串口类实例化#endif


//获取系统的串口,并显示

HANDLE hCom;//串口句柄UART_TYPE *UARTx;//全局串口类实例化UARTx = new UART_TYPE;//调用串口类//动态获取串口号并显示UARTx->MYUART_GetComNum();//更新串口列表this->_UART_ComboBox->Items->Clear();//删除所有选项for(i = 0;i < UARTx->UartNum;i ++)//循环更新串口{this->_UART_ComboBox->Items->Add(gcnew String(UARTx->pUartName[i]));}if(this->_UART_ComboBox->Items->Count != 0)//如果串口数量不为0,则选中第一个{this->_UART_ComboBox->SelectedIndex = 0;//默认选择第一个串口}

如图:



//初始化串口

//初始化串口 this->hCom = UARTx->UART_Init(this->_UART_ComboBox->SelectedIndex, CBR_115200, UART_BUFF_SIZE, &ComError); if(this->hCom != 0)//初始化串口成功 { this->_UART_ComboBox->Enabled = FALSE;//锁定串口,不可操作 this->ComLinkStatus = TRUE;//状态为连接 this->_UART_LinkButton->Text = L"断开连接"; //按钮有效 this->_UART_ReadConfButton->Enabled = TRUE; this->_UART_ReadDataButton->Enabled = TRUE; this->_UART_WriteConfButton->Enabled = TRUE; } else { pLpStr = new WCHAR[64]; pStr = new char[64]; sprintf_s(pStr,64-1, "打开串口失败(错误代码:%d)!", ComError); MyChar.CharToWchar(pStr,pLpStr);//char to WCHAR ::MessageBox(NULL,(LPCTSTR)pLpStr, (LPCTSTR)_T("连接失败"), MB_OKCANCEL); delete pLpStr; delete pStr; return; }


后面直接调用串口收发即可,同单片机一样,先发送数据,等待收数据,通过获取串口接收数据数量来读取.

操作完毕后关闭即可.


0 2
原创粉丝点击