需要用到VC串口调试程序,于是写了一个串口调试助手作参考,源码地址:http://download.csdn.net/detail/hc260164797/4360519,欢迎大家拍砖~~
程序界面是
串口设置是,9600波特率,8数据位,1位停止位,无校验位
该程序实现两个线程,一个线程串口读数据,并更新界面,一个座位主界面和串口发送数据。
主要实现函数:
1.枚举所有可用串口:
//枚举串口 void EnumerateSerialPorts(CUIntArray& ports) { //Make sure we clear out any elements which may already be in the array ports.RemoveAll(); //Determine what OS we are running on OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); BOOL bGetVer = GetVersionEx(&osvi); //On NT use the QueryDosDevice API if (bGetVer && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)) { //Use QueryDosDevice to look for all devices of the form COMx. This is a better //solution as it means that no ports have to be opened at all. TCHAR szDevices[65535]; DWORD dwChars = QueryDosDevice(NULL, szDevices, 65535); if (dwChars) { int i=0; for (;;) { //Get the current device name TCHAR* pszCurrentDevice = &szDevices[i]; //If it looks like "COMX" then //add it to the array which will be returned int nLen = _tcslen(pszCurrentDevice); if (nLen > 3 && _tcsnicmp(pszCurrentDevice, _T("COM"), 3) == 0) { //Work out the port number int nPort = _ttoi(&pszCurrentDevice[3]); ports.Add(nPort); } // Go to next NULL character while(szDevices[i] != _T('\0')) i++; // Bump pointer to the next string i++; // The list is double-NULL terminated, so if the character is // now NULL, we're at the end if (szDevices[i] == _T('\0')) break; } } else TRACE(_T("Failed in call to QueryDosDevice, GetLastError:%d\n"), GetLastError()); } else { //On 95/98 open up each port to determine their existence //Up to 255 COM ports are supported so we iterate through all of them seeing //if we can open them or if we fail to open them, get an access denied or general error error. //Both of these cases indicate that there is a COM port at that number. for (UINT i=1; i<256; i++) { //Form the Raw device name CString sPort; sPort.Format(_T("\\\\.\\COM%d"), i); //Try to open the port BOOL bSuccess = FALSE; HANDLE hPort = ::CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (hPort == INVALID_HANDLE_VALUE) { DWORD dwError = GetLastError(); //Check to see if the error was because some other app had the port open or a general failure if (dwError == ERROR_ACCESS_DENIED || dwError == ERROR_GEN_FAILURE) bSuccess = TRUE; } else { //The port was opened successfully bSuccess = TRUE; //Don't forget to close the port, since we are going to do nothing with it anyway CloseHandle(hPort); } //Add the port number to the array which will be returned if (bSuccess) ports.Add(i); } } }2.初始化串口:
void CSerial1AppDlg::OnBnClickedOpencomBtn() { // TODO: 在此添加控件通知处理程序代码 /*串口的初始化*/ CString str_com=L""; com_combobox.GetWindowTextW(str_com); hCom=CreateFile(str_com,GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING,0,NULL); //打开串口 if(hCom==(HANDLE)-1) { MessageBox(L"打开COM失败!"); } else{ open_btn.EnableWindow(FALSE); close_btn.EnableWindow(TRUE); send_btn.EnableWindow(TRUE); com_combobox.EnableWindow(FALSE); SetupComm(hCom,100,100); //输入缓冲区和输出缓冲区的大小都是100 COMMTIMEOUTS TimeOuts; //设定读超时 TimeOuts.ReadIntervalTimeout=MAXDWORD; TimeOuts.ReadTotalTimeoutMultiplier=0; TimeOuts.ReadTotalTimeoutConstant=0; //在读一次输入缓冲区的内容后读操作就立即返回, //而不管是否读入了要求的字符。 //设定写超时 TimeOuts.WriteTotalTimeoutMultiplier=100; TimeOuts.WriteTotalTimeoutConstant=500; SetCommTimeouts(hCom,&TimeOuts); //设置超时 DCB dcb; GetCommState(hCom,&dcb); dcb.BaudRate=9600; //波特率为9600 dcb.ByteSize=8; //每个字节有8位 dcb.Parity=NOPARITY; //无奇偶校验位 dcb.StopBits=ONESTOPBIT ; //停止位 SetCommState(hCom,&dcb); PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR); //创建新线程读取串口数据 hThread_receiver=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)UpdateUIThread, this, 0, (unsigned long *)&ThreadID); } }
HCURSOR CSerial1AppDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CSerial1AppDlg::OnBnClickedSendBtn() { // TODO: 在此添加控件通知处理程序代码 //UpdateData(true); CString str_senddata=L""; send_edit.GetWindowTextW(str_senddata);//需要发送到数据 CStringA str_senddataA=""; str_senddataA=CStrW2CStrA(str_senddata); int len=str_senddata.GetLength(); DWORD dwBytesWrite=len; COMSTAT ComStat; DWORD dwErrorFlags; BOOL bWriteStat; ClearCommError(hCom,&dwErrorFlags,&ComStat); bWriteStat=WriteFile(hCom,str_senddataA,dwBytesWrite,& dwBytesWrite,NULL); if(!bWriteStat) { MessageBox(L"写串口失败!"); } }
//读数据 CString readdata(){ char str[100]; memset(str,'\0',100); DWORD wCount=100;//读取的字节数 BOOL bReadStat; bReadStat=ReadFile(hCom,str,wCount,&wCount,NULL); if(!bReadStat){ AfxMessageBox(L"读串口失败!,点击确定关闭程序"); exit(0); } PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); return (CString)str; }
//更新线程函数 void UpdateUIThread(CSerial1AppDlg *p){ CString str=L""; CString str_previous=L""; while(1){ str_previous=str; str.Append(readdata()); if(str_previous!=str){ p->receive_edit.SetWindowTextW(str); } //p->SendMessage(WM_MYUPDATEDATA,FALSE); } }