📄 myprotocol.c
字号:
case MODBUS_Read_Holding_Registers:
address=ntohs(pHdr->address);
size=ntohs(pHdr->u.size);
bytes = size*2;
if (myProtocolDebug)
logMsg ("Modbus Request MODBUS_Read_Holding_Registers address=%hu size=%hu bytes=%hu\n", address, size, (int)bytes, 4, 5, 6);
if (((address+size) > NUMBER_OF_HOLDING_REGISTERS)
|| (pProtoCtrl->bufferSize < 6)
|| (bytes > 256) )
{
modbusSendError(pProtoCtrl,0x02);
break;
}
pProtoCtrl->pBuffer[2] = (uchar_t)bytes;
#if _WHY_BYTE_ORDER==_BIG_ENDIAN
bcopy((char*)&holdingRegisters[address],&(pProtoCtrl->pBuffer[3]),bytes);
#else
data = (ushort_t *)&pProtoCtrl->pBuffer[3];
/* align if necessary */
for (count=0;count<size;count++)
{
data[count]= htons(holdingRegisters[address+count]);
}
#endif
/* transmit reply */
pProtoCtrl->bufferSize = 3+ bytes;
break;
case MODBUS_Read_Input_Registers:
if (myProtocolDebug)
logMsg ("Modbus Request MODBUS_Read_Input_Registers\n", 1, 2, 3, 4, 5, 6);
address=ntohs(pHdr->address);
size=ntohs(pHdr->u.size);
bytes = size*2;
if ( ((address+size) > NUMBER_OF_INPUT_REGISTERS)
|| (pProtoCtrl->bufferSize < 6)
|| (bytes > 256) )
{
modbusSendError(pProtoCtrl,0x02);
break;
}
pProtoCtrl->pBuffer[2] = (uchar_t)bytes;
#if _WHY_BYTE_ORDER==_BIG_ENDIAN
bcopy((char*)&inputRegisters[address],&(pProtoCtrl->pBuffer[3]),bytes);
#else
/* align if necessary */
data = (ushort_t *)&pProtoCtrl->pBuffer[3];
/* align if necessary */
for (count=0;count<size;count++)
{
data[count]= htons(holdingRegisters[address+count]);
}
#endif
/* transmit reply */
pProtoCtrl->bufferSize = 3+ bytes;
break;
case MODBUS_Write_Single_Coil:
if (myProtocolDebug)
logMsg ("Modbus Request MODBUS_Write_Single_Coil\n", 1, 2, 3, 4, 5, 6);
address=ntohs(pHdr->address);
if ((address > NUMBER_OF_COILS )
|| (pProtoCtrl->bufferSize < 6)
|| (pProtoCtrl->pBuffer[4] != 0x00))
{
modbusSendError(pProtoCtrl,0x02);
break;
}
shift=address%8;
switch( pProtoCtrl->pBuffer[3] )
{
case 0xFF:
mask = (0x0001<<shift);
coils[address/8]|= mask;
break;
case 0x00:
mask = ~(0x0001<<shift);
coils[address/8]&= mask;
break;
default:
modbusSendError(pProtoCtrl,0x03);
goto sendIt;
}
/* transmit reply */
pProtoCtrl->bufferSize = 6;
break;
case MODBUS_Write_Single_Register:
if (myProtocolDebug)
logMsg ("Modbus Request MODBUS_Write_Single_Register\n", 1, 2, 3, 4, 5, 6);
address=ntohs(pHdr->address);
if ((address > NUMBER_OF_HOLDING_REGISTERS )
|| (pProtoCtrl->bufferSize < 6))
{
modbusSendError(pProtoCtrl,0x02);
break;
}
holdingRegisters[address] = ntohs(pHdr->u.data);
/* transmit reply */
pProtoCtrl->bufferSize = 6;
break;
case MODBUS_Write_Multiple_registers:
address=ntohs(pHdr->address);
size=ntohs(pHdr->u.size);
bytes = pHdr->bytes;
if (myProtocolDebug)
logMsg ("Modbus Request MODBUS_Write_Multiple_registers address=%d size=%d bytes=%d\n", address, size, bytes, 4, 5, 6);
if (((address+size) > NUMBER_OF_HOLDING_REGISTERS)
|| (pProtoCtrl->bufferSize < 7+bytes)
|| (size*2 != bytes ) )
{
modbusSendError(pProtoCtrl,0x02);
break;
}
#if _WHY_BYTE_ORDER==_BIG_ENDIAN
bcopy(&(pProtoCtrl->pBuffer[7]),(char*)&holdingRegisters[address],bytes);
#else
/* align if necessary */
data = (ushort_t *)&pProtoCtrl->pBuffer[7];
/* align if necessary */
for (count=0;count<size;count++)
{
holdingRegisters[address+count]=ntohs(data[count]);
}
#endif
/* transmit reply */
pProtoCtrl->bufferSize = 6;
break;
case MODBUS_Read_Device_Identification:
case MODBUS_Mask_Write_Register:
case MODBUS_Read_Write_Multiple_registers:
case MODBUS_Read_File_Record:
case MODBUS_Write_Multiple_Coils:
default:
/* send not supported error */
modbusSendError(pProtoCtrl,0x01);
break;
}
sendIt:
myProtocolTx(
pProtoCtrl->pCookie,
pProtoCtrl->pBuffer,
pProtoCtrl->bufferSize,
pProtoCtrl->returnAddress
);
/* make sure the buffer is free */
pProtoCtrl->busy = FALSE;
return (TRUE);
}
void modbusSendError
(
MODBUS_PROTO_CTRL * pProtoCtrl,
uchar_t errornum
)
{
if (myProtocolDebug)
logMsg ("Modbus Request Sent an ERROR\n", 1, 2, 3, 4, 5, 6);
pProtoCtrl->pBuffer[1] |= MODBUS_ERROR;
pProtoCtrl->pBuffer[2] = errornum;
pProtoCtrl->bufferSize = 3;
}
/******************************************************************************
*
* modbus - a command line interface for the modbus master (or client)
*
* This function provides a interface to the protocol for demostration purposes.
* The format of the command is
*
* modbus read|write points type address@host [data1] [data2] .. [dataN]
*
* dataX, points, and address are unsigned integers
* type is any one of the following
* coils (1 bit read/write values)
* inputs (1 bit read only values)
* holding (16 bit read/write holding registers)
* registers (16 bit read only input registers)
* ID (Device identification string)
*
* RETURNS: OK or ERROR, indicating command syntax only,
* communication errors and response are logged to thew consol
*
*
*/
int modbus(
char * rwStr,
unsigned int points,
char * typeStr,
char * addressAtHost,
...)
{
#define COIL_TYPE 0
#define INPUT_TYPE 1
#define HOLDING_TYPE 2
#define REGISTER_TYPE 3
#define ID_TYPE 4
#define MAX_SIZE 512
va_list vaList; /* traverses argument list */
char * pHost;
char sendBuf[270];
MODBUS_HEADER * pHdr = (MODBUS_HEADER * )sendBuf;
int destInetAddr;
unsigned int modbusAddr;
int type,requestSize,count;
volatile ushort_t data; /* made volatile so it doesn't get optimised out */
ushort_t * pData;
char mac[7];
static MODBUS_PROTO_CTRL * pProtoCtrl;
static BOOL init = FALSE;
if(NULL== rwStr)
goto printSyntax;
if( 0 == points)
{
printf("ERROR points must be > 0\n");
goto printSyntax;
}
if( NULL ==( pHost = strchr(addressAtHost,'@')))
{
printf("ERROR addess@host|IP must contain '@'\n");
goto printSyntax;
}
pHost++;
sscanf(pHost,"%2hx",&data);mac[0]=(uchar_t)data;
sscanf(pHost,"%*3c%2hx",&data);mac[1]=(uchar_t)data;
sscanf(pHost,"%*6c%2hx",&data);mac[2]=(uchar_t)data;
sscanf(pHost,"%*9c%2hx",&data);mac[3]=(uchar_t)data;
sscanf(pHost,"%*12c%2hx",&data);mac[4]=(uchar_t)data;
sscanf(pHost,"%*15c%2hx",&data);mac[5]=(uchar_t)data;
/* printf("%02x:%02x:%02x:%02x:%02x:%02x\n",(int)mac[0],(int)mac[1],
(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); */
if (0==strncmp( typeStr, "coil", 4))
type = COIL_TYPE;
else if (0==strncmp( typeStr, "input", 5))
type = INPUT_TYPE;
else if (0==strncmp( typeStr, "hold", 4))
type = HOLDING_TYPE;
else if (0==strncmp( typeStr, "reg", 3))
type = REGISTER_TYPE;
else if (0==strncmp( typeStr, "ID", 2))
type = ID_TYPE;
else goto printSyntax;
pHdr->type = MODBUS_REQUEST; /* identify message as comming from Master */
pHdr->address = htons((ushort_t)atoi(addressAtHost)); /* parse the address (the client checks for illegal values) */
if (0==strncmp( rwStr, "read", 4))
{
switch(type)
{
case COIL_TYPE:
pHdr->function = MODBUS_Read_Coils;
pHdr->u.size = htons(points);
requestSize = 6;
break;
case INPUT_TYPE:
pHdr->function = MODBUS_Read_Discrete_Inputs;
pHdr->u.size = htons(points);
requestSize = 6;
break;
case HOLDING_TYPE:
pHdr->function = MODBUS_Read_Holding_Registers;
pHdr->u.size = htons(points);
requestSize = 6;
break;
case REGISTER_TYPE:
pHdr->function = MODBUS_Read_Input_Registers;
pHdr->u.size = htons(points);
requestSize = 6;
break;
case ID_TYPE:
pHdr->function = MODBUS_Read_Input_Registers;
sendBuf[2] = 0x0E;
if (points == 1)
sendBuf[3] = 0x04; /* individual items */
else
sendBuf[3] = 0x03; /* stream access, all item types */
sendBuf[4] = (uchar_t)atoi(addressAtHost); /* first item to get */
requestSize = 5;
break;
}
}
else if (0==strncmp( rwStr, "write", 4))
{
va_start (vaList, addressAtHost);
switch(type)
{
case COIL_TYPE:
if (points == 1)
{
pHdr->function = MODBUS_Write_Single_Coil;
data = va_arg (vaList, ushort_t);
if (data)
sendBuf[4] = 0xFF;
else
sendBuf[4] = 0x00;
sendBuf[5] = 0x00;
requestSize = 6;
}
else
{
pHdr->function = MODBUS_Write_Multiple_Coils;
printf("ERROR writting multiple coils not supported.\n");
return(ERROR);
}
break;
case INPUT_TYPE:
printf("ERROR Discrete inputs are read only.\n");
return(ERROR);
break;
case HOLDING_TYPE:
if (points ==1)
{
pHdr->function = MODBUS_Write_Single_Register;
data = va_arg (vaList, ushort_t);
pHdr->u.data=htons(data);
requestSize = 6;
}
else if(points > 128 )
{
printf("ERROR to many data points\n");
return(ERROR);
}
else
{
pHdr->function = MODBUS_Write_Multiple_registers;
pHdr->u.size= htons(points);
pHdr->bytes= points*2;
pData=(ushort_t *)&sendBuf[7];
for(count=0;count<points;count++)
{
/* data going into buffer to be sent on network. needed htons(). EAN 07/26/02 */
volatile int temp;
/* have to use a temporary, or htons() will call va_arg() twice...
pain in the butt to figure this one out, thank goodness for
preprocessed files. EAN 07/26/02 */
temp=(ushort_t) va_arg (vaList,int );
pData[count] =htons(temp);
}
requestSize = 7+pHdr->bytes;
}
break;
case REGISTER_TYPE:
printf("ERROR Inputs registers are read only.\n");
return(ERROR);
case ID_TYPE:
printf("ERROR Device ID is read only.\n");
return(ERROR);
}
va_end (vaList);
}
else goto printSyntax;
if(!init)
{
if( pProtoCtrl = myProtocolInit(sysBootParams.bootDev, 0))
init = TRUE;
else
printf("ERROR can't attach protocol to specified device.\n");
return(ERROR);
}
myProtocolTx(
pProtoCtrl->pCookie,
sendBuf,
requestSize,
mac);
return(OK);
printSyntax:
printf("\nmodbus read|write points type address@XX:XX:XX:XX:XX:XX [data1].. [dataN]\n\n");
printf(" dataX and address are positive integers\n");
printf(" type is any one of the following\n");
printf(" coils (1 bit read/write values)\n");
printf(" inputs (1 bit read only values)\n");
printf(" holding (16 bit read/write holding registers)\n");
printf(" registers (16 bit read only input registers)\n");
printf(" ID (Device identification string)\n\n");
printf(" examples:\n -> modbus \"read\", 2, \"coils\", \"123@00:50:DA:FE:7B:DD\"\n");
printf(" -> modbus \"write\", 2, \"holding\", \"43@00:a0:1e:09:08:07\", 234, 56\n\n");
return(ERROR);
}
void dump( void)
{
int i;
for( i=0;i<NUMBER_OF_HOLDING_REGISTERS;i++)
{
if((i%10)==0)
printf("\n %d ",i);
printf("%hu, ",holdingRegisters[i]);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -