⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 robindlg.cpp

📁 PC抄表软件, 用于降数据上载到PC机上, 通过USB传COM口实现.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
{
	//UpdateData(TRUE);

	//Variables to store Vid, Pid and SerialNumbers
	WORD Vid, Pid;
	CP2101_SERIAL_STRING serialNum;

	//Loop through and display data for each connected device
//	for (int i = 0; i < m_dwNumDevices; i++)
//	{
		// Query the Vid, Pid and Serial number of each device.
		// We will use this information to look up the device
		// in the registry to find the port number. There are also
		// examples of displaying other items in the registry as well.

		// Open device
		CP2101_STATUS status = CP2101_Open(0, &m_hUSBDevice);
		if (status == CP2101_SUCCESS)
		{
			// Get Vid
			status = CP2101_GetDeviceVid(m_hUSBDevice, &Vid);
			if (status == CP2101_SUCCESS)
			{
				// Get Pid
				status = CP2101_GetDevicePid(m_hUSBDevice, &Pid);
				if (status == CP2101_SUCCESS)
				{
					BYTE bLength = 0;
					CString tmpDevStr;

					// Get Serial Number
					status = CP2101_GetDeviceSerialNumber(m_hUSBDevice, serialNum, &bLength);

					// Null terminate to make it a string
					serialNum[bLength] = '\0';

					//Display our current information about the device we found
					tmpDevStr.Format("Found Device: VID=%04X, PID=%04X", Vid, Pid);

				}
			}
		}

		// This is a function call to obtain the port number
		// by passing the Vid, Pid, and SN of the device in
		// question. An integer value with the port is passed back
		int Port;
		DWORD winVersion = GetVersion() & VERSION_MASK;
		
		if (winVersion == VERSION_WINXP2000)
			Port = GetPortNumXP2000(Vid, Pid, serialNum);
		else if (winVersion == VERSION_WIN98)
			Port = GetPortNum98(Vid, Pid, serialNum);

		// Text formatting for display of the com port
		DCB dcbPort1InitState, dcbPort1;

		CString COMPort1;
		COMPort1.Format("\\\\.\\COM%u", Port);
		CP2101_Close(m_hUSBDevice);
		m_hUSBDevice = INVALID_HANDLE_VALUE;
		if(Port!=-1)
		{
			m_comstatus.Format("COM%u ON", Port);
			UpdateData(FALSE);
		}

		// Create the Handles
		hDev1 = CreateFile(COMPort1, GENERIC_READ | GENERIC_WRITE, 0, 0, 
									OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);

		if(hDev1 == INVALID_HANDLE_VALUE)
		{
			MessageBox("Error: Invalid Handle Value for Device 1.");
			CommFlag = false;
			m_buttonul.SetWindowText("&Start");
			m_comstatus.Replace("ON","OFF");
			UpdateData(FALSE);
			//m_output = ""; 
		}
		else
		{
			if(!PurgeComm(hDev1, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) // device 1 fails
			{
				//m_output = "Error: Failed to purge COM port for device 1.";
				MessageBox("Error: Failed to purge COM port for Device 1.");
			}
			else
			{
				if(!GetCommState(hDev1, &dcbPort1InitState)) // port 1 fails to get its current state
				{
					//m_output = "Error: Failed to get current state of port 1.";
					MessageBox("Error: Failed to get current state of port 1.");
					CloseHandle(hDev1);
					hDev1 = INVALID_HANDLE_VALUE;
					CommFlag = false;
					m_buttonul.SetWindowText("&Start");
					m_comstatus.Replace("ON","OFF");
					UpdateData(FALSE);
				}
				else
				{
					dcbPort1 = dcbPort1InitState;
					dcbPort1.BaudRate = 19200;
					dcbPort1.Parity = NOPARITY;
					dcbPort1.ByteSize = 8;
					dcbPort1.StopBits = ONESTOPBIT;

					if(!SetCommState(hDev1, &dcbPort1)) // fails to set port 1 state
					{
						//m_output = "Error: Failed to set the state of port 1.";
						MessageBox("Error: Failed to set the state of port 1.");
						CloseHandle(hDev1);
						hDev1 = INVALID_HANDLE_VALUE;
						CommFlag = false;
						m_buttonul.SetWindowText("&Start");
						m_comstatus.Replace("ON","OFF");
						UpdateData(FALSE);
					}
					else 
					{
						DelayMS(60);
						if(!Transfer())
							MessageBox("Error: Failed to transfer data.");
					}
				}
			}

			
		}

		
		// Closing the handles	
//		if (hDev1 != INVALID_HANDLE_VALUE) CloseHandle(hDev1);
//		hDev1 = INVALID_HANDLE_VALUE;
//	}

	//UpdateData(FALSE);
}

bool CMyDlg::Transfer()
{
	BYTE dataStart[] = {0x66};
	nUser = 1;

	bool success = false;
	OVERLAPPED o = {0};

	o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	UINT timeout = 3000;
	
	DWORD* written = (DWORD*)malloc(sizeof(DWORD));

	DWORD toBeWritten = 1;
	if(!WriteFile(hDev1, (LPCVOID)dataStart, toBeWritten, written, &o))//send START flag
	{
		if(GetLastError() == ERROR_IO_PENDING)
		{
			if(WaitForSingleObject(o.hEvent, INFINITE) == WAIT_OBJECT_0)
				if(GetOverlappedResult(hDev1, &o, written, FALSE))
					success = true;
		}
		// surprise removal case
		else if (GetLastError() == ERROR_OPERATION_ABORTED)
		{
			MessageBox("Surprise Removal on Device Write!");
			CloseHandle(hDev1);
			hDev1 = INVALID_HANDLE_VALUE;
			CommFlag = false;
			m_buttonul.SetWindowText("&Start");
			m_comstatus.Replace("ON","OFF");
			UpdateData(FALSE);
		}
	}
	else
		success = true;

	if(*written != toBeWritten)
		success = false;

	if(success) // read the sum of users that will be uploaded
	{
		phase=1;
		TimeOutRd=500;
		SetTimer(1,10,NULL);
	}

	return success;
}

void CMyDlg::FillDeviceList()
{

	EnumDevices();
	GetDeviceData();
}

void CMyDlg::EnumDevices()
{

	//Obtain the number of connected devices
	CP2101_STATUS status = CP2101_GetNumDevices(&m_dwNumDevices);
		if(m_dwNumDevices<1) MessageBox("Error: No Supported Device.");
	if(m_dwNumDevices>1) MessageBox("Error: Please Get Rid of Other USB Devices.");
}

// GetPortNum functions takes the Vid, Pid, and SerialNumber and
// returns an integer containing the COM port that the device is
// connected to (different functions for Win98/WinXP2000)

int CMyDlg::GetPortNumXP2000(WORD vid, WORD pid, char* ser)
{
	//Variables used for Registry access
	HKEY tmpKey, tmpSubKey, tmpPortKey;
	CString portKeyString;
	DWORD valtype;
	char* portString;
	DWORD length = 100;
	portString = new char[101];

	//Set portnum to -1, so if there is an error we will
	//know by returning a negative port value
	int portNum = -1;

	//  Open keys to get to the key where the port number is located. This key is:
	//  HKLM\System\CurrentControlSet\Enum\USB\Vid_xxxx&Pid_yyyy&Mi_00\zzzz_00\DeviceParameters\PortName
	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\", 0, KEY_READ, &tmpKey))
	{
		if (ERROR_SUCCESS == RegOpenKey(tmpKey, "Enum\\USB\\", &tmpSubKey))
		{
			//Loop through and replace spaces for WinXP2000
			int i = 0;
			while (ser[i] != '\0')
			{
				if (ser[i] == 0x20)
					ser[i] = '_';
				i++;
			}

			//The portkey string should look like this
			//"Vid_XXXX&Pid_XXXX&MI_00\\XXXX_00" where the XXXX's are Vid, Pid and serial string
			portKeyString.Format("Vid_%04x&Pid_%04x&Mi_00\\%s_00\\Device Parameters\\", vid, pid, ser);

			//If the portkey string is in the registry, then go ahead and open the portname
			if (ERROR_SUCCESS == RegOpenKey(tmpSubKey, portKeyString, &tmpPortKey))
			{
				if (ERROR_SUCCESS == RegQueryValueEx(tmpPortKey, "PortName", NULL, &valtype, (unsigned char *)portString, &length))
				{
					// When we obtain this key, it will be in string format of
					// "COMXX" where XX is the port. Simply make the first three
					// elements of the string 0, and call the atoi function to obtain
					// the number of the port.
					portString[0] = '0';
					portString[1] = '0';
					portString[2] = '0';
					portNum = atoi(portString);
				}
				//Make sure to close all open keys for cleanup
				RegCloseKey(tmpPortKey);
			}
			RegCloseKey(tmpSubKey);
		}
		RegCloseKey(tmpKey);
	}
	RegCloseKey(HKEY_LOCAL_MACHINE);

	// Return the number of the port the device is connected too
	return portNum;
}

int CMyDlg::GetPortNum98(WORD vid, WORD pid, char* ser)
{
	//Variables used for Registry access
	HKEY tmpKey;
	CString portKeyString, serKeyString;
	int	serialIndex;
	DWORD valtype;
	char* portString;
	DWORD length = 100;
	portString = new char[101];

	//Set portnum to -1, so if there is an error we will
	//know by returning a negative port value
	int portNum = -1;

	//We will search through the keys by index, starting at 0
	//Use this index in the key "Enum\SLABCR\guid\XXXX"
	serialIndex = 0;
	serKeyString.Format("Enum\\SLABCR\\guid\\%.4d", serialIndex);

	//Loop through and convert the serial string to all upper case and replace spaces for Win98
	int i = 0;
	while (ser[i] != '\0')
	{
		if (ser[i] == 0x20)
			ser[i] = '_';
		else if ((ser[i] >= 0x61) && (ser[i] <= 0x7A))
			ser[i] -= 32;
		i++;
	}

	//The portkey string should look like this when we query the CLowerDeviceID
	//"USB\VID_XXXX&PID_XXXX&MI_00\\XXXX_00" where the XXXX's are Vid, Pid and serial string
	portKeyString.Format("USB\\VID_%04X&PID_%04X&MI_00\\%s_00", vid, pid, ser);

	//  Open keys to get to the key where the port number is located. This key is:
	//  HKLM\Enum\SLABCR\guid\XXXX\Portname is the key and we will loop through each key in the registry
	while (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, serKeyString, &tmpKey))
	{	
		// Determine the status of the call
		DWORD status = RegQueryValueEx(tmpKey, "CRLowerDeviceID", NULL, &valtype, (unsigned char *)portString, &length);

		// If we need to make the call again, then decrement the serial index so we can access
		// it the next time through the loop
		if (ERROR_MORE_DATA == status)
			serialIndex--;
		// Otherwise, the call is a success, and we can compare the portString from the key
		// to the port string that we want, if they match then retrieve the port
		else if (ERROR_SUCCESS == status)
		{
			if (portString == portKeyString)
			{
				if (ERROR_SUCCESS == RegQueryValueEx(tmpKey, "Portname", NULL, &valtype, (unsigned char *)portString, &length))
				{
					// When we obtain this key, it will be in string format of
					// "COMXX" where XX is the port. Simply make the first three
					// elements of the string 0, and call the atoi function to obtain
					// the number of the port.
					portString[0] = '0';
					portString[1] = '0';
					portString[2] = '0';
					portNum = atoi(portString);
				}
			}
		}

		// Increment the serial index
		serialIndex++;
		serKeyString.Format("Enum\\SLABCR\\guid\\%.4d", serialIndex);
						
		//Make sure to close all open keys for cleanup
		RegCloseKey(tmpKey);
	}
	RegCloseKey(HKEY_LOCAL_MACHINE);

	// Return the number of the port the device is connected too
	return portNum;
}

