Hallo rolf,
ich habe ein großes Problem, ich nutze schon eine ganze Zeit den MODBUS-Treiber unter ATMEGA, da lief er bis jetzt ohne Probleme.
Aber unter meiner neuen XMEGA Leiterplatte tut sich nix, er reagiert nicht im geringsten auf MODBUS Anfragen. Gibt es da ein BUG?
Hardware kann ich ausschließen, da beide RS485 mit ControlPin ohne Probleme ohne MODBUS Daten senden / empfangen. Nur der Modbus-Treiber reagiert einfach nicht.
Da sich der Treiber selbst um das Control-PIN kümmert habe ich da ja keinen Einfluss drauf.
Evtl. schaffe ich es Heute nochmal mit dem Oszi den PIN zu Messen, ich könnte mir vorstellen, das der Treiber den PIN nicht umschaltet. Aber da ich die Steuerung mit einer Testsoftware fertig machen muss (Morgen ist EMV-Prüftermin) habe ich Heute nicht mehr so viel Zeit. Ich weiß immer in der letzten Minute . Aber das ist doch immer so
Hier ist ein kleines Testprogramm:
Am besten kannst Du das mit dem Tool vom www.Modbusdriver.com testen, ist kostenlos und einfach zum testen.
-b = Baudrate
-p = Par.
-m = Modbusprotokoll
-a = Slaveadresse
-r = Registerstart
-c = Anzahl der Daten
und dann noch der COMPORT
Gruß
Thorsten
ich habe ein großes Problem, ich nutze schon eine ganze Zeit den MODBUS-Treiber unter ATMEGA, da lief er bis jetzt ohne Probleme.
Aber unter meiner neuen XMEGA Leiterplatte tut sich nix, er reagiert nicht im geringsten auf MODBUS Anfragen. Gibt es da ein BUG?
Hardware kann ich ausschließen, da beide RS485 mit ControlPin ohne Probleme ohne MODBUS Daten senden / empfangen. Nur der Modbus-Treiber reagiert einfach nicht.
Da sich der Treiber selbst um das Control-PIN kümmert habe ich da ja keinen Einfluss drauf.
Evtl. schaffe ich es Heute nochmal mit dem Oszi den PIN zu Messen, ich könnte mir vorstellen, das der Treiber den PIN nicht umschaltet. Aber da ich die Steuerung mit einer Testsoftware fertig machen muss (Morgen ist EMV-Prüftermin) habe ich Heute nicht mehr so viel Zeit. Ich weiß immer in der letzten Minute . Aber das ist doch immer so
Hier ist ein kleines Testprogramm:
Code
program MODBUS_RTU;
{$NOSHADOW}
{ $WG} {global Warnings off}
Device = xmega256A3U, VCC = 3.3;
//Device = xmega128A1U, VCC = 3.3;
Define_Fuses
Override_Fuses;
NoteBook = D;
COMport = USB;
LockBits0 = [];
FuseBits0 = [];
FuseBits1 = [];
FuseBits2 = []; // mandatory !!
// Brown-out is obligatory with USB !!!
FuseBits5 = [BODACT0, BodLevel0, BodLevel1, BodLevel2];
ProgFlash = true; // or false – program Flash
ProgEEprom= FALSE; // or false – program EEprom
AutoRelease = true; // or false – Release Target // Wichtig für Programmierung über UPP !!
Import SysTick, SerPortC0, SerPortD0, ModBus{, TWI_E, TWI_C};
From System Import Processes, Longword, Float, Random;
From ModBus import {MOD_Radio};
Define
//OSCtype = int2MHz, PLLmul = 16, prescB = 1, prescC = 1;
OSCtype = int32MHz,
PLLmul=4,
prescB=1,
prescC=1;
SysTick = 10; // msec
StackSize = $0255, iData;
FrameSize = $0255, iData;
Scheduler = iData;
// ModBus
SerPortD0 = 19200, Stop1; {19200 Baud, 1Stopbit}
RxBufferD0 = 254, iData;
TxBufferD0 = 100, iData;
SerCtrlD0 = PortB, 0, negative; {control line for RS485 driver}
ModBus = SerPortD0, 40, iData, 240;
ModBusMode = {ASCII;} RTU, Timer_D0;
// RS485 Leserbus / Modbus
SerPortC0 = 19200, Stop1;
RxBufferC0 = 255, iData;
TxBufferC0 = 100, iData;
SerCtrlC0 = PortA, 6, negative; {control line for RS485 driver}
// TWI
// TWIprescE = TWI_BR400; //TWI speed interner I2C
// TWIprescC = TWI_BR400; //TWI speed Exp3 I2C
Uses {ModBusServASCII} ModBusServRTU;
Implementation
{$IDATA}
{--------------------------------------------------------------}
{ Type Declarations }
type
tVar_Flags = (rw_job_is_started = 15); // use the prefix "rw_" to define a coil = read/write
tFlagsSet = BitSet of tVar_Flags;
{--------------------------------------------------------------}
{ Const Declarations }
const
{--------------------------------------------------------------}
{ Var Declarations }
var
{$IDATA}
ww : word;
SecTimer : SysTimer;
long_counter : longword; // needed to calc scans_per_second
/////////////
// MAPPING //
/////////////
//
{$MODBUS ModBusRT_Test}
ModBuff[@ModDPR] : record // word byte
counter1 : mb_InpW; // [02] 02..03
scans_per_second : mb_InpW32; // [04] 04..07 main loop executed in every second
CompYear : mb_InpW; // [08] 08..09
CompMonth : mb_InpW; // [10] 10..11
CompDay : mb_InpW; // [12] 12..13
CompHour : mb_InpW; // [14] 14..15
CompMinute : mb_InpW; // [16] 16..17
ProjBuild : mb_InpW; // [18] 18..19
counter2 : mb_InpW; // [20] 20..21
counter3 : mb_InpW; // [22] 22..23
before_register_read_counter : mb_InpW32; // [24] 24..27 event counter
various_flags : tFlagsSet; // [00] 00..01 access individual bits (coils)
end;
iDebug : LONGINT;
{--------------------------------------------------------------}
{ functions }
procedure InitPorts;
begin
end;
procedure mb_BeforeRegisterRead(RegisterNumber: word);
begin
Inc(ModBuff.before_register_read_counter);
inc(ModBuff.counter3);
end;
procedure DebugOut( OutStr : String[59] );
var
xc : integer;
begin
Writeln(SerOutC0,OutStr);
end; //Ende Debug Out
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin
// initial setup
InitPorts;
mb_SetBeforeRegisterRead(@mb_BeforeRegisterRead); // Setze User Event und starte es...
mb_SetModBusDevID(1); // Setze die DEVICE ID
{ process init }
//Priority(Main_Proc, 2);
//Priority(mb_Communication, 2);
//EnableInts;
ModBuff.CompYear := word(COMPILEYEAR);
ModBuff.CompMonth := word(COMPILEMONTH);
ModBuff.CompDay := word(COMPILEDAY);
ModBuff.CompHour := word(COMPILEHOUR);
ModBuff.CompMinute := word(COMPILEMINUTE);
ModBuff.ProjBuild := PROJECTBUILD;
DebugOut('Start Process $87...');
Start_Processes($87);
DebugOut('Sys start...');
loop // start of scan (main loop)
if rw_job_is_started in ModBuff.various_flags then // if Master set this bit then he wants to know how many scans per second can we achieve
Inc(long_counter);
endif;
if isSysTimerZero(SecTimer) then
SetSysTimer(SecTimer, 1000 div SysTick); // 1 second
// we will simulate reading values from some real devices here
//
Inc(ModBuff.counter1);
Inc(ModBuff.counter2);
ModBuff.counter3:= ModBuff.counter2 * 2;
if rw_job_is_started in ModBuff.various_flags then
ModBuff.scans_per_second := long_counter;
else
ModBuff.scans_per_second := 0;
endif;
long_counter := 0;
mb_SetBeforeRegisterRead(@mb_BeforeRegisterRead); // initialize user's event and enable it
endif;
// Info Ausgabe
inc(iDebug);
if iDebug > 200000
then
iDebug:= 0;
DebugOut('200.000 zu ende...');
DebugOut('Read Counter: '+ LongToStr(ModBuff.before_register_read_counter));
endif;
endloop; // end of scan
end MODBUS_RTU.
{$NOSHADOW}
{ $WG} {global Warnings off}
Device = xmega256A3U, VCC = 3.3;
//Device = xmega128A1U, VCC = 3.3;
Define_Fuses
Override_Fuses;
NoteBook = D;
COMport = USB;
LockBits0 = [];
FuseBits0 = [];
FuseBits1 = [];
FuseBits2 = []; // mandatory !!
// Brown-out is obligatory with USB !!!
FuseBits5 = [BODACT0, BodLevel0, BodLevel1, BodLevel2];
ProgFlash = true; // or false – program Flash
ProgEEprom= FALSE; // or false – program EEprom
AutoRelease = true; // or false – Release Target // Wichtig für Programmierung über UPP !!
Import SysTick, SerPortC0, SerPortD0, ModBus{, TWI_E, TWI_C};
From System Import Processes, Longword, Float, Random;
From ModBus import {MOD_Radio};
Define
//OSCtype = int2MHz, PLLmul = 16, prescB = 1, prescC = 1;
OSCtype = int32MHz,
PLLmul=4,
prescB=1,
prescC=1;
SysTick = 10; // msec
StackSize = $0255, iData;
FrameSize = $0255, iData;
Scheduler = iData;
// ModBus
SerPortD0 = 19200, Stop1; {19200 Baud, 1Stopbit}
RxBufferD0 = 254, iData;
TxBufferD0 = 100, iData;
SerCtrlD0 = PortB, 0, negative; {control line for RS485 driver}
ModBus = SerPortD0, 40, iData, 240;
ModBusMode = {ASCII;} RTU, Timer_D0;
// RS485 Leserbus / Modbus
SerPortC0 = 19200, Stop1;
RxBufferC0 = 255, iData;
TxBufferC0 = 100, iData;
SerCtrlC0 = PortA, 6, negative; {control line for RS485 driver}
// TWI
// TWIprescE = TWI_BR400; //TWI speed interner I2C
// TWIprescC = TWI_BR400; //TWI speed Exp3 I2C
Uses {ModBusServASCII} ModBusServRTU;
Implementation
{$IDATA}
{--------------------------------------------------------------}
{ Type Declarations }
type
tVar_Flags = (rw_job_is_started = 15); // use the prefix "rw_" to define a coil = read/write
tFlagsSet = BitSet of tVar_Flags;
{--------------------------------------------------------------}
{ Const Declarations }
const
{--------------------------------------------------------------}
{ Var Declarations }
var
{$IDATA}
ww : word;
SecTimer : SysTimer;
long_counter : longword; // needed to calc scans_per_second
/////////////
// MAPPING //
/////////////
//
{$MODBUS ModBusRT_Test}
ModBuff[@ModDPR] : record // word byte
counter1 : mb_InpW; // [02] 02..03
scans_per_second : mb_InpW32; // [04] 04..07 main loop executed in every second
CompYear : mb_InpW; // [08] 08..09
CompMonth : mb_InpW; // [10] 10..11
CompDay : mb_InpW; // [12] 12..13
CompHour : mb_InpW; // [14] 14..15
CompMinute : mb_InpW; // [16] 16..17
ProjBuild : mb_InpW; // [18] 18..19
counter2 : mb_InpW; // [20] 20..21
counter3 : mb_InpW; // [22] 22..23
before_register_read_counter : mb_InpW32; // [24] 24..27 event counter
various_flags : tFlagsSet; // [00] 00..01 access individual bits (coils)
end;
iDebug : LONGINT;
{--------------------------------------------------------------}
{ functions }
procedure InitPorts;
begin
end;
procedure mb_BeforeRegisterRead(RegisterNumber: word);
begin
Inc(ModBuff.before_register_read_counter);
inc(ModBuff.counter3);
end;
procedure DebugOut( OutStr : String[59] );
var
xc : integer;
begin
Writeln(SerOutC0,OutStr);
end; //Ende Debug Out
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin
// initial setup
InitPorts;
mb_SetBeforeRegisterRead(@mb_BeforeRegisterRead); // Setze User Event und starte es...
mb_SetModBusDevID(1); // Setze die DEVICE ID
{ process init }
//Priority(Main_Proc, 2);
//Priority(mb_Communication, 2);
//EnableInts;
ModBuff.CompYear := word(COMPILEYEAR);
ModBuff.CompMonth := word(COMPILEMONTH);
ModBuff.CompDay := word(COMPILEDAY);
ModBuff.CompHour := word(COMPILEHOUR);
ModBuff.CompMinute := word(COMPILEMINUTE);
ModBuff.ProjBuild := PROJECTBUILD;
DebugOut('Start Process $87...');
Start_Processes($87);
DebugOut('Sys start...');
loop // start of scan (main loop)
if rw_job_is_started in ModBuff.various_flags then // if Master set this bit then he wants to know how many scans per second can we achieve
Inc(long_counter);
endif;
if isSysTimerZero(SecTimer) then
SetSysTimer(SecTimer, 1000 div SysTick); // 1 second
// we will simulate reading values from some real devices here
//
Inc(ModBuff.counter1);
Inc(ModBuff.counter2);
ModBuff.counter3:= ModBuff.counter2 * 2;
if rw_job_is_started in ModBuff.various_flags then
ModBuff.scans_per_second := long_counter;
else
ModBuff.scans_per_second := 0;
endif;
long_counter := 0;
mb_SetBeforeRegisterRead(@mb_BeforeRegisterRead); // initialize user's event and enable it
endif;
// Info Ausgabe
inc(iDebug);
if iDebug > 200000
then
iDebug:= 0;
DebugOut('200.000 zu ende...');
DebugOut('Read Counter: '+ LongToStr(ModBuff.before_register_read_counter));
endif;
endloop; // end of scan
end MODBUS_RTU.
Am besten kannst Du das mit dem Tool vom www.Modbusdriver.com testen, ist kostenlos und einfach zum testen.
Code
modpoll.exe -b 19200 -p none -m rtu -a 1 -r 1 -c 5 COM1
-b = Baudrate
-p = Par.
-m = Modbusprotokoll
-a = Slaveadresse
-r = Registerstart
-c = Anzahl der Daten
und dann noch der COMPORT
Gruß
Thorsten