Hallo,
vielleicht findet jemand Zeit, sich dieses Codefragemnt anzuschauen:
bACKReceived:= False; //Flag für ACK von PC löschen
SetSysTimer(TimerTOut, 250); //Kein ACK von PC? Dann Timeout nach 250xSystick
repeat
SetSysTimer(TimerWait, 8); //~80ms auf Antwort von PC warten
SerOutBlock_P(@SendBuffer[0], 9); //Referenz OK an PC senden
inc(SendACKCount); //Sendungen mitzaehlen
repeat
if serstat then //PC hat gesendet
SerialMonitor; //Input verarbeiten, hier wird auch bACKReceived gesetzt
endif;
until isSysTimerZero(TimerWait); //80ms um, ACK empfangen? Sonst weiter bis TimeOut
until bACKReceived or isSysTimerZero(TimerTOut);
SysLEDflashMsg(0, SendACKCount, 5);
Es geht darum, Daten an den PC zu senden und auf eine Bestätigung des PC zu warten.
Die Funktionen SerInpBlock_TO habe ich gesehen, glaube aber nicht, dass ich diese für meine Empfangsroutine "SerialMonitor" nutzen kann. Siehe Codefragment unten.
Grundsätzlich funktioniert Senden und Empfang, wie ich es jetzt gelöst habe. Ich habe aber den Verdacht, das ich alles (mal wieder) zu kompliziert mache?
Vielen Dank für Eure Zeit und eine schöne Woche!
Rolf
procedure SerialMonitor;
begin
if CommFlag = StartChar then //Vorher schon gültiges Startzeichen empfangen?
inc(CommPointer); // dann im Buffer ablegen
RecvBuffer[CommPointer]:= SerInp;
if (CommPointer = BUFFMAX) then //Bufferende erreicht?
if RecvBuffer[CommPointer] = LASTCHAR then // und auch letztes Zeichen=Endezeichen?
CommFlag:= Received; //Ja, Empfangsflag setzen
else //Buffer voll und kein Endezeichen
CommFlag:= NoChar; //wieder von vorn
endif; // if RecvBuffer[CommPointer] = SYNC
endif; //if (CommPointer = BUFFMAX) then
else
Case Serinp of
SYNC : //sync empfangen
CommPointer:= 0; //Bufferzeiger auf Anfang Buffer
CommFlag:= StartChar;
RecvBuffer[CommPointer]:= SYNC;
|
endcase;
endif; //if CommFlag = StartChar then
if CommFlag = Received then
(*
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|snyc |cmd |dat1 |dat2 |dat3 |dat4 |crcL |crcH | stp |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
CRC16 über Byte1 bis Byte4
CMD von 1..125
Bit7 von CMD = 1 = ACK
*)
CRCstreamInit ($0810);
Crc16w := CRCcheck(@RecvBuffer[1], 5);
crcPCLow:= RecvBuffer[6];
crcPCHigh:= RecvBuffer[7];
if CrcPC = Crc16w then //die vom PC gesendete CRC ist gleich der errechneten
cmd:= RecvBuffer[1]; //also ist das Kommando gültig
if cmd < 127 then //es wurde ein Befehl vom PC empfangen
RecvBuffer[1]:= RecvBuffer[1] or %10000000; //Bit7 auf 1, stecht für ACK
CRCstreamInit ($0810);
Crc16w := CRCcheck(@RecvBuffer[1], 5); //CRC16 über Byte1 bis Byte4
RecvBuffer[6]:= lo(Crc16w);
RecvBuffer[7]:= hi(Crc16w);
SerOutBlock_P(@RecvBuffer[0], 9); //ACK an PC senden
ProcessCommand(cmd); //Befehl ausführen
else //es wurde ein ACK von PC empfangen
ProcessACK(cmd);
endif;
endif;
CommFlag:= NoChar;
CommPointer:= 0;
endif;
end;
vielleicht findet jemand Zeit, sich dieses Codefragemnt anzuschauen:
Code
bACKReceived:= False; //Flag für ACK von PC löschen
SetSysTimer(TimerTOut, 250); //Kein ACK von PC? Dann Timeout nach 250xSystick
repeat
SetSysTimer(TimerWait, 8); //~80ms auf Antwort von PC warten
SerOutBlock_P(@SendBuffer[0], 9); //Referenz OK an PC senden
inc(SendACKCount); //Sendungen mitzaehlen
repeat
if serstat then //PC hat gesendet
SerialMonitor; //Input verarbeiten, hier wird auch bACKReceived gesetzt
endif;
until isSysTimerZero(TimerWait); //80ms um, ACK empfangen? Sonst weiter bis TimeOut
until bACKReceived or isSysTimerZero(TimerTOut);
SysLEDflashMsg(0, SendACKCount, 5);
Es geht darum, Daten an den PC zu senden und auf eine Bestätigung des PC zu warten.
Die Funktionen SerInpBlock_TO habe ich gesehen, glaube aber nicht, dass ich diese für meine Empfangsroutine "SerialMonitor" nutzen kann. Siehe Codefragment unten.
Grundsätzlich funktioniert Senden und Empfang, wie ich es jetzt gelöst habe. Ich habe aber den Verdacht, das ich alles (mal wieder) zu kompliziert mache?
Vielen Dank für Eure Zeit und eine schöne Woche!
Rolf
Code
procedure SerialMonitor;
begin
if CommFlag = StartChar then //Vorher schon gültiges Startzeichen empfangen?
inc(CommPointer); // dann im Buffer ablegen
RecvBuffer[CommPointer]:= SerInp;
if (CommPointer = BUFFMAX) then //Bufferende erreicht?
if RecvBuffer[CommPointer] = LASTCHAR then // und auch letztes Zeichen=Endezeichen?
CommFlag:= Received; //Ja, Empfangsflag setzen
else //Buffer voll und kein Endezeichen
CommFlag:= NoChar; //wieder von vorn
endif; // if RecvBuffer[CommPointer] = SYNC
endif; //if (CommPointer = BUFFMAX) then
else
Case Serinp of
SYNC : //sync empfangen
CommPointer:= 0; //Bufferzeiger auf Anfang Buffer
CommFlag:= StartChar;
RecvBuffer[CommPointer]:= SYNC;
|
endcase;
endif; //if CommFlag = StartChar then
if CommFlag = Received then
(*
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|snyc |cmd |dat1 |dat2 |dat3 |dat4 |crcL |crcH | stp |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
CRC16 über Byte1 bis Byte4
CMD von 1..125
Bit7 von CMD = 1 = ACK
*)
CRCstreamInit ($0810);
Crc16w := CRCcheck(@RecvBuffer[1], 5);
crcPCLow:= RecvBuffer[6];
crcPCHigh:= RecvBuffer[7];
if CrcPC = Crc16w then //die vom PC gesendete CRC ist gleich der errechneten
cmd:= RecvBuffer[1]; //also ist das Kommando gültig
if cmd < 127 then //es wurde ein Befehl vom PC empfangen
RecvBuffer[1]:= RecvBuffer[1] or %10000000; //Bit7 auf 1, stecht für ACK
CRCstreamInit ($0810);
Crc16w := CRCcheck(@RecvBuffer[1], 5); //CRC16 über Byte1 bis Byte4
RecvBuffer[6]:= lo(Crc16w);
RecvBuffer[7]:= hi(Crc16w);
SerOutBlock_P(@RecvBuffer[0], 9); //ACK an PC senden
ProcessCommand(cmd); //Befehl ausführen
else //es wurde ein ACK von PC empfangen
ProcessACK(cmd);
endif;
endif;
CommFlag:= NoChar;
CommPointer:= 0;
endif;
end;