線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:6586
推到 Plurk!
推到 Facebook!

使用RS232 接收GPS 資料

答題得分者是:mephise
good3125
一般會員


發表:2
回覆:2
積分:0
註冊:2008-05-16

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-05-16 20:34:07 IP:59.120.xxx.xxx 訂閱

各位大大好
我是剛加入的板友
最近寫出一個可以透過RS232接收GPS資料的程式
但是,是寫在用BC6開發在C下
所以只會有黑框框,不過為了讓人使用,所以打算寫出介面
就把C的程式放進介面中,編譯也會通過...
但是每當按下做好的開始鈕,程式就會卡住
有人跟我說是因為我是同步接收的,所以等不到資料就不會開始
但在C的黑框框下,卻都跑的好好的,分明一樣的核心程式碼(只改了一點些為了銜接介面)
為什麼放進介面中卻無法使用呢?
以下是程式碼

[code cpp]
#include
#include
#include
#define CarNo "JZ-3938" //CAR Number
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
struct GGA //struct of GGA
{
char strUttcTime [20];
char varLatitude [20];
char strNSIndicator [20];
char varLongitude [20];
char strEWIndicator [20];
char strPositionFix [20];
char strSatsUsed [20];
char strIIDOP [20];
char strAltitude [20];
char strAltUnits [20];
char strGeoid [20];
char strSepUnits [20];
char strDgpsAge [20];
char strDgpsid [20];
char strchecksum [20];
char strTerminator [20];
}GGA_info;
//------------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HANDLE hPort;
LPCTSTR lpszPortName;
DWORD dwError, dwThreadID;
DCB PortDCB;
COMMTIMEOUTS CommTimeouts;
BYTE Byte;
DWORD dwCommModemStatus, dwBytesTransferred, READBUFLEN, WRITEBUFLEN;
String s;
s="COM" String(Edit8->Text);
hPort = CreateFile(s.c_str(),GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
// Handle to port with attribute to copy
// Specify a set of events to be monitored for the port.
SetCommMask (hPort, EV_RXCHAR);
SetupComm(hPort, READBUFLEN, WRITEBUFLEN);
PurgeComm(hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutConstant = 0;
CommTimeouts.WriteTotalTimeoutMultiplier = 10;
CommTimeouts.WriteTotalTimeoutConstant = 1000;
SetCommTimeouts(hPort, &CommTimeouts);
// If it fails to open the port, return FALSE.
PortDCB.DCBlength = sizeof (DCB);
// Get the default port setting information.
GetCommState (hPort, &PortDCB);
// Change the DCB structure settings.
PortDCB.BaudRate = 4800; // Current baud
PortDCB.fBinary = TRUE; // Binary mode; no EOF check
PortDCB.fParity = TRUE; // Enable parity checking.
PortDCB.fOutxCtsFlow = FALSE; // No CTS output flow control
PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control
PortDCB.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type
PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity
PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx
PortDCB.fOutX = FALSE; // No XON/XOFF out flow control
PortDCB.fInX = FALSE; // No XON/XOFF in flow control
PortDCB.fErrorChar = FALSE; // Disable error replacement.
PortDCB.fNull = FALSE; // Disable null stripping.
PortDCB.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control
PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on error.
PortDCB.ByteSize = 8; // Number of bits/bytes, 4-8
PortDCB.Parity = NOPARITY; // 0-4=no,odd,even,mark,space
PortDCB.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2
SetCommState (hPort, &PortDCB);
// Retrieve the time-out parameters for all read and write operations on the port.
GetCommTimeouts (hPort, &CommTimeouts);
// Change the COMMTIMEOUTS structure settings.
char linebuf[1024], *p, *q, *pField;
p = linebuf;
while (hPort != INVALID_HANDLE_VALUE)
{
// Wait for an event to occur for the port.
WaitCommEvent (hPort, &dwCommModemStatus, 0);
// Re-specify the set of events to be monitored for the port.
if (dwCommModemStatus & EV_RXCHAR == EV_RXCHAR)
{
if( ReadFile (hPort, p, 1, &dwBytesTransferred, 0) == 0)
break;
if( *p == 0xA )
{
// one line is received
if(strncmp(linebuf, "$GPGGA,", 7) == 0)
{
// this is the line that we want!
// parse the line
memset(&GGA_info, 0, sizeof(GGA_info));
int j = 1;
pField = linebuf 7;
for(q = pField; *q != 0; q )
{
if(*q == ',' || *q == 0xD || *q == 0xA)
{
*q = 0;
if (j == 1) strcpy(GGA_info.strUttcTime, pField);
if (j == 2) strcpy(GGA_info.varLatitude, pField);
if (j == 3) strcpy(GGA_info.strNSIndicator, pField);
if (j == 4) strcpy(GGA_info.varLongitude, pField);
if (j == 5) strcpy(GGA_info.strEWIndicator, pField);
if (j == 6) strcpy(GGA_info.strPositionFix, pField);
if (j == 7) strcpy(GGA_info.strSatsUsed, pField);
if (j == 8) strcpy(GGA_info.strIIDOP, pField);
if (j == 9) strcpy(GGA_info.strAltitude, pField);
if (j == 10) strcpy(GGA_info.strAltUnits, pField);
if (j == 11) strcpy(GGA_info.strGeoid, pField);
if (j == 12) strcpy(GGA_info.strSepUnits, pField);
if (j == 13) strcpy(GGA_info.strDgpsAge, pField);
if (j == 14) strcpy(GGA_info.strDgpsid, pField);
q ;
pField = q;
j ;
}
}
// Chack here
Edit1->Text=GGA_info.strUttcTime;
Edit2->Text=GGA_info.strEWIndicator;
Edit3->Text=GGA_info.varLongitude;
Edit4->Text=GGA_info.varLatitude;
Edit5->Text=GGA_info.strNSIndicator;
Edit6->Text=CarNo;
Edit7->Text="$GPGGA";
}
[/code]


小弟是BCB介面的新手,若問題太笨,請見諒
也順便問一下
若要加入一個可以探測使用者有那些正在用的COMPORT的介面選項
這大概要怎麼寫呢?
可以提供思考方式,或一些提示嗎?
因為我現在的COM號碼依舊是用打入的...

以上就是我的問題
先在這感謝回答的人
------
就是因為什麼都不知道...
才能體會成長的喜悅....
所以繼續學習吧....
GGL
資深會員


發表:104
回覆:600
積分:335
註冊:2006-11-05

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-06-07 10:16:30 IP:203.70.xxx.xxx 未訂閱
先回答妳的第二個問題

讀取使用中的port可透過讀取機碼的方式
HKEY_LOCAL_MOCHINE/HARDWARE/DEVICEMAP/SERIALCOMM
good3125
一般會員


發表:2
回覆:2
積分:0
註冊:2008-05-16

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-06-07 18:31:04 IP:59.120.xxx.xxx 訂閱

===================引 用 GGL 文 章===================
先回答妳的第二個問題

讀取使用中的port可透過讀取機碼的方式
HKEY_LOCAL_MOCHINE/HARDWARE/DEVICEMAP/SERIALCOMM


感謝大大回答

其實我介面的問題已經解決了
全都是因為那個WHILE...但那個WHILE又是我程式,可以不斷抓資料的核心
所以,我已經換了別的寫法,並且在介面下寫出來了

不過第2個問題,也就是大大你回答的
我倒是沒想到可以這做呢....
感謝大大的提供,詳細的方法,我會在去找找的

------
就是因為什麼都不知道...
才能體會成長的喜悅....
所以繼續學習吧....
mephise
高階會員


發表:4
回覆:149
積分:205
註冊:2004-02-09

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-06-07 21:25:48 IP:220.137.xxx.xxx 訂閱
我補充一下第二點好了  下面這段是用 Delphi 寫成的, 換成 BCB 很簡單, 函數名稱都一樣

Reg: TRegistry;

Reg:=TRegistry.Create(KEY_READ);
Reg.RootKey:=HKEY_LOCAL_MACHINE;
if Reg.KeyExists('\HARDWARE\DEVICEMAP\SERIALCOMM') then begin
Reg.OpenKey('\HARDWARE\DEVICEMAP\SERIALCOMM',False);
Data:=TStringList.Create;
Reg.GetValueNames(Data);
for i:=0 to Data.Count-1 do ListBox1.Items.Add(Reg.ReadString(Data.Strings[i]));
end;

不過在 BCB 中 HARDWARE\DEVICEMAP\SERIALCOMM 要換成 HARDWARE\\DEVICEMAP\\SERIALCOMM
\ --> 換成 \\ 因為在C中 \是控制字元符號

關於第一個問題 你的 RS232 沒有實作 Multi-Threading 這是會有問題的
許多同好都是使用 SPComm 元件, 我建議你不妨試試看 雖然她是用 Delphi 寫成的 BCB 還是能直接使用
------
Mephise Chen
前興德工程師
good3125
一般會員


發表:2
回覆:2
積分:0
註冊:2008-05-16

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-06-07 21:30:56 IP:125.224.xxx.xxx 訂閱

===================引 用 mephise 文 章===================
我補充一下第二點好了 下面這段是用 Delphi 寫成的, 換成 BCB 很簡單, 函數名稱都一樣

Reg: TRegistry;

Reg:=TRegistry.Create(KEY_READ);
Reg.RootKey:=HKEY_LOCAL_MACHINE;
if Reg.KeyExists('\HARDWARE\DEVICEMAP\SERIALCOMM') then begin
Reg.OpenKey('\HARDWARE\DEVICEMAP\SERIALCOMM',False);
Data:=TStringList.Create;
Reg.GetValueNames(Data);
for i:=0 to Data.Count-1 do ListBox1.Items.Add(Reg.ReadString(Data.Strings[i]));
end;

不過在 BCB 中 HARDWARE\DEVICEMAP\SERIALCOMM 要換成 HARDWARE\\DEVICEMAP\\SERIALCOMM
\ --> 換成 \\ 因為在C中 \是控制字元符號

關於第一個問題 你的 RS232 沒有實作 Multi-Threading 這是會有問題的
許多同好都是使用 SPComm 元件, 我建議你不妨試試看 雖然她是用 Delphi 寫成的 BCB 還是能直接使用

感謝大大提供詳細用法
至於開PORT的元件,小弟是找不到好,應該說找不到有解釋怎麼用的
不過大大你說的SPCOMM,小弟倒是沒試過,有空會來試看看
目前小弟還是乖乖的用API來開PORT...
雖然很麻煩,但我想怎改都可以....
再次感謝回覆
------
就是因為什麼都不知道...
才能體會成長的喜悅....
所以繼續學習吧....
mephise
高階會員


發表:4
回覆:149
積分:205
註冊:2004-02-09

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-06-08 12:09:33 IP:220.137.xxx.xxx 訂閱
我建議可以看一下 SPComm 的原始程式碼
開 Port 的方式都是用 CreateFile 沒錯, 但是用 Multi-Treading(TThread) 來讀取資料
這樣你的主程式就不會掛在那邊等資料了
------
Mephise Chen
前興德工程師
系統時間:2024-03-29 21:51:45
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!