Hallo Leute,
ich hänge gerade an einem Problem fest und hoffe ihr habt eine Idee wie ich das mit AVRco lösen könnte.
In meinem aktuellen Projekt habe ich folgenden Task- / Processaufbau und das ganze System läuft richtig rund und sauber.
Aber da ich mit einem Ausweisleser-System über RS485 reden muss (meine Steuerung ist der Master) wollte ich hier was ändern.
Hier die Tasks/Processe:
Mein Problem ist nun, der Leser sendet verschiedene Längen,
z.B. :
ACKN $FF $AA
NACK $FF $BB
Beim Telegramm Anfang: $FF $CC (Start of Text)
Beim Telegramm Ende: $FF $DD (End of Text) gefolgt von 2 Byte Checksumme
Also kann das Telegramm vom Leser immer zwischen 2 bis 128 Zeichen liegen.
Im Task hatte ich das so gelöst:
Aber hier ist leider nicht immer sichergestellt, das innerhalb eines TaskZyklus das komplette Telegramm kommt. Das hat immer zu problemen geführt, wenn ich das ganze mit NACKs gestresst habe.
Deswegen wollte ich nun den Task in einem Process umbauen:
Damit dachte ich mir, ich warte hier im Process einfach bis Daten kommmen (WaitPipe) oder alle Daten da sind bzw. das TimeOut kommt "SerInpBlock_TO( UsartC0, inByte, 1)"
Den ControlJobZKS habe ich in einem Process geändert:
Der Ser-Daten-Empfang funktioniert so zwar wunderbar, aber alle paar Sekunden hängt das ganze System. Das Display wird nicht mehr aktualisiert und die die ganzen / Tasks / Processe scheinen für 2-3 Sekunden zu blocken.
Muss ich hier meine Task-/Processplanung überdenken / Optimieren oder darf ich hier vieleicht doch keine Funktion wie "SerInpBlock_TO" / "Waitpipe" nehmen?
Evtl. sollte ich hier doch lieber mit "SerStatC0", oder habt ihr evtl. eine andere Idee / Lösungsansatz?
Thorsten
ich hänge gerade an einem Problem fest und hoffe ihr habt eine Idee wie ich das mit AVRco lösen könnte.
In meinem aktuellen Projekt habe ich folgenden Task- / Processaufbau und das ganze System läuft richtig rund und sauber.
Aber da ich mit einem Ausweisleser-System über RS485 reden muss (meine Steuerung ist der Master) wollte ich hier was ändern.
Code
...
SysTick = 10; // msec
StackSize = 384, iData;
FrameSize = 768, iData;
Scheduler = iData;
...
// RS485 Leserbus
SerPortC0 = 19200, Databit8,parNone, Stop1, timeout;
RxBufferC0 = 255, iData;
TxBufferC0 = 255, iData;
SerCtrlC0 = PortA, 6, positive; {control line for RS485 driver negative oder positive}
...
TaskStack = 768, iData;
TaskFrame = 1023;
...
SysTick = 10; // msec
StackSize = 384, iData;
FrameSize = 768, iData;
Scheduler = iData;
...
// RS485 Leserbus
SerPortC0 = 19200, Databit8,parNone, Stop1, timeout;
RxBufferC0 = 255, iData;
TxBufferC0 = 255, iData;
SerCtrlC0 = PortA, 6, positive; {control line for RS485 driver negative oder positive}
...
TaskStack = 768, iData;
TaskFrame = 1023;
...
Hier die Tasks/Processe:
Code
{--------------------------------------------------------------}
// task für Leser Schnittstelle
Task ControlJobZKS(iData, suspended);
...
//--------------------------------------------------------------
// Display Process Fuss und LOGs speichern;
//--------------------------------------------------------------
process LCD_DisplBott(256, 512 : iData; 5); {Stacksize = 256 bytes, Framesize = 512 bytes, 5 Systicks}
...
//--------------------------------------------------------------
// Display Process Obere Screen LCD / Menü
process LCD_Displ(256, 512 : iData; 5); {Stacksize = 256 bytes, Framesize = 512 bytes, 5 Systicks}
...
{--------------------------------------------------------------}
// The USB_ControlJob must be repeatedly called to process common PC requests
Task ControlJob(iData, resumed);
{--------------------------------------------------------------}
Process USB_RxTx (256, 256 : iData ); {Stacksize = 256 bytes, Framesize = 256 bytes}
...
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
...
// task für Leser Schnittstelle
Task ControlJobZKS(iData, suspended);
...
//--------------------------------------------------------------
// Display Process Fuss und LOGs speichern;
//--------------------------------------------------------------
process LCD_DisplBott(256, 512 : iData; 5); {Stacksize = 256 bytes, Framesize = 512 bytes, 5 Systicks}
...
//--------------------------------------------------------------
// Display Process Obere Screen LCD / Menü
process LCD_Displ(256, 512 : iData; 5); {Stacksize = 256 bytes, Framesize = 512 bytes, 5 Systicks}
...
{--------------------------------------------------------------}
// The USB_ControlJob must be repeatedly called to process common PC requests
Task ControlJob(iData, resumed);
{--------------------------------------------------------------}
Process USB_RxTx (256, 256 : iData ); {Stacksize = 256 bytes, Framesize = 256 bytes}
...
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
...
Mein Problem ist nun, der Leser sendet verschiedene Längen,
z.B. :
ACKN $FF $AA
NACK $FF $BB
Beim Telegramm Anfang: $FF $CC (Start of Text)
Beim Telegramm Ende: $FF $DD (End of Text) gefolgt von 2 Byte Checksumme
Also kann das Telegramm vom Leser immer zwischen 2 bis 128 Zeichen liegen.
Im Task hatte ich das so gelöst:
Code
// ziehe alle Daten aus der Ser, bis SerStat False oder ZKSTimer Zero ist
//
if SerStatC0 then
rxCnt:= 0; // Zähler auf 0
rxCnt:= PipeStat(RxBufferC0); // wieviele Daten sind vorhanden
zksClearIn; // lösche EingangsBuffer
if SerInpBlockP_TO( UsartC0, @inZKS, word( rxCnt ), 10) then
..
//
if SerStatC0 then
rxCnt:= 0; // Zähler auf 0
rxCnt:= PipeStat(RxBufferC0); // wieviele Daten sind vorhanden
zksClearIn; // lösche EingangsBuffer
if SerInpBlockP_TO( UsartC0, @inZKS, word( rxCnt ), 10) then
..
Aber hier ist leider nicht immer sichergestellt, das innerhalb eines TaskZyklus das komplette Telegramm kommt. Das hat immer zu problemen geführt, wenn ich das ganze mit NACKs gestresst habe.
Deswegen wollte ich nun den Task in einem Process umbauen:
Code
//--------------------------------------------------------------
function ReadZKSData2: byte;
var
itest : byte;
rxCnt : byte;
inByte : byte;
inByte1 : byte;
inByte2 : byte;
inByte3 : byte;
begin
inByte := 0;
inByte1 := 0;
inByte2 := 0;
inByte3 := 0;
if WaitPipe( RxBufferC0, 200 ) then
// Lösche Speicher
zksClearIn();
//inZKS[79]:=0; // lösche EingangsBuffer Zähler auf 0
rxCnt:= 0;
while SerInpBlock_TO( UsartC0, inByte, 1) do
inZKS[rxCnt]:= inByte;
inc(rxCnt);
if (inByte1=$FF) AND (inByte=$AA) then break;
elsif (inByte1=$FF) AND (inByte=$BB) then break;
elsif (inByte3=$FF) AND (inByte2=$DD) then break;
Endif;
inByte3:=inByte2;
inByte2:=inByte1;
inByte1:=inByte;
endwhile;
inZKS[79]:= rxCnt; // setze Datenmenge in den Empfangsbuffer
return(rxCnt);
else // Waitpipe
return(0);
endif; // Waitpipe
end ReadZKSData2;
function ReadZKSData2: byte;
var
itest : byte;
rxCnt : byte;
inByte : byte;
inByte1 : byte;
inByte2 : byte;
inByte3 : byte;
begin
inByte := 0;
inByte1 := 0;
inByte2 := 0;
inByte3 := 0;
if WaitPipe( RxBufferC0, 200 ) then
// Lösche Speicher
zksClearIn();
//inZKS[79]:=0; // lösche EingangsBuffer Zähler auf 0
rxCnt:= 0;
while SerInpBlock_TO( UsartC0, inByte, 1) do
inZKS[rxCnt]:= inByte;
inc(rxCnt);
if (inByte1=$FF) AND (inByte=$AA) then break;
elsif (inByte1=$FF) AND (inByte=$BB) then break;
elsif (inByte3=$FF) AND (inByte2=$DD) then break;
Endif;
inByte3:=inByte2;
inByte2:=inByte1;
inByte1:=inByte;
endwhile;
inZKS[79]:= rxCnt; // setze Datenmenge in den Empfangsbuffer
return(rxCnt);
else // Waitpipe
return(0);
endif; // Waitpipe
end ReadZKSData2;
Damit dachte ich mir, ich warte hier im Process einfach bis Daten kommmen (WaitPipe) oder alle Daten da sind bzw. das TimeOut kommt "SerInpBlock_TO( UsartC0, inByte, 1)"
Den ControlJobZKS habe ich in einem Process geändert:
Code
{--------------------------------------------------------------}
// Process für Leser Schnittstelle
Process ControlJobZKS (256, 512 : iData; 2, resumed ); // 2 Systicks
...
// Process für Leser Schnittstelle
Process ControlJobZKS (256, 512 : iData; 2, resumed ); // 2 Systicks
...
Der Ser-Daten-Empfang funktioniert so zwar wunderbar, aber alle paar Sekunden hängt das ganze System. Das Display wird nicht mehr aktualisiert und die die ganzen / Tasks / Processe scheinen für 2-3 Sekunden zu blocken.
Muss ich hier meine Task-/Processplanung überdenken / Optimieren oder darf ich hier vieleicht doch keine Funktion wie "SerInpBlock_TO" / "Waitpipe" nehmen?
Evtl. sollte ich hier doch lieber mit "SerStatC0", oder habt ihr evtl. eine andere Idee / Lösungsansatz?
Thorsten