📄 mb_dev.c
字号:
/******************************************************************************
*
* (c) 2004 by BECK IPC GmbH
*
*******************************************************************************
*
* Module: mb_dev.c
* Function: General modbus server functions for read and write single/multiple
coils or registers
* Implemented modbus function codes: 01, 02, 05, 15, 04, 03, 06 , 43 (only in parts)
*
* Basic functions for handle the different types of incoming
* modbus requests. Inside of the several function handlers
* the DK40/DK50/DK60 specific register/coil read/write functions
* are inserted, according to the DKxx demo modbus
* register and coil definition (see comment header at file mb_slv.c).
********************************************************************************
* Disclaimer: This program is an example and should be used as such.
* If you wish to use this program or parts of it in your application,
* you must validate the code yourself. BECK IPC GmbH can not be held
* responsible for the correct functioning or coding of this example.
*******************************************************************************
*
* $Header: mb_dev.c, 3, 02.09.2005 11:06:29, Markus Bartat$
*
******************************************************************************/
/******************************************************************************
* Includes
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <mem.h>
#include "clib.h"
#include "modbus.h"
#include "mb_dkxx.h" //device specific include file DK40 or Dk50
/******************************************************************************
* Defines
******************************************************************************/
//#define MB_DEV_DEBUG
#define MB_DEV_OBJ_MAX_ID 7 //max. number of provided object strings
//******************************************************************************
// Object ID table (function 0x2B), Object-ID equals array index
//******************************************************************************
char * mb_object_id_table[MB_DEV_OBJ_MAX_ID] = { "Beck IPC GmbH", // Vendorname
"xxxxxx", // Product code
"V1.00", // MajorMinor revision
"www.beck-ipc.com",//Vendor url
"DKxx", //Product name
"H01", // Model
"IPC@CHIP DKxx modbus slave" //Appl. name
};
/******************************************************************************/
//local helper function: Convert 16 Bit Big Endian to 16 Bit Little endian
/******************************************************************************/
static int near swap_int ( int w)
{
asm mov ax,w
asm xchg al,ah
return _AX;
}
//******************************************************************************
// Initialize the device, must be called at start of application
// Return 0: succesful
// -1: Device init error
//******************************************************************************
int mb_dev_init(void)
{
//return errorcode of device specific init function
return mb_dkxx_init();
}
//******************************************************************************
// DeInitialize the modbus device
//******************************************************************************
int mb_dev_deinit(void)
{
//return errorcode of device specific deinit/close function
return mb_dkxx_deinit();
}
/******************************************************************************
Modbus device user specific "read coil function" addressed by parameter "address":
Called by function mb_ser_process_request (mb_slv.c), if a modbus request with
function code 01h comes in.
At this example we call here our implemented DKxx read coil function from file mb_DKxx.c
For own applications, the application developer must insert his own defined modbus
coil functions, instead of the mb_dkxx_read_coil_xx functions.
Returns the return value of the device specific function for the specified address
or Exception 2 Illgal address
******************************************************************************/
int mb_read_coil_func(unsigned int address, unsigned char * value)
{
switch (address)
{
case 0: return mb_dkxx_read_coil_00(value);
case 1: return mb_dkxx_read_coil_01(value);
case 2: return mb_dkxx_read_coil_02(value);
case 3: return mb_dkxx_read_coil_03(value);
case 4: return mb_dkxx_read_coil_04(value);
case 5: return mb_dkxx_read_coil_05(value);
case 6: return mb_dkxx_read_coil_06(value);
case 7: return mb_dkxx_read_coil_07(value);
case 8: return mb_dkxx_read_coil_08(value);
case 9: return mb_dkxx_read_coil_09(value);
case 10: return mb_dkxx_read_coil_10(value);
case 11: return mb_dkxx_read_coil_11(value);
case 12: return mb_dkxx_read_coil_12(value);
case 13: return mb_dkxx_read_coil_13(value);
case 14: return mb_dkxx_read_coil_14(value);
default: return MB_ILL_DATA_ADDR ; //illegal address
}
}
/******************************************************************************
Modbus device user specific write coil function addressed by parameter address:
Called by function mb_ser_process_request (mb_slv.c), if a modbus request with
function code 05h or 0fh comes in.
At this example we call here our implemented DKxx write coil function from file DKxx.c
For own applications , the application developer must insert his own defined modbus
coil functions
******************************************************************************/
int mb_write_coil_func(unsigned int address, unsigned char value)
{
switch (address)
{
case 0: return mb_dkxx_write_coil_00(value);
case 1: return mb_dkxx_write_coil_01(value);
case 2: return mb_dkxx_write_coil_02(value);
case 3: return mb_dkxx_write_coil_03(value);
case 4: return mb_dkxx_write_coil_04(value);
case 5: return mb_dkxx_write_coil_05(value);
case 6: return mb_dkxx_write_coil_06(value);
case 7: return mb_dkxx_write_coil_07(value);
case 8: return mb_dkxx_write_coil_08(value);
case 9: return mb_dkxx_write_coil_09(value);
case 10: return mb_dkxx_write_coil_10(value);
case 11: return mb_dkxx_write_coil_11(value);
case 12: return mb_dkxx_write_coil_12(value);
case 13: return mb_dkxx_write_coil_13(value);
case 14: return mb_dkxx_write_coil_14(value);
default: return MB_ILL_DATA_ADDR ; //illegal address
}
}
/******************************************************************************
Modbus device user specific read discrete input function (02) addressed by parameter address:
Called by function mb_ser_process_request (mb_slv.c), if a modbus master request with
function code 02h comes in.
At this example we call here our implemented DKxx read coil function from file DKxx.c
For own applications , the application developer must insert his own defined modbus
read discrete input functions
Returns the return value of the device specific function for the specified address
or Exception 2 (Illegal address)
******************************************************************************/
int mb_read_discrete_inputs_func(unsigned int address, unsigned char * value)
{
switch (address)
{
case 0: return mb_dkxx_read_discr_inp_00(value);
case 1: return mb_dkxx_read_discr_inp_01(value);
case 2: return mb_dkxx_read_discr_inp_02(value);
case 3: return mb_dkxx_read_discr_inp_03(value);
case 4: return mb_dkxx_read_discr_inp_04(value);
case 5: return mb_dkxx_read_discr_inp_05(value);
case 6: return mb_dkxx_read_discr_inp_06(value);
default: return MB_ILL_DATA_ADDR ; //illegal address
}
}
/******************************************************************************
Modbus device user specific read holding register function addressed by parameter address:
Called by function mb_ser_process_request (mb_slv.c), if a modbus master(client) request with
function code 03h comes in.
At this example we call here our implemented DKxx read holding register function from file DKxx.c
For own applications , the application developer must insert his own defined modbus
holding register functions.
Returns return value of device specific function for the specified address
or Exception 2 (Illegal address)
******************************************************************************/
int mb_read_holding_register_func(unsigned int address, unsigned int * value)
{
switch (address)
{
case 0: return mb_dkxx_read_register_00(value);
case 1: return mb_dkxx_read_register_01(value);
case 2: return mb_dkxx_read_register_02(value);
case 3: return mb_dkxx_read_register_03(value);
default: return MB_ILL_DATA_ADDR ; //illegal address
}
}
/******************************************************************************
Modbus device user specific write holding register function addressed by parameter address:
Called by function mb_ser_process_request (mb_slv.c), if a modbus master(client) request with
function code 06h or 10h comes in.
At this example we call here our implemented DKxx write holding register function from file DKxx.c
For own applications , the application developer must insert his own defined modbus
holding registers functions
Returns return value of device specific function for the specified address
or Exception 2 (Illegal address)
******************************************************************************/
int mb_write_holding_register_func(unsigned int address, unsigned int value)
{
switch (address)
{
case 0: return mb_dkxx_write_register_00(value);
case 1: return mb_dkxx_write_register_01(value);
case 2: return mb_dkxx_write_register_02(value);
case 3: return mb_dkxx_write_register_03(value);
default: return MB_ILL_DATA_ADDR ; //illegal address
}
}
/******************************************************************************
Modbus device user specific read holding register function addressed by parameter address:
Called by function mb_ser_process_request (mb_slv.c), if a modbus master(client) request with
function code 04h comes in.
At this example we call here our implemented DKxx read holding register function from file DKxx.c
For own applications , the application developer must insert his own defined modbus
holding register functions.
Returns return value of device specific function for the specified address
or Exception 2 (Illegal address)
******************************************************************************/
int mb_read_input_register_func(unsigned int address, unsigned int * value)
{
switch (address)
{
case 0: return mb_dkxx_read_inp_register_00(value);
case 1: return mb_dkxx_read_inp_register_01(value);
case 2: return mb_dkxx_read_inp_register_02(value);
default: return MB_ILL_DATA_ADDR ; //illegal address
}
}
/******************************************************************************
Bit access: Called if modbus request function code == 0x01
Handle a "multiple read coils" or read discrete input request
Input parameters:
start_address : First coil address
number_of_coils : requested quantity of coils to read
Return 0: Sucessful
Output parameters: the provided storage byte_count holds quantity of coils/8 (+1 if remainder!= 0)
the provided storage coil_status holds coil bit values in the order as described
at the "Modbus application protocol specification V1.1" from modbus.org
Return!=0 is modbus errorcode (see modbus.h)
******************************************************************************/
int mb_read_coils(unsigned int start_address,
unsigned int number_of_coils,
unsigned char * byte_count,
unsigned char * coil_status )
{
int i;
int retval;
unsigned char coil_tmp,shift,byte_count_tmp;
#ifdef MB_DEV_DEBUG
printf("\r\nRead coils: start %d quantity %d",start_address, number_of_coils);
#endif
/*
Read coils from the device
If the application requires no interruption during the following read coil loop,
insert here semaphore protection or disable interrupts
*/
*byte_count = number_of_coils / 8;
if(number_of_coils % 8)
{
(*byte_count)++;
}
//Preset coil status buffer with zeros
memset(coil_status,0,*byte_count);
for(i=shift=byte_count_tmp=0;i<number_of_coils;i++)
{
retval = mb_read_coil_func(start_address + i,&coil_tmp);
if(retval == MB_NO_ERROR)
{
if(coil_tmp)
{
coil_status[byte_count_tmp]|= 1<<shift;
}
shift++;
if(shift==8)
{
byte_count_tmp++;
shift=0;
}
}
else
{
break;
}
}
//Enable interupts or release semaphore here, if they were used above the read loop
#ifdef MB_DEV_DEBUG
printf("\r\nRead coils: Return %d ",retval);
if(retval==MB_NO_ERROR)
{
printf("\r\nCoil_status: ");
for(i=0;i<*byte_count;i++)
{
printf("%02X ",coil_status[i]);
}
}
#endif
return retval;
}
/******************************************************************************
Bit access: Called if modbus request function code == 0x02
Handle a "read discrete input request"
Input parameters:
start_address : address of the first dicrete input
number_of_inputs: quantity of inputs to read
Return 0: Sucessful
Output parameters: the provided storage byte_count holds quantity of coils/8 (+1 if remainder!= 0)
the provided storage input_status holds input bit values in the order as described
at the "Modbus application protocol specification V1.1" from modbus.org
Return!=0 is modbus errorcode (see modbus.h)
******************************************************************************/
int mb_read_discrete_inputs(unsigned int start_address,
unsigned int number_of_inputs,
unsigned char * byte_count,
unsigned char * input_status )
{
int i;
int retval;
unsigned char input_tmp,shift,byte_count_tmp;
#ifdef MB_DEV_DEBUG
printf("\r\nRead discrete inputs: start %d quantity %d",start_address, number_of_inputs);
#endif
/*
Read discrete inputs from the device
If the application requires no interruption during the following read coil loop,
insert here semaphore protection or disable interrupts
*/
*byte_count = number_of_inputs / 8;
if(number_of_inputs % 8)
{
(*byte_count)++;
}
//Preset coil status buffer with zeros
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -