Quote by Avra
It's now officially in 5.04.01 version. Just update your AvrCo.
Hello Avra.
Sorry, but it don't work
The only change with the xMega_ModBusRTU and my Test-Programm is the CPU (i Use XMEGA256A3), Switchport and the BeepPort. I don't use this Options.
Here is my Test-Code (From the Demo with some little Changes):
Code
program TestModBusXMega;
Device = XMega256A3, VCC=3.3;
Define_Fuses
// Override_Fuses;
NoteBook = A;
COMport = USB;
LockBits0 = [];
FuseBits0 = [];
FuseBits1 = [];
FuseBits2 = [];
Import SysTick, SerPortC0, ModBus;
From System Import Processes, Longword, Float, Random;
Define
//>> CPU=32MHz, PeripherX4=32MHz, PeripherX2=32MHz
OSCtype = int32MHz,
PLLmul=4,
prescB=1,
prescC=1;
// overdrive;
SysTick = 10; // msec
StackSize = $0100, iData;
FrameSize = $0200, iData;
Scheduler = iData;
// if you do not have rx/tx buffer large enough, some messages may be lost
SerPortC0 = 19200, Databit8, parEven, Stop1;
// size of this buffer mainly depends on MODBUS CAPACITY
// if you expect very large messages increase this up to 254
// (if this port is used with modbus)
RxBufferC0 = 10, iData; // recommended 255, but may be lower (danger: minimum is max message length in bytes)
TxBufferC0 = 100, iData; // recommended 255, but may be lower (danger: minimum is max message length in bytes)
// Choose port and pin for RS485 line driver
// SerCtrlC0 = PortF, 0, Positive;
// port used, capacity in words, memory area, Framesize (must not exceed 240 bytes)
ModBus = SerPortC0, 40, iData, 240;
ModBusMode = RTU {ASCII}, Timer_C1;
// SwitchPort1 = PinD, $00;
// PolarityP1 = $00; // polarity
// SwitchPort2 = PinE, $00;
// PolarityP2 = $FF; // polarity
// BeepPort = PortR, 0;
// SysLEDblink = mSec300; {10..1000 msec}
// SysLEDBlink0 = PortR, 1, low; {LEDon = low level}
Uses 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;
tLights = (Light1_on = 10, light2_on); // without the prefix "rw_" this is a readonly discrete input
tLightSet = BitSet of tLights;
{--------------------------------------------------------------}
{ Const Declarations }
const
FRamBase : byte = $50;
{--------------------------------------------------------------}
{ Var Declarations }
var
{$IDATA}
ww : word;
SecTimer : SysTimer;
long_counter : longword; // needed to calc scans_per_second
/////////////
// MAPPING //
/////////////
//
// Modbus protocol is not awared of type of data transfered. It can transfer only words and bits,
// but we can map longs, floats, strings, and other stuff and then interprete transfered data.
// You can see here how to map all kind of variables to data zone that deals only with words.
// The same remapping logic must be implemented in master also (usually PC or PLC).
// To conclude, naming mapped variables and using their natural type is the most wanted behavior.
//
// All you have to do is read/write these mapped variables, and communication is transparent in a process!!!
// We use the predefined types so that the E-LAB tool "ModBusTest" can handle it
// and can build a printable list of ModBus types and corresponding addresses
// These are the predefined types. Data direction seen from the master's (client) point of view
// mb_Inp.. defines a read only type. mb_RdWr.. defines a read and write type.
//
// mb_InpB = byte; // !! always as couples
// mb_RdWrB = byte; // !! always as couples
// mb_InpW = word;
// mb_RdWrW = word;
// mb_InpI = Integer;
// mb_RdWrI = Integer;
// mb_InpW32 = longword;
// mb_RdWrW32 = longword;
// mb_InpI32 = longInt;
// mb_RdWrI32 = longInt;
// mb_InpF = Float;
// mb_RdWrF = Float;
// additional types are one-dimensional arrays of byte
// and bitsets. Bitsets are treated as Coils or DiscreteInputs, dependant of the name prefix "rw_"
// Booleans are not directly supported. They can be implemented as bytes, coils or discrete inputs
// Using the switch below forces the compiler to build a readable parameter list.
// The name "ModBuff" is mandatory !!
// The argument is the filename.pmbl
{$MODBUS MBsampleRTU}
ModBuff[@ModDPR] : record // word byte
counter1 : mb_InpW; // [00] 00..01
various_flags : tFlagsSet; // [01] 02..03 access individual bits (coils)
port_j : mb_RdWrB; // [02] 04 this is lo(ModDPR[2])
port_k : mb_RdWrB; // [02] 05 this is hi(ModDPR[2])
dummy_word0 : mb_RdWrW; // [03] 06..07
scans_per_second : mb_InpW32; // [04] 08..11 main loop executed in every second
String0 : array[0..3] of char; // [06] 12..15 only multiple of 2 possible, always R/W
voltage1 : mb_InpF; // [08] 16..19 this is float(ModDPR[8], ModDPR[9])
counter2 : mb_InpW; // [10] 20..21
counter3 : mb_InpW; // [11] 22..23
lights : tLightSet; // [12] 24..25
inverted_byte : mb_InpB; // [13] 26 this is lo(ModDPR[13])
dummy_byte0 : mb_InpB; // [13] 27 this is hi(ModDPR[13])
CompYear : mb_InpW; // [14] 28..29
CompMonth : mb_InpW; // [15] 30..31
CompDay : mb_InpW; // [16] 32..33
CompHour : mb_InpW; // [17] 34..35
CompMinute : mb_InpW; // [18] 36..37
ProjBuild : mb_InpW; // [19] 38..39
before_register_read_counter : mb_InpW32; // [20] 40..43 event counter
after_register_read_counter : mb_InpW32; // [22] 44..47 event counter
before_register_write_counter : mb_InpW32; // [24] 48..51 event counter
after_register_write_counter : mb_InpW32; // [26] 52..55 event counter
before_coil_read_counter : mb_InpW32; // [28] 56..59 event counter
after_coil_read_counter : mb_InpW32; // [30] 60..63 event counter
before_coil_write_counter : mb_InpW32; // [32] 64..67 event counter
after_coil_write_counter : mb_InpW32; // [34] 68..71 event counter
byte_0 : mb_RdWrB; // [36] 72 this is lo(ModDPR[36])
byte_1 : mb_RdWrB; // [36] 73 this is hi(ModDPR[36])
end;
//////////////////////////////////////////////////////////////////////////////
// testing with simple communication software without any additional tools: //
//////////////////////////////////////////////////////////////////////////////
//
// $01$04$00$00$00$01$31$CA - this will read 1 analog input register starting from number 0.
// $01$04$00$00$00$28$F0$14 - this will read 40 analog input registers starting from number 0.
// $01$05$00$1F$FF$00$BD$FC - this will write bit JobIsStarted to 1 (enable counting scans).
// $01$05$00$1F$00$00$FC$0C - this will write bit JobIsStarted to 0 (disable scans count).
// for more information, take a look at "MODBUS Application Protocol Specification 1.1"
{--------------------------------------------------------------}
{ functions }
procedure InitPorts;
begin
//
end;
procedure mb_BeforeRegisterRead(RegisterNumber: word);
begin
Inc(ModBuff.before_register_read_counter);
end;
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin
// initial setup
InitPorts;
ModBuff.String0[0]:= 'a';
ModBuff.String0[1]:= 'b';
ModBuff.String0[2]:= 'c';
ModBuff.String0[3]:= 'd';
mb_SetBeforeRegisterRead(@mb_BeforeRegisterRead); // initialize user's event and enable it
mb_SetModBusDevID(1); // read device address from 5 DIP switches (1..32, nice for RS485)
//SerBaud(9600); // read baud rate from 2 DIP switches (9600, 19200, 38400, 57600)
//SerParity(parEven); // read parity from 2 DIP switches (Even, Odd, None)
//SerDataBits(DataBit7); // read data bits from 1 DIP switch (7, 8)
//SerStopBits(StopBit1); // read stop bits from 1 DIP switch (1, 2)
{ 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;
Start_Processes($87);
// BeepOutLH;
// SysLEDflashAllOn;
loop // start of scan (main loop)
ModBuff.port_j:= 01;
ModBuff.port_k:= 02;
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);
ModBuff.counter2 := ModBuff.counter1;
ModBuff.counter3 := ModBuff.counter2 * 2;
Dec(ModBuff.dummy_byte0);
Toggle(ModBuff.lights, [light1_on]);
SetBit(ModBuff.lights, [light2_on], Random > 13107); // chances are 4:1 that it will be lit (65535/5)
ModBuff.inverted_byte := not ModBuff.inverted_byte;
ModBuff.voltage1 := PI + float(Random) / 100000; // randomize a little simulated voltage
if rw_job_is_started in ModBuff.various_flags then
ModBuff.scans_per_second := long_counter;
//BeepClick;
else
ModBuff.scans_per_second := 0;
endif;
long_counter := 0;
//BeepClick;
endif;
endloop; // end of scan
end TestModBusXMega.
The "E-Lab ModBus Tester" beeb only if i start the Scan, the Tester sending the ModBus RTU-Programm to the Port, but the XMega dosen't send the Answer!
The SerPort from XMega work if i use the ReadLn and WriteLn.
Can anyone try the Demo with the XMEGA256A3 ?
My AVRco Version is V5.04.03
Bye
Thorsten