void CMyDlg::DelayMS(UINT delay)
{
	DWORD start, end;
	start = end = GetTickCount();

	// Wait for 'delay' milliseconds.
	while ((end - start) < delay)
	{
		end = GetTickCount();
	}

}

void CMyDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	KillTimer(1);

	CTime Read_date;
	BYTE dataAck[]={0xAA};
	BYTE dataError[]={0x55};

	BYTE dataSum[3];
	BYTE dataRead[72];

	BYTE checksum = 0xFF;

	bool success = false;
	OVERLAPPED o = {0};

	o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	UINT timeout = 3000;
	
	DWORD* written = (DWORD*)malloc(sizeof(DWORD));
	DWORD* read = (DWORD*)malloc(sizeof(DWORD));
	COMSTAT     ComStat;
	DWORD       dwErrorFlags;
	DWORD toBeWritten = 1, toBeRead = 72;

	ClearCommError( hDev1 , &dwErrorFlags, &ComStat ) ;
	if ((ComStat.cbInQue == 3)&&(phase==1))
	{
		success = false;

		if(!ReadFile(hDev1, dataSum, 3, read, &o))
		{
			if(GetLastError() == ERROR_IO_PENDING)
			{
				if(WaitForSingleObject(o.hEvent, timeout) == WAIT_OBJECT_0)
				{
					if(GetOverlappedResult(hDev1, &o, read, FALSE))
					{
						nUser=(short int)(dataSum[0] & 0x0F)*100+(short int)(dataSum[1] & 0x0F)*10+(short int)(dataSum[2] & 0x0F);
						success = true;
					}
				}
				else // timeout case
					MessageBox("Timeout on Device Read");
			}
			// surprise removal case
			else if (GetLastError() == ERROR_ACCESS_DENIED)
			{
				MessageBox("Surprise Removal on Device Read!");
				CloseHandle(hDev1);
				hDev1 = INVALID_HANDLE_VALUE;
				CommFlag = false;
				m_buttonul.SetWindowText("&Start");
				m_comstatus.Replace("ON","OFF");
				UpdateData(FALSE);
			}
		}
		else
		{	
			nUser=(short int)(dataSum[0] & 0x0F)*100+(short int)(dataSum[1] & 0x0F)*10+(short int)(dataSum[2] & 0x0F);
			success = true;
		}

		if((success)&&(nUser>0))
		{
			if(!PurgeComm(hDev1, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) // device 1 fails
			{
				//m_output = "Error: Failed to purge COM port for device 1.";
				MessageBox("Error: Failed to purge COM port for Device 1.");
			}
			else
			{
				if(!WriteFile(hDev1, (LPCVOID)dataAck, toBeWritten, written, &o))//send START flag
				{
					if(GetLastError() == ERROR_IO_PENDING)
					{
						if(WaitForSingleObject(o.hEvent, INFINITE) == WAIT_OBJECT_0)
							if(GetOverlappedResult(hDev1, &o, written, FALSE))
								success = true;
					}
					// surprise removal case
					else if (GetLastError() == ERROR_OPERATION_ABORTED)
					{
						MessageBox("Surprise Removal on Device Write!");
						CloseHandle(hDev1);
						hDev1 = INVALID_HANDLE_VALUE;
						CommFlag = false;
						m_buttonul.SetWindowText("&Start");
						m_comstatus.Replace("ON","OFF");
						UpdateData(FALSE);
					}
				}
				else
					success = true;

				if(*written != toBeWritten)
					success = false;

				if(success) // read the sum of users that will be uploaded
				{
					TimeOutRd=500;
					phase=2;
					SetTimer(1,10,NULL);
				}
			}
		}
	}
	else
	{
		if(phase==1) SetTimer(1,10,NULL);
	}

	//Start Receive User Data
	if ((ComStat.cbInQue == toBeRead)&&(phase==2))
	{
		success = false;

		if(!ReadFile(hDev1, dataRead, toBeRead, read, &o))
		{
			if(GetLastError() == ERROR_IO_PENDING)
			{
				if(WaitForSingleObject(o.hEvent, timeout) == WAIT_OBJECT_0)
				{
					if(GetOverlappedResult(hDev1, &o, read, FALSE))
					{
						success = true;
					}
				}
				else // timeout case
					MessageBox("Timeout on Device Read");
			}
			// surprise removal case
			else if (GetLastError() == ERROR_ACCESS_DENIED)
			{
				MessageBox("Surprise Removal on Device Read!");
				CloseHandle(hDev1);
				hDev1 = INVALID_HANDLE_VALUE;
				CommFlag = false;
				m_buttonul.SetWindowText("&Start");
				m_comstatus.Replace("ON","OFF");
				UpdateData(FALSE);
			}
		}
		else
		{
			success = true;
		}
		
		if(success)
		{
			for(int i=1;i<68;i++) checksum ^= dataRead[i];
			if(1)//((checksum==(((dataRead[69]&0x0F)<<4)|(dataRead[70]&0x0F)))&&(dataRead[0]==0x99)&&(dataRead[0]==0x99)&&(dataRead[71]==0xEE))
			{
				nUser--;
				success = true;
			}
			else
				success = false;
		}

		if(success)
		{
			//****************just for debug******************//
			UINT nByteN,iL;
			CString strT1,strT2;
			nByteN=72;
			strT2="";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -