You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
3.8 KiB
C

#include <string.h>
#include <stdio.h>
#include "modbus.h"
static unsigned short calculate_crc16(unsigned char *pData, unsigned short iLen)
{
unsigned short iCrc = 0xFFFF;
unsigned short j = 0, i = 0;
for (j = 0; j < iLen; j++)
{
iCrc = iCrc ^ *pData++;
for (i = 0; i < 8; i++)
{
if ((iCrc & 0x0001) > 0)
{
iCrc = iCrc >> 1;
iCrc = iCrc ^ 0xa001;
}
else
{
iCrc = iCrc >> 1;
}
}
}
return iCrc;
}
int _modbus_head_init(unsigned char *buf, unsigned char cmd)
{
modbus_head_t *head = (modbus_head_t*)buf;
int len;
head->slave = 0xff;
head->cmd = cmd;
len = 2;
return len;
}
int _modbus_addr_set(unsigned char *buf, unsigned short addr)
{
buf[0] = addr >> 8;
buf[1] = addr & 0xff;
return 2;
}
int _modbus_size_set(unsigned char *buf, unsigned short size)
{
buf[0] = size >> 8;
buf[1] = size & 0xff;
return 2;
}
int _modbus_write_head(unsigned char *pkt, unsigned char cmd, unsigned short regAddr, unsigned short regCnt)
{
if (pkt == NULL)
{
return -1;
}
unsigned char *ppkt = pkt;
unsigned char len;
int bytecnt;
*ppkt++ = 0xff;
*ppkt++ = cmd;
*ppkt++ = (regAddr >> 8) & 0xff;
*ppkt++ = (regAddr) & 0xff;
*ppkt++ = (regCnt >> 8) & 0xff;
*ppkt++ = (regCnt) & 0xff;
len = 6;
if (cmd == MB_FUNC_MULIT_WR)
{
bytecnt = regCnt * 2;
*ppkt++ = bytecnt;
len++;
}
return len;
}
int _modbus_write_body()
{
return 0;
}
void _modbus_checksum(unsigned char *buf, int len)
{
unsigned short crc = calculate_crc16(buf,len);
buf[len] = crc & 0xff;
buf[len+1] = (crc>>8) & 0xff;
}
int _modbus_verify_crc(unsigned char *buf, int len)
{
unsigned short crc = calculate_crc16(buf,len - 2);
unsigned short recv_crc = buf[len - 2] | (buf[len - 1] << 8);
//printf("crc=0x%x recv_crc=0x%x\n", crc, recv_crc);
if (crc == recv_crc)
{
return 1;
}
return 0;
}
#if 0
int _modbus_packet(unsigned char *pkt, unsigned char cmd, unsigned short addr, unsigned short size)
{
unsigned char *pdat;
int len = 0, ret = 0;
ret = _modbus_head_init(pkt, cmd);
pdat = pkt + ret;
len += ret;
ret = _modbus_addr_set(pdat, addr);
pdat += ret;
len += ret;
ret = _modbus_size_set(pdat, size);
pdat += ret;
len += ret;
ret = _modbus_checksum(pkt, len);
len += ret;
return len;
}
#else
void _modbus_add_float(unsigned char *hex,float val)
{
unsigned int *pint = (unsigned int *)&val;
hex[0] = (*pint>>8)&0xff;
hex[1] = (*pint>>0)&0xff;
hex[2] = (*pint>>24)&0xff;
hex[3] = (*pint>>16)&0xff;
//printf("[%s:%d]%f %x %x %x %x %x\n",__FUNCTION__, __LINE__, val,*pint,hex[0],hex[1],hex[2],hex[3]);
}
int _modbus_packet(unsigned char *pkt, unsigned char cmd, unsigned short regAddr, unsigned short regCnt, unsigned char data[])
{
if (pkt == NULL)
{
return -1;
}
unsigned char *ppkt = pkt;
unsigned char len;
unsigned short crc;
int bytecnt;
*ppkt++ = 0xff;
*ppkt++ = cmd;
*ppkt++ = (regAddr >> 8) & 0xff;
*ppkt++ = (regAddr) & 0xff;
*ppkt++ = (regCnt >> 8) & 0xff;
*ppkt++ = (regCnt) & 0xff;
len = 6;
if (cmd == MB_FUNC_MULIT_WR)
{
bytecnt = regCnt * 2;
*ppkt++ = bytecnt;
len++;
memcpy(ppkt, data, bytecnt);
len += bytecnt;
}
crc = calculate_crc16(pkt, len);
*ppkt++ = (crc >> 8) & 0xff;
len++;
*ppkt++ = (crc) & 0xff;
len++;
return len;
}
#endif