各位大俠朋友,我的工控軟體使用了6個Spcomm,用戶操作了某個部件后,需要顯示該部件的狀態,如果使用定時器掃描的話,好像很卡,這時是不是要用執行緒掃描?在表單里創建執行緒,直接可以使用本表單的Spcomm控制元件進行收發嗎?有沒有例子看看?
uj5u.com熱心網友回復:
執行緒里創建視窗類物件進行處理。uj5u.com熱心網友回復:
修正下上文手誤,是串口類物件
uj5u.com熱心網友回復:
SPCOMM 本身就是執行緒類,訊息觸發的。在收到訊息反饋后,給主行程發送一個訊息,就可以了,比如說,收到1號串口,狀態值是多少。就可以了。uj5u.com熱心網友回復:
如果各個串口想“同時”獨立監控,就一個串口一個執行緒。各個串口控制元件可以在主執行緒里創建好,這樣好管理,也好配置。各個子執行緒呼叫相應串口的方法或事件,用訊息和主執行緒通信。uj5u.com熱心網友回復:
如果操作才觸發資料重繪的話,不應該會卡頓啊,每包資料都很大?也可以定時器時間間隔放大一點。6個SPCOMM也不多。分配好每個SPCOMM的收發記憶體空間就行。除非你的PC本來配置就不高,CPU對一次過多快取資料處理不過來可能會卡。uj5u.com熱心網友回復:
我要讀取設備的狀態,由于設備多,輪詢一邊要1分鐘,如果我要對某個設備發命令,我現在的做法是,停止輪詢,發命令,檢查狀態,再接收新的操作命令。輪詢我是用定時器做的,現在想用執行緒,大俠們有沒有這樣的例子?uj5u.com熱心網友回復:
我如果在表單里創建執行緒,那執行緒函式就可以直接使用表單里的Spcomm控制元件嗎?如果不用執行緒,多加Application.processMessage是否可以改善?
uj5u.com熱心網友回復:
再頂,別下去uj5u.com熱心網友回復:
unearth 說的挺清楚的啊。
另外 你的定時器是接識訓是發送還是兩者都有?
uj5u.com熱心網友回復:
定時器目前是收發都有。我將讀取設備某個引數做成一個函式,在定時器里依次運行。uj5u.com熱心網友回復:
SPCOMM對串口的讀寫是分別放在讀、寫執行緒中的。我們的寫操作,實際上是向寫執行緒post一條訊息,這費不了多少時間
而我們定義的讀函式,實際是在接收執行緒中被呼叫,這也不會引起主執行緒的阻賽,當然對UI的操作可能略有影響
我覺得unearth 說的挺清楚的啊。
或者把你的定時器 和 讀取設備某個引數的函式,用一段偽代碼發布上來?
uj5u.com熱心網友回復:
收發資料很快的,用SPCOMM,根本不需要自己寫執行緒,我現在是這么做的,我96個串口都處理的過來。private
Comm:array of TComm;
SRData:array[1..6,0..1]of string; //【1-6,0】此列存盤發送資料,【1..6,1】此列存盤接收到的資料
如需要6個串口初始化函式里寫
SetLength(Comm,6)
for回圈創建6個物件
并且寫Comm[i].OnReceiveData=https://bbs.csdn.net/topics/CommReceiveData; 共用一個接收函式
接收函式里寫
Str_CommName:=(Sender as TComm).CommName;
比如你6個串口設定的串口名稱串列為COM1,COM2,COM3,COM4,COM5,COM6
根據Str_CommName就可以等到是第X個串口發的資料.
然后存到SRData[X,1]里面去。
發送資料流程
1、for i:=1 to 6 do
發資料
2、 延時(此處可以判定比如你用全域變數計數你發送了6條,判斷是否接收了6條,如果是,就結束延時)
處理資料
我現在在家,沒辦法發代碼。
我現在用的一點都不卡。
uj5u.com熱心網友回復:
procedure Delay(i_Msc:integer);var
初始時間,現在時間。
begin
初始時間=GetTickCount;
repeat
現在時間=GetTickCount;
Application.ProcessMessage;
until(B_Receive) or (現在時間 減去 初始時間)>=I_Msc
end;
在接收函式里判斷是否接收到6條( 可以根據資料幀結束字符判斷),如果是就B_Receive:=True;
uj5u.com熱心網友回復:
更正:根據Str_CommName就可以得到是第X個串口收到的資料
uj5u.com熱心網友回復:
你的問題感覺描述的不是太清楚大概是串口收發處理的不利索導致界面卡了吧。
SPCOMM這個控制元件基本沒用過,用的最多的是CPort,不過應該都差不多的吧,都有接收事件的吧,或者說在串口收到數的時候主執行緒應該是知道的吧。
我的想法就是6個串口用一個接受事件,然后再接收事件里通過判斷是哪個串口收到數了,加上標記然后存入緩沖區,然后就不用管了。再用一個定時器定時掃描緩沖區,如果有資料就處理,然后清除緩沖區,如果沒有就不管。原則是串口接受事件里做的事情最好不要太多,把決議資料的作業放到定時器里面去做。當然這里最好加一個臨界區,這樣就更保險了。
我做工控,再大的資料量都不出錯
uj5u.com熱心網友回復:
首先感謝大家的幫助!我有22個溫控模塊;
22個流量計模塊;
13個松下伺服;
13個分子泵;
7臺特種電源,我在定時器里實作對他們的狀態掃描。
我是表單里拖了6個SPcomm控制元件,每個設定好接收函式。
對于每個Spcomm控制元件,寫好發送函式。
卡得很厲害。
uj5u.com熱心網友回復:
我對DMC這種部件使用了一個定時器,定時間隔是2秒。每次掃描一個。procedure TSamMonitor.timDMCTimer(Sender: TObject);
begin
if DMCmonitorEnable = False then exit;
Application.ProcessMessages;
intDMCmonTim := intDMCmonTim + 1;
case intDMCmonTim of
1: ScanDMC10(1,'D8009','D8020','D8031','D8042');
2: ScanDMC10(2,'D8053','D8064','D8075','D8086');
3: ScanDMC10(3,'D10009','D10020','D10031','D10042');
4: ScanDMC10(4,'D8209','D8220','D8231','D8242');
5: ScanDMC10(5,'D8253','D8264','D8275','D8286');
6: ScanDMC10(6,'D10209','D10220','D10231','D10242');
7: ScanDMC10(7,'D8409','D8420','D8431','D8442');
8: ScanDMC10(8,'D8453','D8464','D8475','D8486');
9: ScanDMC10(9,'D8609','D8620','D8631','D8642');
10: ScanDMC10(10,'D8653','D8664','D8675','D8686');
11: ScanDMC10(11,'D8809','D8820','D8831','D8842');
12: ScanDMC10(12,'D8853','D8864','D8875','D8886');
13: ScanDMC10(13,'D9009','D9020','D9031','D9042');
14: ScanDMC10(14,'D9053','D9064','D9075','D9086');
15: ScanDMC10New(1,'D9209','D9220','D9231','D9242');
16: ScanDMC10New(2,'D9253','D9264','D9275','D9286');
17: ScanDMC10New(3,'D9409','D9420','D9431','D9442');
18: ScanDMC10New(4,'D9453','D9464','D9475','D9486');
19: ScanDMC10New(5,'D9609','D9620','D9631','D9642');
20: ScanDMC10New(6,'D9653','D9664','D9675','D9686');
21: ScanDMC10New(7,'D9809','D9820','D9831','D9842');
22: ScanDMC10New(8,'D9853','D9864','D9875','D9886');
end;
if intDMCmonTim > 22 then intDMCmonTim := 0;
end;
在我的工程里,目前使用了四個這種定時器。
我想如果動態掃描做成執行緒的話,執行緒函式只管不停地掃描設備狀態,結果送到我的PLC通道中。
這種會最好,但是自己沒有深入用過執行緒,所以至今沒下決心。
監控的程序有發有收,我一般做成一個函式。然后在定時器里回圈呼叫。
SPcomm自帶接收、發送執行緒,但對于掃描監控怎么用執行緒還是沒想清楚。
uj5u.com熱心網友回復:
在表單里已經有Spcomm物件的情況下,再創建執行緒,可以使用這些Spcomm的實體物件嗎?uj5u.com熱心網友回復:
ScanDMC10 和 ScanDMC10New 是如何實作的?感覺你程式卡是設計問題 而不是實作問題
uj5u.com熱心網友回復:
前臺用定時器“掃描”串口設備,當然卡界面了。這么多下位設備,最好還是用執行緒。
串口是行程獨占資源,一個行程打開了串口,其它行程就不能用了。在一個行程內前后臺、各執行緒是可以共用的,保證收發不要沖突。
看你用的設備,都是用485主從通信方式吧,那就好控制了。
uj5u.com熱心網友回復:
慚愧啊,大俠兄弟能否發個例子學習學習?[email protected]
uj5u.com熱心網友回復:
如果執行緒的方法搞掂,我會將此專題總結一些。分享出來。uj5u.com熱心網友回復:
SPCOMM 本身就是執行緒類,訊息觸發的。在收到訊息反饋后,給主行程發送一個訊息,就可以了,比如說,收到1號串口,狀態值是多少。就可以了uj5u.com熱心網友回復:
不需要用定時器呀,發完資料后,延時判斷接收到資料,就處理資料就是 。你的定時器有重入的可能,你最好是進入定時器事件里,先關掉定時器,再打開定時器,可以試試。
uj5u.com熱心網友回復:
不需要用定時器呀,發完資料后,延時判斷接收到資料,就處理資料就是 。你的定時器有重入的可能,你最好是進入定時器事件里,先關掉定時器,處理完資料后,再打開定時器,可以試試。
uj5u.com熱心網友回復:
http://download.csdn.net/detail/a295281315/7162601我上傳的一個使用SPCOMM并發的Demo,自編程式部分沒有使用多執行緒。
uj5u.com熱心網友回復:
討論好激烈,學習氣范訓常濃厚啊!uj5u.com熱心網友回復:
非常感謝!我今天將定時器的間隔放大,這樣卡得輕了許多。但是還是不理想。uj5u.com熱心網友回復:
七個RS485通訊回路,每個都有20多個站點,通訊引數基本在19200,E,8,1,這樣掃描起來很費時間,整個程式跑起來后,有“死機”現象,不能回應鍵盤、滑鼠訊息,但是通訊仍在進行。苦惱中。。。
uj5u.com熱心網友回復:
串口控制元件本身單開執行緒進行接收,如果有的話,只要做好協議中自己這邊的發送部分就OK了我們前段做的一個工程,用MOXA的8串口卡進行通訊,8個SPCOMM同時作業,不卡啊。。。
uj5u.com熱心網友回復:
hongss,你好!會不會是我的接收程式中使用了VCL控制元件,導致了系統不穩定?我想把接收到的資料放到狀態欄中的面盤中顯示,以便觀察來往的資料是否正確。這樣7個Spcomm控制元件都會收到資料后訪問Statusbar,這算不算執行緒中修改了VCL?會不會是這里導致了系統的卡死?我的接收函式類似下面:
procedure TsamMonitor.commSDC46ReceiveData(Sender: TObject;
Buffer: Pointer; BufferLength: Word);
var
str : String;
begin
SetLength(Str,BufferLength);
move(buffer^,pchar(@Str[1])^,bufferlength);
sbarDMCMQV.Panels.Items[3].Text := sbarDMCMQV.Panels.Items[3].Text + Str;
end;
我想接收函式中直接用一個字串全域變數來接收,不用StatusBar中的panel了,這樣會不會好一些?
uj5u.com熱心網友回復:
還有,Spcomm本身是支持執行緒的,在我這種情況下如何使用它的執行緒?我要輪詢很多的現場設備,可以說不停地輪詢掃描,發一個命令,等待其回傳結果,再發下一個,再等待反饋結果。
那么Spcomm的執行緒是怎樣用?
準備好發送資料,然后給發送執行緒發送訊息?
接收到資料怎么處理?Spcomm收到資料后也會發送訊息給主執行緒?
我希望將這個很費時間的監控掃描程序做在一個或幾個執行緒里面,每個執行緒驅動一個Spcomm,完成征詢命令1,征詢命令2.。。。依次下去,這樣可以實作嗎?
uj5u.com熱心網友回復:
我的定時器發送、接收都有
uj5u.com熱心網友回復:
hongss,你好!會不會是我的接收程式中使用了VCL控制元件,導致了系統不穩定?我想把接收到的資料放到狀態欄中的面盤中顯示,以便觀察來往的資料是否正確。這樣7個Spcomm控制元件都會收到資料后訪問Statusbar,這算不算執行緒中修改了VCL?會不會是這里導致了系統的卡死?
我的接收函式類似下面:
procedure TsamMonitor.commSDC46ReceiveData(Sender: TObject;
Buffer: Pointer; BufferLength: Word);
var
str : String;
begin
SetLength(Str,BufferLength);
move(buffer^,pchar(@Str[1])^,bufferlength);
sbarDMCMQV.Panels.Items[3].Text := sbarDMCMQV.Panels.Items[3].Text + Str;
end;
我想接收函式中直接用一個字串全域變數來接收,不用StatusBar中的panel了,這樣會不會好一些?
還有,Spcomm本身是支持執行緒的,在我這種情況下如何使用它的執行緒?
我要輪詢很多的現場設備,可以說不停地輪詢掃描,發一個命令,等待其回傳結果,再發下一個,再等待反饋結果。
那么Spcomm的執行緒是怎樣用?
準備好發送資料,然后給發送執行緒發送訊息?
接收到資料怎么處理?Spcomm收到資料后也會發送訊息給主執行緒?
我希望將這個很費時間的監控掃描程序做在一個或幾個執行緒里面,每個執行緒驅動一個Spcomm,完成征詢命令1,征詢命令2.。。。依次下去,這樣可以實作嗎?
串口控制元件本身的執行緒不是這樣理解的,你不用管它本身用不用執行緒,它的內部執行緒和你也沒關系。前面說過了,你可以在自己的主執行緒里創建好Spcomm,并配置好各個引數,然后你的執行緒就可以用這個在主執行緒里創建的SPCOMM了。為了簡單,一個執行緒單獨用一個SPCOMM,這樣就不用考慮各個執行緒間的沖突了。要發送的訊息可以預先設定好一個串列傳入通信子執行緒,通信子執行緒收到資料后給主執行緒發訊息,可以這樣發訊息:
var
aDataRec:TMyRec;
.................
PostMessage(MainFormHandle,WM_MESSAGE001,Integer(@aDataRec),0);
................
//這個aDataRec可以是臨時變數,這樣就可以傳遞大資料了,也不要用全域變數了
如果上位機和下位要互動的資訊是有限和預知的,可以在通信執行緒里設定好。如果是要人參與互動,那就得臨時掛起通信執行緒了,控制元件通信流程。
我記得LZ是個和我一樣的大齡DELPHIER,串口通信方面的可以留言喲,咱們交流學習
uj5u.com熱心網友回復:
非常感謝山水大俠的相助,明天我又要奔赴客戶那里了,我會馬上試一下你的這招。有問題再請教各位。uj5u.com熱心網友回復:
我要讀取設備的狀態,由于設備多,輪詢一邊要1分鐘,如果我要對某個設備發命令,我現在的做法是,停止輪詢,發命令,檢查狀態,再接收新的操作命令。輪詢我是用定時器做的,現在想用執行緒,大俠們有沒有這樣的例子?
你的串口操作是發完就等待收資料的?如果是這樣的話,效率感覺不是很高,自己定義一個管理SPCOMM的類,定義一個回呼函式介面這個介面可能是(串口ID(標識你所使用的是哪個串口,長度,資料)在SPCOMM的接收中呼叫回呼函式來告訴你哪個串口有資料來了,發送就相對簡單了,資料發完就往下一個走不要等,有資料來回呼會告訴你,沒有資料來肯定就是沒有回的,回呼函式里面可能要做同步處理。如果回呼是你的執行緒函式你可能還要考慮VCL執行緒安全的問題。
uj5u.com熱心網友回復:
SPCOMM我記得是收發是兩條單獨的執行緒,感覺你的應用像是串口矩陣一樣,如果要提高效率可能要把6個發整合在一個執行緒中處理,這個是你打開了串口就可以拿到句柄發資料就不是問題了,收資料可以參考SPCOMM,發資料要你改了。祝你好運。轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/108819.html
標籤:網絡通信/分布式開發
