Hallo
Ich baue eine Applikation, die u.a. einen ModbusRTU Slave implementiert. Dafür verwende ich die entsprechenden Library-Funktionen, wie in der Demo-App vorgegeben. Das Gerüst sieht etwa so aus:
Device = mega644p, VCC=3.3;
Import SysTick, SerPort;
Import I2Cport;
Import ModBus;
From System Import Processes;
Define
ProcClock = 8000000; // Hertz
SysTick = 10, Timer0; // 10 msec, use Timer0 (Timer2 used for RTU)
StackSize = $0150, iData;
FrameSize = $0150, iData;
// RS-485 / ModBus
SerPort = 19200, Databit8, parEven, Stop1; {Baud, StopBits|Parity}
RxBuffer = 255, iData;
TxBuffer = 100, iData;
SerCtrl = PortD, 4, positive; {control line for RS485 driver}
I2Cport = PortC;
I2Cdat = 1;
I2Cclk = 0;
// Modbus RTU Slave
Scheduler = iData;
ModBus = SerPort, 20, iData, 40;
ModBusMode = RTU, Timer2;
Uses ModBusServRTU;
Implementation
var
{$MODBUS MBnetaudioRTU}
ModBuff[@ModDPR]: record
// Tag Type // Register (Word)
Meter1: mb_InpW; // [00]
PagingStn: mb_InpW; // [01]
SlaveId: mb_RdWrW; // [02]
Argument: mb_RdWrW; // [03]
NetAudioCmd: mb_RdWrW; // [04]
RxBundle1: mb_RdWrW; // [05]
TxBundle1: mb_RdWrW; // [06]
Rx1Submap1: mb_RdWrW; // [07]
Tx1Submap1: mb_RdWrW; // [08]
end;
begin
Start_Processes;
mb_SetModBusDevID (1); // (LastSlaveId);
// initialize user's event handlers and enable them
mb_SetBeforeRegisterRead (@mb_BeforeRegisterRead);
mb_SetAfterRegisterWrite (@mb_AfterRegisterWrite);
loop
// Do something useful
endloop;
Wenn ich nun ein oder mehrere Register schreibe (Function code 06 oder 16), so funktioniert das meistens. Aber je nachdem was die Prozedur mb_AfterRegisterWrite tut, startet die Applikation neu oder hängt. Ein Lesezugriff auf die Register funktioniert immer. In gewissen Fällen kommt der Neustart auch nach mehrmaligem Schreiben des gleichen Registers und anschliessendem Lesezugriff auf dasselbe Register.
Sieht irgendwie nach überlaufendem Stack aus. Ist das Phänomen bekannt? Hat jemand einen Tip, was ich noch versuchen könnte? Der gleiche Fall tritt übrigens auch mit ModbusASCII auf.
Gruss
Hans
Ich baue eine Applikation, die u.a. einen ModbusRTU Slave implementiert. Dafür verwende ich die entsprechenden Library-Funktionen, wie in der Demo-App vorgegeben. Das Gerüst sieht etwa so aus:
Code
Device = mega644p, VCC=3.3;
Import SysTick, SerPort;
Import I2Cport;
Import ModBus;
From System Import Processes;
Define
ProcClock = 8000000; // Hertz
SysTick = 10, Timer0; // 10 msec, use Timer0 (Timer2 used for RTU)
StackSize = $0150, iData;
FrameSize = $0150, iData;
// RS-485 / ModBus
SerPort = 19200, Databit8, parEven, Stop1; {Baud, StopBits|Parity}
RxBuffer = 255, iData;
TxBuffer = 100, iData;
SerCtrl = PortD, 4, positive; {control line for RS485 driver}
I2Cport = PortC;
I2Cdat = 1;
I2Cclk = 0;
// Modbus RTU Slave
Scheduler = iData;
ModBus = SerPort, 20, iData, 40;
ModBusMode = RTU, Timer2;
Uses ModBusServRTU;
Implementation
var
{$MODBUS MBnetaudioRTU}
ModBuff[@ModDPR]: record
// Tag Type // Register (Word)
Meter1: mb_InpW; // [00]
PagingStn: mb_InpW; // [01]
SlaveId: mb_RdWrW; // [02]
Argument: mb_RdWrW; // [03]
NetAudioCmd: mb_RdWrW; // [04]
RxBundle1: mb_RdWrW; // [05]
TxBundle1: mb_RdWrW; // [06]
Rx1Submap1: mb_RdWrW; // [07]
Tx1Submap1: mb_RdWrW; // [08]
end;
begin
Start_Processes;
mb_SetModBusDevID (1); // (LastSlaveId);
// initialize user's event handlers and enable them
mb_SetBeforeRegisterRead (@mb_BeforeRegisterRead);
mb_SetAfterRegisterWrite (@mb_AfterRegisterWrite);
loop
// Do something useful
endloop;
Wenn ich nun ein oder mehrere Register schreibe (Function code 06 oder 16), so funktioniert das meistens. Aber je nachdem was die Prozedur mb_AfterRegisterWrite tut, startet die Applikation neu oder hängt. Ein Lesezugriff auf die Register funktioniert immer. In gewissen Fällen kommt der Neustart auch nach mehrmaligem Schreiben des gleichen Registers und anschliessendem Lesezugriff auf dasselbe Register.
Sieht irgendwie nach überlaufendem Stack aus. Ist das Phänomen bekannt? Hat jemand einen Tip, was ich noch versuchen könnte? Der gleiche Fall tritt übrigens auch mit ModbusASCII auf.
Gruss
Hans