📄 bl2100_modbus.c
字号:
/*
BL2100使用MODBUS与组态王通讯
1、使用命令说明:
allow control via a Modbus Master controller of the following;
1. Read from/Write to digital outputs
2. Read the status of digital inputs
3. Read the Analog inputs (Cal. Data).
4. Read from/Write to the analog output channels (Cal. data).
MODBUS COMMAND FUNCTIONS USED:
01: Discrete Coil Status
01: Discrete Coil Writing
02: Discrete Input Status
03: Holding Register Status
03: Holding Register Writing
04: Input Register Status
(01: Discrete Coil Status)
Used for reading output coil status. A user defined shadow registeris required in your code which will be updated when digitaloutputs change states using the msOutWr function.
registers used:
0x00001 -> 0x00016 Digital Output 0 -> Digital Output 15
(01: Discrete Coil Writing)
Used for Writing to individual output coils, as well as updating the shadow register used in the above function msOutRd.
registers used:
0x00001 -> 0x00016 (Digital Output 0 -> Digital Output 15)
(02: Discrete Input Status)
Used for reading the state of the individual digital inputs.
registers used:
0x10001 -> 0x10024 (Digital Input 0 -> Digital Input 23)
(04: Reading from a Input Register)
For reading the individual CALIBRATED values of each adc inputs.Since Modbus deals with unsigned ints (words), and our VDC inputfunction returns a float, the function will need to store the value as two registers type casted into unsigned ints for the Modbus protocol to accept properly. How this is done must be the same for both the Master and the slave. This example shows one way to accomplish that. The Master must use the same method for decoding the two unsigned ints and convert it back to a float. A sample of this is the msWrite function that converts 2 unsigned ints into a float for use with the DAC outputs.
registers used;
0x30001 -> 0x30002 = Float val of ADC 0
0x30003 -> 0x30004 = Float val of ADC 1
0x30005 -> 0x30006 = Float val of ADC 2
0x30007 -> 0x30008 = Float val of ADC 3
0x30009 -> 0x30010 = Float val of ADC 4
0x30011 -> 0x30012 = Float val of ADC 5
0x30013 -> 0x30014 = Float val of ADC 6
0x30015 -> 0x30016 = Float val of ADC 7
0x30017 -> 0x30018 = Float val of ADC 8
0x30019 -> 0x30020 = Float val of ADC 9
0x30021 -> 0x30022 = Float val of ADC 10
(03: Writing to Holding Registers)
Will write to the DAC channels (0-3) This function will take a converted float valued (from 2 unsigned int values) and update the DAC output values (in Volts 0-10VDC). It also will update the analog output shadow register aoShad[analog output] used in the msRead function.
registers used:
0x40001 -> 0x40002 = Float val for DAC 0
0x40003 -> 0x40004 = Float val for DAC 1
0x40005 -> 0x40006 = Float val for DAC 2
0x40007 -> 0x40008 = Float val for DAC 0
*/
//2、现场使用的程序框架如下:
//*************************************************************************************
// MODBUS TCP_SERVER_STATUS.c
// Beijing Bocon, 2004
//************************************TCP_IP SETTINGS**********************************
#define TCPCONFIG 1
#define ETH_MTU 600 //maximum is 1500 bytes
#define BUFF_SIZE (ETH_MTU-40) //must be smaller than (ETH_MTU - (IP Datagram + TCP Segment))
#define TCP_BUF_SIZE ((ETH_MTU-40)*4) //sets up (ETH_MTU-40)*2 bytes for Tx & Rx buffers
#define MAX_TCP_SOCKET_BUFFERS 1 //number of sockets
#define INCOMING_IP "0.0.0.0" //except all connections
#define INCOMING_PORT 0 //except all ports
#define TIME_OUT 60000L // if in any state for more than a X msecs re-initialize
#define MY_PORT 502 // Port clients will connect to
//************************************BOARD SETTINGS**********************************
// Define the number of channels for each type of input
// Number of analog inputs/outputs.
#define ADC_AMOUNT 11 // "+1" Frequency input
#define DAC_AMOUNT 4
// Maximum VDC output allowed, If the Master tries to send a value higher
// a MS_BADDATA (0x03) err will be sent back.
#define MAX_DAC_VOLTS 10.00
// Number of digitial I/O
#define INPUT_AMOUNT 24
#define OUTPUT_AMOUNT 16
// Digital Output Shadow Registers
char acShad[OUTPUT_AMOUNT + 1];
// Analog Output Shadow Registers
float aoShad[DAC_AMOUNT + 1];
//*************************************PRINTF MACROS***********************************
#define RED "\x1b[31m" // foreground colors for printf
#define GREEN "\x1b[32m" // foreground colors for printf
#define YELLOW "\x1b[33m" // foreground colors for printf
#define BLUE "\x1b[34m" // foreground colors for printf
#define BLACK "\x1b[30m" // foreground colors for printf
#define XY 0x20 // x and y default cursor location
//*****************************MEMORY SETTINGS & LIBRARIES*****************************
#memmap xmem
#use "dcrtcp.lib"
//****************************GLOBAL VARIABLES & STRUCTURES****************************
typedef struct
{
tcp_Socket sock;
int nextstate;
int sent, rcvd, bytes;
long statetime,oseqnum,oacknum;
char buff[BUFF_SIZE];
word my_port;
}My_Socket_Type;
//***********************************FUNCTION PROTOTYPES*******************************
void My_Init_Socks(My_Socket_Type *my_socks);
int My_Rcv_Pkt(My_Socket_Type *my_sock);
int My_Snd_Pkt(My_Socket_Type *my_sock);
void My_Handler(My_Socket_Type *my_sock);
void My_Print(int i, My_Socket_Type *my_sock);
//************************************ MODBUS TCP *******************************
unsigned char coil[256]; //线圈
float reg[256]; //寄存器
float regout[256];
unsigned char response[256];
int response_len;
int CRC;
unsigned char wFunc;
unsigned char wStartHi;
unsigned char wStartLo;
unsigned char wCntHi;
unsigned char wCntLo;
unsigned char wCrcHi;
unsigned char wCrcLo;
union lsj_FC
{
float F;
char C[4];
} lsj_fc;
void SepPacket(unsigned char *pa);
//******************************************MAIN***************************************
main()
{
auto int sCount;
auto int loop;
My_Socket_Type my_socks[MAX_TCP_SOCKET_BUFFERS];
My_Init_Socks(my_socks);
// Clear the output shadow arrays at startup of this sample
memset(acShad, 0, sizeof(acShad));
memset(aoShad, 0, sizeof(aoShad));
// initialize the SBC
brdInit();
// initializing the outputs to be Sourcing.
digOutConfig(0xFFFF);
sock_init();
ifconfig( IF_ETH0,
IFS_DOWN,
IFS_IPADDR, aton("192.168.8.180"),
IFS_NETMASK, aton("255.255.255.0"),
IFS_ROUTER_SET, aton("192.168.8.202"),
IFS_UP,
IFS_END);
// If there are analog inputs required, get the cal. constants from the
// eeprom.
if (ADC_AMOUNT > 0 )
{
// read in the cal. constants.
for (loop = 0 ; loop < ADC_AMOUNT ; loop++) anaInEERd(loop);
}
// If there are analog outputs required, get the cal. constants from the
// eeprom.
if (DAC_AMOUNT > 0 )
{
// read in the cal. constants.
for (loop = 0 ; loop < DAC_AMOUNT ; loop++) anaOutEERd(loop);
}
while(1)
{
for(sCount=0;sCount<MAX_TCP_SOCKET_BUFFERS;sCount++)
{
My_Handler(&my_socks[sCount]);
My_Print(sCount,&my_socks[sCount]);
}
}
}
//*********************************MY_INIT_SOCKS***************************************
void My_Init_Socks(My_Socket_Type *my_socks)
{
int i;
for(i=0;i<MAX_TCP_SOCKET_BUFFERS;i++)
{
memset(&my_socks[i].buff,0,BUFF_SIZE);
my_socks[i].my_port = MY_PORT;
my_socks[i].nextstate = 0;
my_socks[i].oseqnum = 0L;
my_socks[i].oacknum = 0L;
my_socks[i].sent = 0;
my_socks[i].rcvd = 0;
my_socks[i].bytes = 0;
}
}
//******************************************MY_RCV_PKT*********************************
int My_Rcv_Pkt(My_Socket_Type *my_sock)
{
auto int j;
memset( my_sock->buff,0,BUFF_SIZE );
/* receive the packet */
my_sock->bytes = sock_fastread(&my_sock->sock,my_sock->buff,BUFF_SIZE);
for(j=0;j<11;j++)reg[j]=anaInVolts(j);
for(j=0;j<24;j++)coil[j]=digIn(j);
SepPacket(my_sock->buff);
switch(my_sock->bytes)
{
case -1:
return 4; // there was an error go to state 4 (NO_WAIT_CLOSE)
case 0:
return 2; // connection is okay, but no data received
default:
(my_sock->statetime) = MS_TIMER+TIME_OUT; // reset time to be in the SEND state
my_sock->rcvd += my_sock->bytes;
return 3; //now go to state 3 (SEND)
}
}
//********************************************MY_SND_PKT*******************************
int My_Snd_Pkt(My_Socket_Type *my_sock)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -