📄 mmbl21xx.c
字号:
/* SAMPLE PROGRRAM **********************************************************
SAMPLE NAME: MM_BL21XX.C
DESCRIPTION: Modbus Master Sample program. Written for use with
the BL2100 series SBC's, Though it can be modified
for any rabbit device with an RS232/RS485 channel.
USER INSTRUCTIONS: Run The MS_BL21XX.C sample program on the slave device.
Setup to Match the slaves io and protocol settings
with the user configuration area macros below.
The Following sample is setup to read/write
4 digital outputs
4 digital inputs
4 analog outputs
4 analog inputs
The analog channels are setup to send/receive
a floating point representation. It will use
2 registers per channel and convert from/to
floating point values.
The Slave program is setup to use all of the BL21xx
resources.
The following modbus registers are used for this
sample;
0x10001 -> 0x10004 Output Coils
0x20001 -> 0x20004 Input Status
0x30001 -> 0x30008 Analog Output Writing
2 regs per converted from float
0x40001 -> 0x40008 Analog Input Status
2 regs per converted to (float)
END SAMPLE DESCRIPTION *******************************************************/
/*============================================================================*\
USER CONFIGURATION AREA
\*============================================================================*/
// Defines the Baudrate to use
#define MODBUS_BAUDRATE 9600
// Defines the Protocol. 0 = ASCII, 1 = RTU
#define MODBUS_PROTOCOL 1
// Defines the ms output delay between changes
#define MODBUS_OUTPUT_DELAY 500
/*============================================================================*/
// Set the variable class to auto
#class auto
// If not using separate I & D then move as much code into xmem as possible
#ifndef __SEPARATE_INST_DATA__
#memmap xmem
#endif
// Modbus Master library
#use "mmz_rab.lib"
// Setup serial port D in/out serial buffers.
#define DINBUFSIZE 255
#define DOUTBUFSIZE 255
// Defines the Serial port type. 0 = RS485, 1 = RS232
#define MODBUS_SERIAL 0
// Defines the number of Digital outputs on the slaves
#define MODBUS_DIGITAL_OUTPUTS 4
// Defines the Number of Digital inputs on the slaves
#define MODBUS_DIGITAL_INPUTS 4
// Defines the number of analog inputs on the slaves
#define MODBUS_ANALOG_INPUTS 4
// Defines the number of analog outputs on the slaves
#define MODBUS_ANALOG_OUTPUTS 4
#define MODBUS_SLAVES_COUNT 1
// for display purposes only
const char *onOff[] =
{
"LOW ",
"HIGH",
};
// Slave Data structure
typedef struct
{
// Slaves address
int addr;
// Slaves current digital output status
int digOutShadow[MODBUS_DIGITAL_OUTPUTS+1];
// Slaves current digital input status
int digInShadow[MODBUS_DIGITAL_INPUTS+1];
// Slaves current analog output status
float anaOutShadow[MODBUS_ANALOG_OUTPUTS+1];
// Slaves current analog input status
float anaInShadow[MODBUS_ANALOG_INPUTS+1];
// Last error detected in the modbus transactions
int Errors;
} _mSlaves;
// 1 structure per slave
_mSlaves mSlaves[MODBUS_SLAVES_COUNT+1];
/*============================================================================*\
MODBUS FUNCTION (SEE FUNCTION DESCRIPTION FOR DETAILS)
\*============================================================================*/
nodebug
void mmDrx (void)
{
while (serDwrUsed() || BitRdPortI(SDSR,2) || BitRdPortI(SDSR,3));
ser485Rx();
serDrdFlush();
}
nodebug
void mmDtx()
{
ser485Tx();
}
nodebug
int mmDopen(unsigned long qBaud)
{
if (serDopen(qBaud))
{
serDparity(PARAM_EPARITY);
serDdatabits(PARAM_8BIT);
serMode(0);
return 1;
}
return 0;
}
/*==========================================================================*\
Application specific functions with modbus functionality
\*==========================================================================*/
// For reading the status of the slaves digital outputs
int readOutputs( _mSlaves *Slave )
{
static int retval;
static int outs;
costate
{
retval = 0;
// Send a Coil Read command, and wait for either a reply,
// or a timeout err.
waitfor( (Slave -> Errors = \
mmOutRd(Slave -> addr,
0x0000,
MODBUS_DIGITAL_OUTPUTS,
&outs)
) != MM_BUSY );
// if the reply from the slave was good, store the results
if (Slave -> Errors== MM_OK)
{
// copying the results for the read to the shadow registers
Slave -> digOutShadow[0] = bit(&outs,0);
Slave -> digOutShadow[1] = bit(&outs,1);
Slave -> digOutShadow[2] = bit(&outs,2);
Slave -> digOutShadow[3] = bit(&outs,3);
retval = 1;
}
// if the reply was bad, return the bad reply code
// (codes are located in the mm_rab.lib
else retval = Slave -> Errors;
}
return (retval);
}
// For reading the status of the slaves digital inputs
int readInputs(_mSlaves *Slave )
{
static int retval;
static int ins;
costate
{
retval = 0;
// Send a Input Read command, and wait for either a reply,
// or a timeout err.
waitfor( (Slave -> Errors = \
mmIn ( Slave -> addr,
0x0000,
MODBUS_DIGITAL_INPUTS,
&ins)
) != MM_BUSY );
// if the reply from the slave was good, store the results
if (Slave -> Errors == MM_OK)
{
// copying the results for the read to the shadow registers
Slave -> digInShadow[0] = bit(&ins,0);
Slave -> digInShadow[1] = bit(&ins,1);
Slave -> digInShadow[2] = bit(&ins,2);
Slave -> digInShadow[3] = bit(&ins,3);
retval = 1;
}
else retval = Slave -> Errors ;
}
// if the reply was bad, return the bad reply code
// (codes are located in the mm_rab.lib
return (retval);
}
// For reading the status of the slaves analog inputs
// Inputs will come in as two registers, and then converted to float values
int readAnaInputs( _mSlaves *Slave)
{
static int retval;
static int cnt;
static unsigned int anaRegs[1+MODBUS_ANALOG_INPUTS * 2];
costate
{
retval = 0;
// Send a Read Input Register command.
waitfor( (Slave -> Errors = \
mmInput( Slave -> addr,
0x0000,
MODBUS_ANALOG_INPUTS * 2,
&anaRegs[0])
) != MM_BUSY );
if (Slave -> Errors == MM_OK)
{
cnt = 0;
for (cnt = 0 ; cnt <MODBUS_ANALOG_INPUTS; cnt++)
{
Slave ->anaInShadow[cnt] = *(float*)&anaRegs[(cnt*2)];
}
retval = 1 ;
}
else retval = Slave -> Errors ;
}
return retval;
}
// for writing to the digital outputs.
//
int writeOutputs(_mSlaves *Slave)
{
static int retval;
static long del;
static char outs;
#GLOBAL_INIT {del = 0;}
costate
{
retval = 0;
if ( del < MS_TIMER)
{
if (Slave ->digOutShadow[0] == 1)
outs = 0;
else
{
outs = 0xFF;
}
waitfor( (Slave -> Errors = mmForceCoils(Slave -> addr,
0x0000,
MODBUS_DIGITAL_OUTPUTS,
&outs ) )!= MM_BUSY);
if (Slave -> Errors == MM_OK) retval = 1;
else retval = Slave -> Errors ;
del = MS_TIMER + MODBUS_OUTPUT_DELAY;
}
else
{
retval = 1;
}
}
return retval;
}
// For reading the status of the slaves analog outputs
// Output values are floats, and will be converted to two integer registers
// before sending to the slaves
writeAnaOut (_mSlaves *Slave)
{
static int retval;
static unsigned int anaRegs[2];
static int cnt;
static long del;
#GLOBAL_INIT {del = 0;}
costate
{
if (del < MS_TIMER)
{
retval = 0;
for (cnt = 0 ; cnt < MODBUS_ANALOG_OUTPUTS+1 ; cnt++)
{
if (Slave -> anaOutShadow[cnt] < 8.75 )
Slave -> anaOutShadow[cnt] += 1.25;
else Slave -> anaOutShadow[cnt] = 0.00;
*(float*) &anaRegs[0] = Slave -> anaOutShadow[cnt];
waitfor( (Slave -> Errors = \
mmPresetRegs(Slave -> addr,
0x0000 + (cnt * 2),
2,
anaRegs
) ) != MM_BUSY);
}
if (Slave -> Errors == MM_OK)
{
retval = 1;
}
else retval = Slave -> Errors ;
del = MS_TIMER + MODBUS_OUTPUT_DELAY;
}
else
{
retval = 1;
}
}
return retval;
}
// The following are for display purposes only
void DispStr(int x, int y, char *s)
{
x += 0x20;
y += 0x20;
printf ("\x1B=%c%c%s", x, y, s);
}
int updateInputs(_mSlaves *Slave)
{
char buff[100];
sprintf(buff," %s %s %s %s",
onOff[Slave -> digInShadow[0]],
onOff[Slave -> digInShadow[1]],
onOff[Slave -> digInShadow[2]],
onOff[Slave -> digInShadow[3]]);
DispStr(20,10,buff);
return 1;
}
int updateOutputs(_mSlaves *Slave)
{
char buff[100];
sprintf(buff," %s %s %s %s",
onOff[Slave -> digOutShadow[0]],
onOff[Slave -> digOutShadow[1]],
onOff[Slave -> digOutShadow[2]],
onOff[Slave -> digOutShadow[3]]);
DispStr(20,14,buff);
return 1;
}
int updateAnaIns(_mSlaves *Slave)
{
char buff[100];
sprintf(buff,"%5.2f %5.2f %5.2f %5.2f",
Slave ->anaInShadow[0],
Slave ->anaInShadow[1],
Slave ->anaInShadow[2],
Slave ->anaInShadow[3]
);
DispStr(20,18,buff);
return 1;
}
main ()
{
brdInit();
memset (mSlaves,0x00,sizeof(mSlaves) );
#if (MODBUS_PROTOCOL)
mmrDinit(MODBUS_BAUDRATE);
#else
mmaDinit(MODBUS_BAUDRATE);
#endif
// Set the Slave address
mSlaves[1].addr = 1;
// display the title screen
DispStr(20,2," MODBUS MASTER SAMPLE PROGRAM");
DispStr(20,4," CHAN CHAN CHAN CHAN");
DispStr(20,5," 0 1 2 3 ");
DispStr(20,6,"----------------------------------------");
DispStr(20,8," DIGITAL OUTPUTS ");
DispStr(20,9,"----------------------------------------");
DispStr(20,12," DIGITAL INPUTS ");
DispStr(20,13,"---------------------------------------");
DispStr(20,16," ANALOG INPUTS ");
DispStr(20,17,"---------------------------------------");
for (;;)
{
costate
{
// Write to the output coils
waitfor( writeOutputs(&mSlaves[1]));
// Write to the analog output channels
waitfor( writeAnaOut(&mSlaves[1]));
// Read the output coil status
waitfor( readOutputs(&mSlaves[1]));
// Read the input status
waitfor( readInputs(&mSlaves[1]));
// Read the analog input channels
waitfor( readAnaInputs(&mSlaves[1]));
// Display the output status
waitfor( updateOutputs(&mSlaves[1]));
// Display the input status
waitfor( updateInputs(&mSlaves[1]));
// Display the analog input status
waitfor( updateAnaIns(&mSlaves[1]));
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -