{**************************************************************}
program WS2300_Master;
{**************************************************************}
{S. Taborek}
{Version 1.3 am 02.06.2005}
{Stand : 14.06.2005}
{Stand : 24.06.2005}
{**************************************************************}
{$NOSHADOW}
Device = mega8, VCC=4.9;
Import SysTick, RTclock, SerPort, TWINet;
From System Import longword ;
Define
ProcClock = 16000000; {Hertz}
SysTick = 10; {msec}
StackSize = $0096, iData;
FrameSize = $0064, iData;
SerPort = 38400, Stop2; {Baud, StopBits|Parity}
RxBuffer = 32, iData;
TxBuffer = 32, iData;
//
TWInetMode = Master;
TWInode = 02; {address in slave mode}
TWIpresc = TWI_BR100; {Bitrate}
TWIframe = 56, iData; {buffer/packet size}
TWIframeBC = 4; {Broadcast Frame size}
//
RTClock = iData, DateTime; {Time, DateTime}
RTCsource = SysTick;
//uses Unit_Types;
Implementation
{$IDATA}
{--------------------------------------------------------------}
{ Type Declarations }
type
TReply = array[0..31]of Byte;
TRAMDATENRec = Record
Rec_jj : byte; //1
Rec_mm : byte; //2
Rec_dd : byte; //3
Rec_hh : byte; //4
Rec_mi : byte; //5
//..........................
TempInn : Integer; //6..7 1
TempOut : Integer; //8..9 2
HumidityOut : Word; //10..11 3
WindSpeed : word; //12..13 4
WindDir : Word; //14..15 5
AirPressRel : Word; //16..17 6
DewPoint : Word; //18..19 7
RainTotal : Word; //20..21 8
OkBits : Byte; //22 für Werte 1..8
//...........................
CRS : Byte; //23
end;
//folgener Record muss in Größe gleich dem TRAMSaveRec sein!
TRAMContrRec = Record
RecStart_jj : byte; //1
RecStart_mm : byte; //2
RecStart_dd : byte; //3
RecStart_st : byte; //4
RecStart_mi : byte; //5
RecSize : byte; //6
MAX_DevNr : byte; //7
SaveZyk : byte; //8
Akt_WrSnr : word; //9..10
Last_RdPC : word; //11..12 letzter DS an PC
Last_AnzPC : word; //13..14
IdentCode : word; //15..16
voll : boolean; //17
d : byte; //18
MasterStatus : byte; //19
WSS_SlvStatus : byte; //20
RAM_SlvStatus : byte; //21
LCD_Slvstatus : byte; //22
CRS : byte; //23
end;
TRAM_DS = array[1..sizeOf(TRAMDATENRec)] of byte;
//da RAM-Wetterdaten und Ctrl-Daten gleich groß sind,
//wird TRAM_DS auch als TRAM_CDS verwendet
TTime1 = array[1..3{4}] of byte;
//.................................................
//folgender Record darf die Größe von TWIframe nicht übersteigen!!
//Der Record enthält alle Messwerte der Wetterstation - auch jene,
//die nicht im I2C-RAM archiviert werden.
TWSTSlaveDS = Record
cmd : byte; //1
Time : TTime1; //2..4 4
Date : TTime1; //5..7
TempInnen : Integer; //8..9
TempAussen : Integer; //10..11
HumidityInn : word; //12..13
HumidityOut : word; //14..15
WindFlag : byte; //16
WindCode : Byte; //17
WindSpeed : word; //18..19
WindDir : array[1..7]of byte;//20..26
AirPressRel : Word; //27..28
Rain1H : word; //29..30
RainTotal : word; //31..32
DewPoint : word; //33..34
Reserve : byte; //35
WSSensorExt : byte; //36
MW_Status : word; //37..38 für alle MW
WSConnErr : word; //39..40
Last_RdPC : word; //41..42
MasterStatus : byte; //43 >> LED s
WSS_Slv_Status : byte; //44
RAM_Slv_Status : byte; //45
LCD_Slv_status : byte; //46
RAMCapacity : longword; //47..50
r1 : longword;
end;
//folgender Record darf die Größe von TWIframe nicht übersteigen!!
TRAMSlaveRec = Record
cmd : byte; //1
qui : byte; //2
Akt_WrSnr : word; //3..4
CtrlDS : TRAMContrRec; //Controldaten 5..28
WetterDS : TRAMDATENRec; //Wetterdaten 29..51
r1 : longword;
end;
{--------------------------------------------------------------}
{ Const Declarations }
const
BroadCNode : byte = $00;
MasterNode : byte = $02;
WSTSlvNode : byte = $03;
RAMSlvNode : byte = $04;
LCDSlvNode : byte = $05;
BatSlvNode : byte = $06;
const
FM24C_Adr : byte = $50; //Moduladr. im Datenblatt: 10100000b
SlvTimeOut : byte = 20; // 20x SysTick = 200msec
TxFrameSize : byte = sizeOf(TWSTSlaveDS);
TxLCDFrameSize : byte = SizeOf(TWSTSlaveDS);
TimeoutLimit : byte = 230; //für Timeoutüberwachung der ser.Schnittst.
CRAM_ZykTime : byte = 10; //Anzahl Minuten bis Speicherung
const
RAMCtrlCode : word = $abcd;
RAM_MAX_DevNr : byte = 3; //0..3 für Anzahl FM24C256
RAMDevCapacit : word = 32768; //Bytes pro Device
RAMRecSize : byte = sizeOf(TRAMDATENRec);
RAMDS_proDev : word = RAMDevCapacit div word(RAMRecSize);
RAM_MAX_Snr : word = ((RAM_MAX_DevNr + 1)* RAMDS_proDev) -1; //
RAMContrDSAdr : word = 0; //Datensatzadresse für Control-Daten
//-----------------------------
ClearBuffer : byte = $01; //broadcast for Slv to clear Rx state
cmd_01 : byte = $01;
cmd_02 : byte = $04;
cmd_03 : byte = $15;
cmd_04 : byte = $17;
cmd_05 : byte = $19;
cmd_06 : byte = $31;
cmd_07 : byte = $43;
cmd_08 : byte = $07;
cmd_09 : byte = $13;
qui_01 : byte = $A1;
qui_02 : byte = $A4;
qui_03 : byte = $A7;
qui_04 : byte = $A9;
kenng1 : byte = $37;
kenng2 : byte = $32;
kenng3 : byte = $31;
kenng4 : byte = $33;
kenng5 : byte = $35;
kenng6 : byte = $36;
kenng8 : byte = $38;
kenng9 : byte = $A2;
kenngA : byte = $AA;
kenngB : byte = $BB;
kenngC : byte = $CC;
//es folgen Messwert-Kennzeichnungen:
CTempInn : word = 1;
CTempOut : word = 2;
CHumyInn : word = 4;
CHumyOut : word = 8;
CWindFlag : word = 16;
CWindCode : word = 32;
CWindSpd : word = 64;
CWindDir : word = 128;
CAirPress : word = 256;
CRain1H : word = 512;
CRainTot : word = 1024;
CDewPoint : word = 2048;
CWSSensExt : word = 4096;
{--------------------------------------------------------------}
{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var
NetTimeOut : SysTimer8;
twistate : tTWINetState;
//
NetTxRec[@TWITXBUFF] : TWSTSlaveDS;
NetRxRec[@TWIRXBUFF] : TWSTSlaveDS;
WstDaten : TWSTSlaveDS;
//
RAMTxRec[@TWITXBUFF] : TRAMSlaveRec;
RAMRxRec[@TWIRXBUFF] : TRAMSlaveRec;
//
RAMRX_Rec : TRAMSlaveRec;
RAM_DatenDS : TRAMDATENRec;
RAM_WDS[@RAM_DatenDS]: TRAM_DS; //array
RAM_ContrDS : TRAMContrRec;
RAM_CDS[@RAM_ContrDS]: TRAM_DS; //array
RAM_DS_S : TRAM_DS;
DS_Saved : boolean;
RAM_voll : boolean;
// RAMCDS_OK : boolean;
RAM_Wr_Snr : word;
RAM_PC_Snr : word; //hält snr temporär
RAM_ZykTime : byte;
RAMCapacity : longword;
// RAMCpA[@RAMCapacity] : array[1..4] of byte;
Prot_B_Aktiv : boolean;
Ref_DL : word;
ANr_PC : word;
winddir1 : byte;
dcf_time : boolean;
time_sync : boolean;
tick_min : boolean;
tick_std : boolean;
ret : boolean;
bcnt : byte;
w,hw : word;
lw : longword;
iw : integer;
s : string[27];
c1,c2,i,j,h : byte;
se, mi, st : byte;
dd, mm, jj : byte;
pc_snr : word;
pc_s_cnt : integer;
pc_l_cnt : integer;
// Ma_con_err : word;
// Sl_prs_err : word;
// Ma_tio_err : word;
{--------------------------------------------------------------}
{ functions }
procedure RTCtickMinute; // CallBack from RTCclock
begin
tick_min := true;
end;
procedure RTCtickHour; // CallBack from RTCclock
begin
tick_std := true;
end;
{==============================================================}
procedure RTC_TimeLesen;
{==============================================================}
begin
disableints;
se := RTCGetSecond;
mi := RTCGetMinute;
st := RTCGetHour;
enableints;
end;
{==============================================================}
procedure RTC_DateLesen;
{==============================================================}
begin
disableints;
dd := RTCGetDay;
mm := RTCGetMonth;
jj := RTCGetYear;
enableints;
end;
{==============================================================}
function SendFrame(node, frsize : byte) : boolean;
{==============================================================}
var
timeout : boolean;
begin //Senden der Daten im Puffer: NetTxRec
SetSysTimer(NetTimeOut, SlvTimeOut);
Timeout:= false;
//timeout occurs after 200msec -> 20 retries
while not(TWItxFrame(node, frsize {TxFrameSize}) or Timeout) do
TWItxClear; //tx failed, clear own states
mDelay(10); //Zeit für Slave
timeout:= isSysTimerZero(NetTimeOut);
endwhile;
if Timeout then
TWItxClear;
//slave has to clear all its states
TWItxBroadcast(ClearBuffer, 0, 0); // cmd, subnode, count
mDelay(50);
SetSysTimer(NetTimeOut, SlvTimeOut);
Timeout:= false;
// timeout occurs after 200msec -> 20 retries
while not(TWItxFrame(node, frsize {TxFrameSize}) or Timeout) do
TWItxClear; //
mDelay(10); //Zeit für Slave
timeout:= isSysTimerZero(NetTimeOut);
endwhile;
endif;
//
if timeout then // Die Sendung war fehlerhaft!!
// WriteLn(SerOut, Tx Timeout );
endif;
return(not timeout);
end;
{==============================================================}
function ReceiveFrame(Node : byte) : boolean;
{==============================================================}
var
timeout : boolean;
begin
SetSysTimer(NetTimeOut, SlvTimeOut);
Timeout:= false;
TWIrxClear;
while not(TWIrxFrame(node) or Timeout) do //Empfang NetRxRec
TWIrxClear; //rx failed, clear own states
mDelay(10); //Zeit für Slave !!!
timeout:= isSysTimerZero(NetTimeOut); //timeout nach 200msec -> 20mal
endwhile;
if Timeout then
// inc(Ma_tio_err);
// WriteLn(SerOut, Rx Timeout 1 );
TWIrxClear;
//slave has to clear all its states
TWItxBroadcast(ClearBuffer, 0, 0); // cmd, subnode, count
mDelay(50);
SetSysTimer(NetTimeOut, SlvTimeOut);
Timeout:= false;
//timeout occurs after 200msec -> 20 retries
while not(TWIrxFrame(node) or Timeout) do
TWIrxClear; //tx failed, clear own states
mDelay(10); //Zeit für Slave !!!
timeout:= isSysTimerZero(NetTimeOut);
endwhile;
endif;
return(not timeout);
end;
{--------------------------------------------------------------}
function RDWR_ADR(snr_:word; var devnr:byte):word;
{--------------------------------------------------------------}
begin
//Die I2C-RAMs werden addressiert, indem zur Basisadresse (das
//entspricht dem 1.Modul) die Adressoffsets 1 bis 7 addiert
//werden. Somit können max 8 Module adressiert werden.
devnr := Byte((snr_ div (RAMDS_proDev)));
if devnr <= RAM_MAX_DevNr then
snr_ := snr_ - (RAMDS_proDev * word(devnr));
snr_ := snr_ * RAMRecSize; //Berechnen der Byte-Adresse
devnr := FM24C_Adr or devnr; //Hardware-Adresse
endif;
return(snr_);
end;
{==============================================================}
function FM24ReadDS(ReadSnr_:word; var Satz:TRAM_DS): boolean;
{==============================================================}
var result : boolean;
devadr_ : byte;
begin
Readsnr_ := RDWR_ADR(ReadSnr_, devadr_); //Adressumrechnung
result := TWIout(devadr_, ReadSnr_);
result := result or TWIinp(devadr_, satz);
return(result);
end;
{==============================================================}
function FM24WriteDS(WriteSnr_:word; Satz:TRAM_DS): boolean;
{==============================================================}
var result : boolean;
devadr_ : byte;
begin
WriteSnr_ := RDWR_ADR(WriteSnr_, devadr_); //Adressumrechnung
result := TWIout(devadr_, WriteSnr_, satz);
return(result);
end;
{--------------------------------------------------------------}
function DateTimeLesen:boolean;
{--------------------------------------------------------------}
var ret:boolean;
tsum : byte;
begin
with WstDaten do
tsum := Time[1] or Time[2] or Time[3];
if (Time[1] < 24)and(Time[2] < 60)and (Time[3] < 60)and
(tsum > 0) and
(Date[1] > 0)and(Date[1] < 32)and
(Date[2] > 0)and(Date[2] < 13)and
(Date[3] > 0)and(Date[3] < 99) then
st := WstDaten.Time[1];
mi := WstDaten.Time[2];
se := WstDaten.Time[3];
dd := WstDaten.Date[1];
mm := WstDaten.Date[2];
jj := WstDaten.Date[3];
disableints;
RTCsetSecond(se);
RTCsetMinute(mi);
RTCsetHour(st);
enableints;
ret := true;
else
ret := false;
endif;
endwith;
return(ret);
end;
{--------------------------------------------------------------}
function SIOPufferLeeren:boolean;
{--------------------------------------------------------------}
var c_:byte;
begin
ret := false;
while serstat do
mdelay(5);
c_ := serinp; //Puffer leeren
ret := true;
endwhile;
return(ret);
end;
{--------------------------------------------------------------}
function WetterDatenHolen:boolean;
{--------------------------------------------------------------}
begin
NetTxRec.cmd:= cmd_01;
if SendFrame(WSTSlvNode, 2) then //Daten anfordern
WstDaten.cmd := 0;
h := 4;
repeat
mdelay(600);
if ReceiveFrame(WSTSlvNode) then
WstDaten := NetRxRec; //Datensatz übergeben
endif;
dec(h);
until (WstDaten.cmd = cmd_09)or (h = 0);
return(h > 0);
else
return(false);
endif;
end;
{--------------------------------------------------------------}
function GetSumCode(RAM_DS_:TRAM_DS):byte;
{--------------------------------------------------------------}
var ps:word;
begin
ps := 0;
for i := 1 to (RAMRecSize -1) do
ps := ps + word(RAM_DS_[i]);
endfor;
return(hi(ps) xor lo(ps));
end;
{--------------------------------------------------------------}
function ReadRAMControlSatz(neu_ds:boolean):boolean;
{--------------------------------------------------------------}
var dl:byte;
begin
//Lesen des Control-Records aus dem RAM:
dl := 4;
Repeat
dec(dl);
mdelay(20);
until (FM24ReadDS(RAMContrDSAdr, RAM_CDS))or(dl = 0);
if (dl = 0) then
//MasterStatus melden:
RAM_ContrDS.MasterStatus:= RAM_ContrDS.MasterStatus or $20 {32};
RAM_ContrDS.CRS := GetSumCode(RAM_CDS); //
FM24WriteDS(RAMContrDSAdr, RAM_CDS);
return(false);
endif;
//---------------
if neu_ds then //Ctrl-DS neu definieren:
// Writeln(SerOut, ControlCode neu );
RAM_ContrDS.IdentCode := RAMCtrlCode; //Ident
RAM_ContrDS.RecStart_jj := jj;
RAM_ContrDS.RecStart_mm := mm;
RAM_ContrDS.RecStart_dd := dd; //
RAM_ContrDS.RecStart_st := st;
RAM_ContrDS.RecStart_mi := mi;
RAM_ContrDS.Akt_WrSnr := 1; //RAM Datensatznummer für Neustart
RAM_ContrDS.RecSize := RAMRecSize;
RAM_ContrDS.MAX_DevNr := RAM_MAX_DevNr;
RAM_ContrDS.Last_RdPC := 0; // für PC
RAM_ContrDS.SaveZyk := RAM_ZykTime; //
RAM_ContrDS.voll := false;
RAM_ContrDS.MasterStatus:= $44;
RAM_ContrDS.CRS := GetSumCode(RAM_CDS); //
endif;
if (RAM_ContrDS.IdentCode = RAMCtrlCode)then {Ident-Test}
if (GetSumCode(RAM_CDS) = RAM_CDS[RAMRecSize]) then
// if (TestSumCode(RAM_CDS)) then
// Writeln(SerOut, CRS OK );
return(true);
else
// Writeln(SerOut, CRS Err );
//MasterStatus melden:
RAM_ContrDS.MasterStatus:= RAM_ContrDS.MasterStatus or $01;
RAM_ContrDS.CRS := GetSumCode(RAM_CDS); //raus aus der Schlinge
FM24WriteDS(RAMContrDSAdr, RAM_CDS);
return(false);
endif;
endif;
//
return(true);
end;
{--------------------------------------------------------------}
function RAMDatenRecSpeichern(snr_:word):boolean;
{--------------------------------------------------------------}
//wenn snr_ = 0 dann wird nur der Control-DS gesichert
//da jeder DS seine Zeitstempel bekommt, kann PC archivieren
var ret:boolean;
begin
if dcf_time = false then //wird true beim ersten Sync
return(false);
endif;
//
if Snr_<> RAMContrDSAdr then //nicht nur Contr-Satz sichern
//
if FM24WriteDS(Snr_, RAM_WDS) then
ret := true;
else
ret := false;
endif;
endif;
//
//----Speicherauslastung berechnen----
//Achtung: Compilerprobleme mit der Function abs !
iw := (integer(RAM_ContrDS.Last_RdPC) - integer(RAM_ContrDS.Akt_WrSnr));
if RAM_ContrDS.Akt_WrSnr < RAM_ContrDS.Last_RdPC then
RAMCapacity := longword(RAM_MAX_Snr - abs(iw));
else
RAMCapacity := longword(abs(iw));
endif;
RAMCapacity := (100000 * RAMCapacity) div longword(RAM_MAX_Snr);
//------------------------------------
RAM_ContrDS.CRS := GetSumCode(RAM_CDS); //RAM_Contr overlays RAM_CDS
FM24WriteDS(RAMContrDSAdr, RAM_CDS); //Contr-Satz sichern
return(ret);
end;
{==============================================================}
function RAMSlave_DatenEmpfangen:boolean;
{==============================================================}
//RAMRxRec[@TWIRXBUFF] : TRAMSlaveRec;
begin
mdelay(200);
if ReceiveFrame(RAMSlvNode) then
RAMRx_Rec := RAMRxRec; //Daten kopiern
case RAMRx_Rec.cmd of
cmd_01: //RAM_Slv schickt Daten zwecks Anzeige
RAM_DatenDS := RAMRx_Rec.WetterDS; //Datensatz übergeben
// nicht RAMDatenRecSpeichern(RAM_Wr_Snr); //daten sichern
|
cmd_07: //angeforderter DS trifft ein:
//hier trifft RAM-DS mit berechneten Mittelwerten ein
RAM_DatenDS := RAMRx_Rec.WetterDS; //Datensatz übergeben
if RAMDatenRecSpeichern(RAM_Wr_Snr) then //daten sichern
//Satzpointer weiterzählen:
RAM_Wr_Snr := RAM_ContrDS.Akt_WrSnr + 1;
if (RAM_Wr_Snr >= RAM_MAX_Snr) then
RAM_Wr_Snr := 1; //Überschreiben beginnt evtl jetzt
endif;
RAM_ContrDS.Akt_WrSnr := word(RAM_Wr_Snr);
else
//Satznummer darf nicht weitergezählt werden:
//Akt_WrSnr
endif;
tick_min := false;
DS_Saved := true;
|
endcase;
return(true);
else
// receive failed
// inc(Ma_con_err);
return(false);
endif;
end;
{--------------------------------------------------------------}
function DS_Senden(snr1:word; kn:byte):boolean;
{--------------------------------------------------------------}
var i5:byte;
begin
if FM24ReadDS(snr1, RAM_DS_S) then //lesen der Dates
SerOut(Kn); SerOut(Kn); //Kennung senden
SerOut(RAMRecSize + 2); //Anzahl der nun folgenden Bytes:
SerOut(lo(Snr1)); SerOut(hi(Snr1));
if kn = kenng8 then
RAM_DS_S := RAM_WDS; //aktueller Satz aus RAM-Slave
endif;
for i5 := 1 to RAMRecSize do //Daten
SerOut(RAM_DS_S[i5]);
endfor;
return(true);
else
SerOut($FD); SerOut($FD); SerOut(0); //Error 253
return(false);
endif;
end;
{--------------------------------------------------------------}
function WordReadFromCOM:word;
{--------------------------------------------------------------}
var wd1 : word;
ada1[@wd1] : array[1..2] of byte;
h6, j6 : byte;
begin
h6 := 0; j6 := 0;
repeat
if serstat then
inc(j6);
ada1[j6] := SerInp; //Empfang einer Word-Adresse
endif;
if h6 > 1 then mdelay(7); endif;
inc(h6);
until (j6 = 2) or (h6 > 75);
if (j6 = 2) then
return(wd1);
else
return($FFFF); //in diesem Zusammenhang möglich
endif;
end;
{--------------------------------------------------------------}
function DS_SendenWS(snr5:word; kn:byte):boolean;
{--------------------------------------------------------------}
begin
if DS_Senden(snr5, kn) then //gewünschter DS
return(true);
else
return(false);
endif;
end;
{--------------------------------------------------------------}
procedure PC_DatenSenden;
{--------------------------------------------------------------}
var wd : word;
ada[@wd] : array[1..2] of byte;
snr : word;
begin
//
c1 := 0;
h := 0;
repeat
if SerStat then
c1 := SerInp;
endif;
if h > 0 then mdelay(10); endif;
inc(h);
until (c1 > 0) or (h > 7);
// SIOPufferLeeren; nicht hier
//--------------
//Es werden stets mindestens 3 Byte zurückgesendet:
//1. Kennungswiederholung
//2. Kennungswiederholung
// Anzahl der folgenden Bytes
case c1 of
kenng2: //Speicherzyklus ändern
ada[1] := 9; ada[2] := 111;
wd := WordReadFromCOM; //wd overlay ada
//Zyklus muss kleiner als 60 sein, da min mod zyk !
if (ada[1] = ada[2])and(ada[1] < 60)and(ada[1] > 1) then
RAM_ZykTime := ada[1];
SerOut(kenng2); SerOut(ada[1]); SerOut(0);
RAM_ContrDS.SaveZyk := RAM_ZykTime;
RAM_ContrDS.CRS := GetSumCode(RAM_CDS); //RAM_Contr overlays
RAM_CDS
RAMDatenRecSpeichern(RAMContrDSAdr);
else
SerOut($F2); SerOut($F2); SerOut(0); //Error
endif;
|
kenng3: //RAM-Control-DS auslesen und senden:
DS_Senden(RAMContrDSAdr, kenng3); //aktueller Ctrl-DS
Prot_B_Aktiv := false;
|
kenng4: //Reset des DL:
wd := WordReadFromCOM;
if wd = RAMCtrlCode then
ReadRAMControlSatz(true); //DS neu erstellen
RAMDatenRecSpeichern(RAMContrDSAdr);
SerOut(kenng4); SerOut(kenng4); SerOut(0); //Error
else
SerOut($F4); SerOut($F4); SerOut(0); //Error
endif;
|
kenng6: //Angefordert ein bestimmter DS
snr := WordReadFromCOM; //snr wird empfangen
if (snr > 0)and(snr < RAM_MAX_Snr) then
DS_SendenWS(snr, kenng6);
else
SerOut($F6); SerOut($F6); SerOut(0); //Error
endif;
|
Kenng8: if not Prot_B_Aktiv then
DS_Senden(word(RAM_Wr_Snr), kenng8); //aktueller DS
endif;
|
kenngA: //Anzahl DS anfordern seit letzter Übernahme
//im Ctrl-Ds wird jeweils nach einer Datenübernahme die
//RAM-Satznummer gespeichert und bei einer erneuten
//Übernahme wird ab dieser Satznummer fortgesetzt.
pc_snr := WordReadFromCOM;
//
SerOut(kenngA); SerOut(kenngA);
SerOut(2); //Anzahl der nun folgenden Sende-Bytes = 2
SerOut(lo(pc_snr)); //Snr zurücksenden
SerOut(hi(pc_snr)); //Snr zurücksenden
Prot_B_Aktiv := true; //Bereit für Protokollteil B
|
kenngB://Anfordern eines bestimmten DS zwecks definitiver Übernahme.
//Die snr soll in Folge sein. Bevor dieser Teil des
//Protokolls benutzt wird, muss mit kenngA eröffnet werden.
//Die Quittierung der Übernahme durch den PC
//erfolgt abschließend über kenngC.
if Prot_B_Aktiv then
if DS_SendenWS(pc_snr, kenngB) then
//nach diesem Aufruf ist PC_Snr als die vom PC gewünschte snr
//definiert:
inc(pc_snr);
if (pc_snr > RAM_MAX_Snr-1) then
pc_snr := 1;
endif;
else
//andernfalls wurde PC informiert, dass Anfrage fehlerhaft
SerOut($FB); SerOut($FB); SerOut(0); //Error
RAM_ContrDS.Last_RdPC := word(PC_Snr);
RAMDatenRecSpeichern(RAMContrDSAdr);
endif;
else
endif;
|
kenngC:// Das Übernahme-Protokoll wird hier abgeschlossen.
// Der Master erstellt den neuen RAM_Ctrl-DS
// nach der Datenübertragung an den PC:
if Prot_B_Aktiv then
ReadRAMControlSatz(true); //DS neu erstellen
RAM_ContrDS.Last_RdPC := word(PC_Snr);
RAM_ContrDS.Akt_WrSnr := word(RAM_Wr_Snr);
RAMDatenRecSpeichern(RAMContrDSAdr);
SerOut(kenngC); SerOut(kenngC); SerOut(0); //Error
else
SerOut($FC); SerOut($FC); SerOut(0); //Error
endif;
Prot_B_Aktiv := false;
|
else
SerOut($F9); SerOut($F9); SerOut(0); //Error
endcase;
SIOPufferLeeren;
end;
{--------------------------------------------------------------}
procedure InitVar;
{--------------------------------------------------------------}
begin
tick_std := true;
time_sync := false; // RTC-Uhr muss gestellt werden
WstDaten.Date[1] := 255;
// Ma_con_err := 0;
// Sl_prs_err := 0;
// Ma_tio_err := 0;
DS_Saved := true; // damit die Speicherung nicht sofort beginnt
RAM_voll := false;
// pc_readed := false;
// pc_kenng := $F1;
Prot_B_Aktiv := false;
end;
{--------------------------------------------------------------}
{ Main Program WS2300-Datenlogger-Master}
{$IDATA}
begin
InitVar;
TWIrxClear;
EnableInts;
//
//------Uhrzeit von WS2300 holen---------------
h := 0;
dcf_time := false; //wird erst durch WS2300-Time true
while (h < 72)and(dcf_time = false) do
if WetterDatenHolen then //Daten anfordern incl. Zeit
if (WstDaten.WSS_Slv_Status and %00000011) > 0 then
if DateTimeLesen then
dcf_time := true;
h := 100;
endif;
endif;
else
mdelay(800);
TWItxBroadcast(ClearBuffer, 0, 0); // cmd, subnode, count
endif;
mdelay(2000);
inc(h);
endwhile;
mdelay(4000); // 1 mal warten bis LCD_Start abgelaufen!!!
//------1.Controlsatz übernehmen-------
repeat
until ReadRAMControlSatz(false); //hier fehlt Timeout-Kontr.
//
RAMDatenRecSpeichern(RAMContrDSAdr); //berechnet RAMCapacity
RAM_ZykTime:= RAM_ContrDS.SaveZyk; //kann vom PC parametr. werden
pc_snr := (RAM_ContrDS.Last_RdPC); //für Start
RAM_Wr_Snr := RAM_ContrDS.Akt_WrSnr; //!!!
//
//
//==================Hauptschleife======================
//
loop
//------------Datenverteilung-------------
if WetterDatenHolen then //Daten von WS2300 anfordern u holen
// Writeln(SerOut, WDaten von WS-Slv );
NetTxRec := NetRxRec; //TX-Buffer mit RX-Buffer füllen
//---hier die Daten für den LCD_Slave vorbereiten
NetTxRec.RAMCapacity := RAMCapacity; // siehe RAMDatenRecSpeichern
NetTxRec.cmd := cmd_08; //Kennung für aktuellere Daten
SendFrame(LCDSlvNode, TxLCDFrameSize); //Daten an LCDSlv weitersenden
//---hier die Daten für den RAM-Slave vorbereiten
NetTxRec.cmd := cmd_02; //auch Auforderungscode für MiW-Speichern
if SendFrame(RAMSlvNode,TxFrameSize) then //Daten an RAMSlv senden
mdelay(30);
RAMSlave_DatenEmpfangen;
endif;
endif;
//
//---------Zyklische Speicherung der Wetterdaten---------
if (mi mod RAM_ZykTime = 0)and(not DS_Saved) then
RAMTxRec.cmd := cmd_01; //Anforderungscode für RAM_DS
if SendFrame(RAMSlvNode,TxFrameSize) then //DS anfordern
mdelay(200);
RAMSlave_DatenEmpfangen;
//nur wenn Daten empfangen, wird DS_saved = true
else
endif{SendFrame};
else
//nächste RAM-Speicherung anstoßen:
if tick_min then
RTC_TimeLesen;
DS_Saved := false; //fordert die nächste Sicherung
tick_min := false;
endif;
endif{min_cnt};
//
//RTC-UHR stellen: nach je 1 Std
if tick_std then
RTC_DateLesen;
time_sync := false; //damit DCF-Time erneut gelesen wird
tick_std := false;
//
endif;
if not time_sync then
if DateTimeLesen then
//
time_sync := true;
dcf_time := true;
else
dcf_time := false;
endif;
endif;
//-----------------------------------------------
for i := 1 to 200 do //Pollen in der Warteschleife
if SerStat then //PC-Anfrage
c1 := SerInp;
mdelay(2);
if c1 = Kenng1 then
PC_DatenSenden;
mdelay(5);
else
SerOut($F0); SerOut($F0); SerOut(0); //Error
SIOPufferLeeren;
mdelay(30);
endif;
else
mdelay(30);
endif;
endfor;
endloop;
//
end WS2300_Master.