針對 Windows CE 平台,透過 P/Invoke 呼叫 coredll.dll 實現序列埠通訊與 NMEA 協議解析。
DCB:裝置控制區塊,設定波特率、奇偶校驗、資料位、停止位等COMMTIMEOUTS:通訊逾時設定OVERLAPPED:非同步 I/O 重疊結構CreateFile、GetCommState、BuildCommDCB、SetCommState、GetCommTimeouts、SetCommTimeouts、ReadFile、WriteFile、CloseHandle、GetLastErrorpublic void Open() {
DCB dcb = new DCB(); COMMTIMEOUTS cto = new COMMTIMEOUTS();
hComm = CreateFile(PortNum, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (hComm == INVALID_HANDLE_VALUE) throw new ApplicationException("無法開啟序列埠!");
GetCommTimeouts(hComm, ref cto);
cto.ReadTotalTimeoutConstant = ReadTimeout;
SetCommTimeouts(hComm, ref cto);
GetCommState(hComm, ref dcb);
dcb.BaudRate = BaudRate; dcb.ByteSize = ByteSize; dcb.Parity = Parity; dcb.StopBits = StopBits;
dcb.flags = 1; if (Parity > 0) dcb.flags |= 2; // fBinary=1, fParity=1
if (!SetCommState(hComm, ref dcb)) throw new ApplicationException("無法設定序列埠!");
Opened = true;
}
public byte[] Read(int NumBytes) {
byte[] buf = new byte[NumBytes];
if (hComm != INVALID_HANDLE_VALUE) {
OVERLAPPED ovl = new OVERLAPPED(); int bytesRead = 0;
ReadFile(hComm, buf, NumBytes, ref bytesRead, ref ovl);
byte[] outBytes = new byte[bytesRead]; Array.Copy(buf, 0, outBytes, 0, bytesRead);
return outBytes;
} throw new ApplicationException("序列埠未開啟!");
}
public void Write(byte[] WriteBytes) {
if (hComm != INVALID_HANDLE_VALUE) {
OVERLAPPED ovl = new OVERLAPPED(); int bytesWritten = 0;
WriteFile(hComm, WriteBytes, WriteBytes.Length, ref bytesWritten, ref ovl);
} else throw new ApplicationException("序列埠未開啟!");
}
GetGPS() 從 $GPRMC 句式提取經度(X)、緯度(Y)、時間(T)、速度(V):
DM2DD():度分格式轉十進制度格式T2Time():日期時間字串轉 DateTime 並加 8 小時(UTC+8)開啟埠口讀取 512 位元組,檢查是否含 $GP 標頭判斷 GPS 裝置是否就緒。
透過 Timer 週期性讀取:
GPS ss_port = new GPS();
private void opengps(string ComPort) {
ss_port.PortNum = ComPort; ss_port.BaudRate = 4800; ss_port.ByteSize = 8; ss_port.Parity = 0; ss_port.StopBits = 1; ss_port.ReadTimeout = 1000;
if (ss_port.Opened) { ss_port.Close(); ss_port.Open(); } else ss_port.Open();
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e) {
if (ss_port.Opened) gpsread(); else ss_port.Open();
}
private void gpsread() {
byte[] data = ss_port.Read(512);
string gps = Encoding.ASCII.GetString(data, 0, data.Length);
GetParam.GpsLongitude = ss_port.GetGPS(gps, "X");
GetParam.GpsLatitude = ss_port.GetGPS(gps, "Y");
GetParam.GpsSpeed = ss_port.GetGPS(gps, "V");
GetParam.GpsTime = ss_port.GetGPS(gps, "T");
// 狀態判斷與預設值處理...
}
十六進制字串與位元組陣列互轉。