|
Introduction In the .NET compact framework version 1.1, there is no direct way of accessing the built in serial ports on the Pocket PC device. This has been corrected in version 2 of the framework, but for most of us using version 1.1, how can we get around this problem? This article details the source code to create a C .dll file that can be accessed from other C, C++ or C# applications. Using the code The code below is the full source code for a basic serial port .dll library. The code should be compiled with Microsoft Embedded Visual Tools which can be downloaded from Microsoft's site by clicking here. Please feel free to use this in your own projects, and to build on top of this functionality as suits your requirements: /******************************************************************************** File: genserial.c Author: Brent Jenkins Website: http://www.e-ultrasys.com/ Platform: Pocket PC / Win32 ********************************************************************************/ #include <windows.h> HANDLE g_hPort = INVALID_HANDLE_VALUE; /******************************************************************************** Function: OpenPort Parameters: szPort - name of the port to be opened (e.g. "COM1:") lBaudRate - the baud rate to use for the connection Returns: FALSE on fail, TRUE on success Purpose: Open a connection to the specified port. ********************************************************************************/ extern __declspec(dllexport) BOOL OpenPort(unsigned short* szPort, unsigned long lBaudRate) { BOOL result = FALSE; DCB dcb; if(g_hPort == INVALID_HANDLE_VALUE) { g_hPort = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(g_hPort != INVALID_HANDLE_VALUE) { if(GetCommState(g_hPort, &dcb)) { dcb.BaudRate = lBaudRate; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.fBinary = TRUE; dcb.fParity = TRUE; dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fDsrSensitivity = FALSE; dcb.fTXContinueOnXoff = TRUE; dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.fErrorChar = FALSE; dcb.fNull = FALSE; dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.fAbortOnError = FALSE; if(SetCommState(g_hPort, &dcb)) { result = TRUE; } else { MessageBox(NULL, _T("SetCommState() Failed"), _T("Error"), MB_OK); } } else { MessageBox(NULL, _T("GetCommState() Failed"), _T("Error"), MB_OK); } } else { MessageBox(NULL, _T("Unable to open the specified port"), _T("Error"), MB_OK); g_hPort = INVALID_HANDLE_VALUE; } } return result; } /******************************************************************************** Function: ClosePort Parameters: N/A Returns: N/A Purpose: Close the current connection to the specified port. ********************************************************************************/ extern __declspec(dllexport) void ClosePort() { if(g_hPort != INVALID_HANDLE_VALUE) { CloseHandle(g_hPort); g_hPort = INVALID_HANDLE_VALUE; } } /******************************************************************************** Function: ReadPort Parameters: szBuffer - pointer to a byte buffer to receive the bytes from the currently open port nBufferLength - maximum length of the buffer Returns: Number of bytes actually read from the port, or -1 on fail. Purpose: Read a specified number of bytes from the currently open port. ********************************************************************************/ extern __declspec(dllexport) DWORD ReadPort(BYTE* szBuffer, int nBufferLength) { DWORD bytesread = 0; if(g_hPort != INVALID_HANDLE_VALUE) { if(!ReadFile(g_hPort, szBuffer, nBufferLength, &bytesread, NULL)) { g_hPort = INVALID_HANDLE_VALUE; bytesread = -1; } } return bytesread; } /******************************************************************************** Function: WritePort Parameters: szBuffer - pointer to a byte buffer to send to the currently open port nBufferLength - length of the buffer Returns: Number of bytes actually written to the port, or -1 on fail. Purpose: Write a specified number of bytes to the currently open port. ********************************************************************************/ extern __declspec(dllexport) int WritePort(BYTE* szBuffer, int nBufferLength) { int byteswritten = 0; if(g_hPort != INVALID_HANDLE_VALUE) { if(!WriteFile(g_hPort, szBuffer, nBufferLength, &byteswritten, NULL)) { g_hPort = INVALID_HANDLE_VALUE; byteswritten = -1; } } return byteswritten; } /******************************************************************************** Function: GetErrorCode Parameters: N/A Returns: Error code relating to the last error encountered. Purpose: Retrieve the Windows error code of the last error that occurred. ********************************************************************************/ extern __declspec(dllexport) DWORD GetErrorCode() { return GetLastError(); } Points of Interest So how can I use this from C#? Well, once you've compiled this into your Pocket PC .dll file (don't forget to set the correct target processor - usually x86 for the Windows emulator or ARM for the actual device), you can access it from your .NET Smart Device Application by adding the following code to your C# project: [DllImport("genserial.dll")] static extern bool OpenPort(string PortName, int nBaudRate); [DllImport("genserial.dll")] static extern void ClosePort(); [DllImport("genserial.dll")] static extern int ReadPort(byte[] Buffer, int nBufferLength); [DllImport("genserial.dll")] static extern int WritePort(byte[] Buffer, int nBufferLength); [DllImport("genserial.dll")] static extern int GetErrorCode(); Make sure that the .dll file is in the same location as your .exe, or alternatively put it in the \Windows folder. You can then call each function from C# as if it was code within your project! Have fun! History 24/07/2006 - Initial version. Download source code - 1168.3 Kb 转自:http://www.codeproject.com/useritems/ppcnetserialdll.asp
|