Files
chrg/apps/chrg/applications/thread/chrg_comm.c
T
2025-11-18 00:40:02 +08:00

799 lines
23 KiB
C

/****************************************************************************
文件名称 : chrg_comm.c
完成日期 :
当前版本号 : V1.0
主要功能 : 实现对外通讯协议 MODBUS 服务端,以独立线程等待处理响应请求数据。
版本历史 : 创建原始版本
说明 :
******************************************************************************/
#include <string.h>
#include <rtthread.h>
#include "chrg_comm.h"
#include "chrg_utils.h"
#define LOG_TAG "chrg.comm"
#define DBG_LEVEL DBG_LOG
#include <rtdbg.h>
rt_uint16_t usSDiscInStart = S_DISCRETE_INPUT_START;
rt_uint8_t ucSDiscInBuf[(S_DISCRETE_INPUT_NDISCRETES+BITS_UCHAR-1)/BITS_UCHAR];
rt_uint16_t usSCoilStart = S_COIL_START;
rt_uint8_t ucSCoilBuf[(S_COIL_NCOILS+BITS_UCHAR-1)/BITS_UCHAR];
rt_uint16_t usSRegInStart = S_REG_INPUT_START;
rt_uint16_t usSRegInBuf[S_REG_INPUT_NREGS];
rt_uint16_t usSRegHoldStart = S_REG_HOLDING_START;
rt_uint16_t usSRegHoldBuf[S_REG_HOLDING_NREGS];
struct chrg_comm_t chrgcomm = {
.devname = DEV_NAME_COMM,
.tty = RT_NULL,
.rx_len = 0,
.tx_len = 0,
.addr = MODBUS_ADDRESS_DEFAULT,
};
/*! \brief Function to set bits in a byte buffer.
*
* This function allows the efficient use of an array to implement bitfields.
* The array used for storing the bits must always be a multiple of two
* bytes. Up to eight bits can be set or cleared in one operation.
*
* \param ucByteBuf A buffer where the bit values are stored. Must be a
* multiple of 2 bytes. No length checking is performed and if
* usBitOffset / 8 is greater than the size of the buffer memory contents
* is overwritten.
* \param usBitOffset The starting address of the bits to set. The first
* bit has the offset 0.
* \param ucNBits Number of bits to modify. The value must always be smaller
* than 8.
* \param ucValues Thew new values for the bits. The value for the first bit
* starting at <code>usBitOffset</code> is the LSB of the value
* <code>ucValues</code>
*
* \code
* ucBits[2] = {0, 0};
*
* // Set bit 4 to 1 (read: set 1 bit starting at bit offset 4 to value 1)
* mb_set_bits( ucBits, 4, 1, 1 );
*
* // Set bit 7 to 1 and bit 8 to 0.
* mb_set_bits( ucBits, 7, 2, 0x01 );
*
* // Set bits 8 - 11 to 0x05 and bits 12 - 15 to 0x0A;
* mb_set_bits( ucBits, 8, 8, 0x5A);
* \endcode
*/
void mb_set_bits (rt_uint8_t *ucByteBuf, rt_uint16_t usBitOffset,
rt_uint8_t ucNBits, rt_uint8_t ucValue)
{
rt_uint16_t usWordBuf;
rt_uint16_t usMask;
rt_uint16_t usByteOffset;
rt_uint16_t usNPreBits;
rt_uint16_t usValue = ucValue;
RT_ASSERT(ucNBits <= BITS_UCHAR);
RT_ASSERT((size_t)BITS_UCHAR == sizeof(rt_uint8_t) * 8);
/* Calculate byte offset for first byte containing the bit values starting
* at usBitOffset. */
usByteOffset = (rt_uint16_t)((usBitOffset) / BITS_UCHAR);
/* How many bits precede our bits to set. */
usNPreBits = (rt_uint16_t)(usBitOffset - usByteOffset * BITS_UCHAR);
/* Move bit field into position over bits to set */
usValue <<= usNPreBits;
/* Prepare a mask for setting the new bits. */
usMask = (rt_uint16_t)((1 << (rt_uint16_t)ucNBits) - 1);
usMask <<= usBitOffset - usByteOffset * BITS_UCHAR;
/* copy bits into temporary storage. */
usWordBuf = ucByteBuf[usByteOffset];
usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;
/* Zero out bit field bits and then or value bits into them. */
usWordBuf = (rt_uint16_t)((usWordBuf & (~usMask)) | usValue);
/* move bits back into storage */
ucByteBuf[usByteOffset] = (rt_uint8_t)(usWordBuf & 0xFF);
ucByteBuf[usByteOffset + 1] = (rt_uint8_t)(usWordBuf >> BITS_UCHAR);
}
/*! \brief Function to read bits in a byte buffer.
*
* This function is used to extract up bit values from an array. Up to eight
* bit values can be extracted in one step.
*
* \param ucByteBuf A buffer where the bit values are stored.
* \param usBitOffset The starting address of the bits to set. The first
* bit has the offset 0.
* \param ucNBits Number of bits to modify. The value must always be smaller
* than 8.
*
* \code
* rt_uint8_t ucBits[2] = {0, 0};
* rt_uint8_t ucResult;
*
* // Extract the bits 3 - 10.
* ucResult = mb_get_bits( ucBits, 3, 8 );
* \endcode
*/
rt_uint8_t mb_get_bits (rt_uint8_t * ucByteBuf, rt_uint16_t usBitOffset, rt_uint8_t ucNBits)
{
rt_uint16_t usWordBuf;
rt_uint16_t usMask;
rt_uint16_t usByteOffset;
rt_uint16_t usNPreBits;
/* Calculate byte offset for first byte containing the bit values starting
* at usBitOffset. */
usByteOffset = (rt_uint16_t)((usBitOffset) / BITS_UCHAR);
/* How many bits precede our bits to set. */
usNPreBits = (rt_uint16_t)(usBitOffset - usByteOffset * BITS_UCHAR);
/* Prepare a mask for setting the new bits. */
usMask = (rt_uint16_t)((1 << (rt_uint16_t)ucNBits) - 1);
/* copy bits into temporary storage. */
usWordBuf = ucByteBuf[usByteOffset];
usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;
/* throw away unneeded bits. */
usWordBuf >>= usNPreBits;
/* mask away bits above the requested bitfield. */
usWordBuf &= usMask;
return (rt_uint8_t)usWordBuf;
}
static eMBException mb_error (eMBErrorCode eErrorCode)
{
eMBException eStatus;
switch (eErrorCode) {
case MB_ENOERR:
eStatus = MB_EX_NONE;
break;
case MB_ENOREG:
eStatus = MB_EX_ILLEGAL_DATA_ADDRESS;
break;
case MB_ETIMEDOUT:
eStatus = MB_EX_SLAVE_BUSY;
break;
default:
eStatus = MB_EX_SLAVE_DEVICE_FAILURE;
break;
}
return eStatus;
}
eMBErrorCode mb_reg_input_cb (rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress, rt_uint16_t usNRegs)
{
eMBErrorCode eStatus = MB_ENOERR;
rt_uint16_t iRegIndex;
rt_uint16_t *pusRegInputBuf = usSRegInBuf;
rt_uint16_t REG_INPUT_START = S_REG_INPUT_START;
rt_uint16_t REG_INPUT_NREGS = S_REG_INPUT_NREGS;
rt_uint16_t usRegInStart = usSRegInStart;
if ((usAddress >= REG_INPUT_START)
&& (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS)) {
iRegIndex = usAddress - usRegInStart;
while (usNRegs > 0) {
*pucRegBuffer++ = (rt_uint8_t)(pusRegInputBuf[iRegIndex] >> BITS_UCHAR);
*pucRegBuffer++ = (rt_uint8_t)(pusRegInputBuf[iRegIndex] & 0xFF);
iRegIndex++;
usNRegs--;
}
} else {
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode mb_reg_holding_cb (rt_uint8_t *req, rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress,
rt_uint16_t usNRegs, eMBRegisterMode eMode)
{
eMBErrorCode eStatus = MB_ENOERR;
rt_uint16_t iRegIndex;
rt_uint16_t *pusRegHoldingBuf = usSRegHoldBuf;
rt_uint16_t REG_HOLDING_START = S_REG_HOLDING_START;
rt_uint16_t REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
rt_uint16_t usRegHoldStart = usSRegHoldStart;
if ((usAddress >= REG_HOLDING_START)
&& (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS)) {
iRegIndex = usAddress - usRegHoldStart;
switch (eMode) {
/* read current register values from the protocol stack. */
case MB_REG_READ:
while (usNRegs > 0) {
*pucRegBuffer++ = (rt_uint8_t)(pusRegHoldingBuf[iRegIndex] >> BITS_UCHAR);
*pucRegBuffer++ = (rt_uint8_t)(pusRegHoldingBuf[iRegIndex] & 0xFF);
iRegIndex++;
usNRegs--;
}
break;
/* write current register values with new values from the protocol stack. */
case MB_REG_WRITE:
while (usNRegs > 0) {
pusRegHoldingBuf[iRegIndex] = *req++ << BITS_UCHAR;
pusRegHoldingBuf[iRegIndex] |= *req++;
iRegIndex++;
usNRegs--;
}
break;
}
} else {
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode mb_reg_coils_cb (rt_uint8_t *req, rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress,
rt_uint16_t usNCoils, eMBRegisterMode eMode)
{
eMBErrorCode eStatus = MB_ENOERR;
rt_uint16_t iRegIndex = 0, iRegBitIndex = 0, iNReg = 0;
rt_uint8_t *pucCoilBuf = ucSCoilBuf;
rt_uint16_t COIL_START = S_COIL_START;
rt_uint16_t COIL_NCOILS = S_COIL_NCOILS;
rt_uint16_t usCoilStart = usSCoilStart;
iNReg = (usNCoils+BITS_UCHAR-1)/BITS_UCHAR;
if ((usAddress >= COIL_START) && (usAddress + usNCoils <= COIL_START + COIL_NCOILS)) {
iRegIndex = (rt_uint16_t)(usAddress - usCoilStart) / BITS_UCHAR;
iRegBitIndex = (rt_uint16_t)(usAddress - usCoilStart) % BITS_UCHAR;
switch (eMode) {
/* read current coil values from the protocol stack. */
case MB_REG_READ:
while (iNReg > 0) {
*pucRegBuffer++ = mb_get_bits(&pucCoilBuf[iRegIndex++], iRegBitIndex, BITS_UCHAR);
iNReg--;
}
pucRegBuffer--;
/* last coils */
usNCoils = usNCoils % BITS_UCHAR;
/* filling zero to high bit */
*pucRegBuffer = *pucRegBuffer << (BITS_UCHAR - usNCoils);
*pucRegBuffer = *pucRegBuffer >> (BITS_UCHAR - usNCoils);
break;
/* write current coil values with new values from the protocol stack. */
case MB_REG_WRITE:
while (iNReg > 1) {
mb_set_bits(&pucCoilBuf[iRegIndex++], iRegBitIndex, BITS_UCHAR, *req++);
iNReg--;
}
/* last coils */
usNCoils = usNCoils % BITS_UCHAR;
/* mb_set_bits has bug when ucNBits is zero */
if (usNCoils != 0) {
mb_set_bits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, *req++);
}
break;
}
} else {
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode mb_reg_discrete_cb (rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress, rt_uint16_t usNDiscrete)
{
eMBErrorCode eStatus = MB_ENOERR;
rt_uint16_t iRegIndex , iRegBitIndex , iNReg;
rt_uint8_t *pucDiscreteInputBuf = ucSDiscInBuf;
rt_uint16_t DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
rt_uint16_t DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
rt_uint16_t usDiscreteInputStart = usSDiscInStart;
iNReg = (usNDiscrete+BITS_UCHAR-1) / BITS_UCHAR;
if ((usAddress >= DISCRETE_INPUT_START)
&& ((usAddress + usNDiscrete) <= (DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))) {
iRegIndex = (rt_uint16_t) (usAddress - usDiscreteInputStart) / BITS_UCHAR;
iRegBitIndex = (rt_uint16_t) (usAddress - usDiscreteInputStart) % BITS_UCHAR;
while (iNReg > 0) {
*pucRegBuffer++ = mb_get_bits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, BITS_UCHAR);
iNReg--;
}
pucRegBuffer--;
/* last discrete */
usNDiscrete = usNDiscrete % BITS_UCHAR;
/* filling zero to high bit */
*pucRegBuffer = *pucRegBuffer << (BITS_UCHAR - usNDiscrete);
*pucRegBuffer = *pucRegBuffer >> (BITS_UCHAR - usNDiscrete);
} else {
eStatus = MB_ENOREG;
}
return eStatus;
}
/*****************************************************************
函数名称: funcReadCoils
函数描述: 读多个继电器
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcReadCoils (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
rt_uint16_t regAddress = 0, cntCoils = 0;
rt_uint8_t ucNBytes = 0;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if (4+MB_PDU_FUNC_READ_SIZE != reqLen) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
regAddress = u8v_to_u16(&reqFrame[2]);
cntCoils = u8v_to_u16(&reqFrame[4]);
if ((0 == cntCoils)||(cntCoils >= MB_PDU_FUNC_READ_COILCNT_MAX)) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
ucNBytes = (cntCoils+BITS_UCHAR-1)/BITS_UCHAR;
resFrame[1] = MB_READ_COILS;
resFrame[2] = ucNBytes;
eRegStatus = mb_reg_coils_cb(RT_NULL, &resFrame[3], regAddress, cntCoils, MB_REG_READ);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
} else {
*resLen = 3+ucNBytes;
}
return eStatus;
}
/*****************************************************************
函数名称: funcReadDiscreteInputs
函数描述: 读离散输入
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcReadDiscreteInputs (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
rt_uint16_t regAddress = 0, cntDisCrete = 0;
rt_uint8_t ucNBytes = 0;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if (4+MB_PDU_FUNC_READ_SIZE != reqLen) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
regAddress = u8v_to_u16(&reqFrame[2]);
cntDisCrete = u8v_to_u16(&reqFrame[4]);
if ((0 == cntDisCrete)||(cntDisCrete >= MB_PDU_FUNC_READ_DISCCNT_MAX)) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
ucNBytes = (cntDisCrete+BITS_UCHAR-1)/BITS_UCHAR;
resFrame[1] = MB_READ_DISCRETE_INPUTS;
resFrame[2] = ucNBytes;
eRegStatus = mb_reg_discrete_cb(&resFrame[3], regAddress, cntDisCrete);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
} else {
*resLen = 3+ucNBytes;
}
return eStatus;
}
/*****************************************************************
函数名称: funcReadHoldingRegister
函数描述: 读保持寄存器
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcReadHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
rt_uint16_t regAddress = 0, cntReg = 0;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if (4+MB_PDU_FUNC_READ_SIZE != reqLen) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
regAddress = u8v_to_u16(&reqFrame[2]);
cntReg = u8v_to_u16(&reqFrame[4]);
if ((0 == cntReg)||(cntReg >= MB_PDU_FUNC_READ_REGCNT_MAX)) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
resFrame[1] = MB_READ_HOLDING_REGISTER;
resFrame[2] = cntReg * 2;
eRegStatus = mb_reg_holding_cb(RT_NULL, &resFrame[3], regAddress, cntReg, MB_REG_READ);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
} else {
*resLen = 3+cntReg * 2;
}
return eStatus;
}
/*****************************************************************
函数名称: funcReadInputRegister
函数描述: 读输入寄存器
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcReadInputRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
rt_uint16_t regAddress = 0, cntReg = 0;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if (4+MB_PDU_FUNC_READ_SIZE != reqLen) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
regAddress = u8v_to_u16(&reqFrame[2]);
cntReg = u8v_to_u16(&reqFrame[4]);
if ((0 == cntReg)||(cntReg >= MB_PDU_FUNC_READ_REGCNT_MAX)) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
resFrame[1] = MB_READ_INPUT_REGISTER;
resFrame[2] = cntReg * 2;
eRegStatus = mb_reg_discrete_cb(&resFrame[3], regAddress, cntReg);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
} else {
*resLen = 3+cntReg*2;
}
return eStatus;
}
/*****************************************************************
函数名称: funcWriteCoil
函数描述: 写单个保持继电器
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcWriteCoil (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
rt_uint16_t regAddress = 0, value = 0;
rt_uint8_t ucBuf[2] = {0};
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if (4+MB_PDU_FUNC_WRITE_SIZE != reqLen) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
regAddress = u8v_to_u16(&reqFrame[2]);
value = u8v_to_u16(&reqFrame[4]);
if (0x0000 == value) {
ucBuf[0] = 0;
ucBuf[1] = 0;
} else if (0xFF00 == value) {
ucBuf[0] = 1;
ucBuf[1] = 0;
} else {
return MB_EX_ILLEGAL_DATA_VALUE;
}
rt_memcpy(resFrame, reqFrame, reqLen);
*resLen = reqLen-2;
eRegStatus = mb_reg_coils_cb(RT_NULL, ucBuf, regAddress, 1, MB_REG_WRITE);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
}
return eStatus;
}
/*****************************************************************
函数名称: funcWriteHoldingRegister
函数描述: 写多个保持继电器
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcWriteHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
rt_uint16_t regAddress = 0;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if (4+MB_PDU_FUNC_WRITE_SIZE != reqLen) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
regAddress = u8v_to_u16(&reqFrame[2]);
rt_memcpy(resFrame, reqFrame, reqLen);
*resLen = reqLen-2;
eRegStatus = mb_reg_holding_cb(&reqFrame[4], &resFrame[3], regAddress, 1, MB_REG_WRITE);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
}
return eStatus;
}
/*****************************************************************
函数名称: funcWriteMultipleCoils
函数描述: 写多个继电器
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcWriteMultipleCoils (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
rt_uint16_t regAddress = 0, cntCoils = 0;
rt_uint8_t ucByteCount;
rt_uint8_t ucByteCountVerify;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if (4+MB_PDU_FUNC_WRITE_SIZE > reqLen) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
regAddress = u8v_to_u16(&reqFrame[2]);
cntCoils = u8v_to_u16(&reqFrame[4]);
ucByteCount = reqFrame[6];
ucByteCountVerify = (cntCoils+BITS_UCHAR-1)/BITS_UCHAR;
if ((0 == cntCoils)
||(cntCoils > MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX)
||(ucByteCountVerify != ucByteCount)) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
rt_memcpy(resFrame, reqFrame, reqLen);
*resLen = 6;
eRegStatus = mb_reg_coils_cb(reqFrame, &resFrame[3], regAddress, cntCoils, MB_REG_WRITE);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
}
return eStatus;
}
/*****************************************************************
函数名称: funcWriteMultipleHoldingRegister
函数描述: 写多个寄存器
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcWriteMultipleHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
rt_uint16_t regAddress = 0, cntReg = 0;
rt_uint8_t ucRegByteCount;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if (4+MB_PDU_FUNC_WRITE_MUL_SIZE_MIN > reqLen) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
regAddress = u8v_to_u16(&reqFrame[2]);
cntReg = u8v_to_u16(&reqFrame[4]);
ucRegByteCount = reqFrame[6];
if ((0 == cntReg)
||(cntReg > MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX)
||(ucRegByteCount != cntReg*2)) {
return MB_EX_ILLEGAL_DATA_VALUE;
}
rt_memcpy(resFrame, reqFrame, reqLen);
*resLen = 6;
eRegStatus = mb_reg_holding_cb(reqFrame, &resFrame[3], regAddress, cntReg, MB_REG_WRITE);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
}
return eStatus;
}
static struct code_func_t funcHandlers[MB_HANDLERS_MAX] = {
{MB_READ_COILS, funcReadCoils},
{MB_READ_DISCRETE_INPUTS, funcReadDiscreteInputs},
{MB_READ_HOLDING_REGISTER, funcReadHoldingRegister},
{MB_READ_INPUT_REGISTER, funcReadInputRegister},
{MB_WRITE_SINGLE_COIL, funcWriteCoil},
{MB_WRITE_REGISTER, funcWriteHoldingRegister},
{MB_WRITE_MULTIPLE_COILS, funcWriteMultipleCoils},
{MB_WRITE_MULTIPLE_REGISTERS, funcWriteMultipleHoldingRegister},
};
/*****************************************************************
函数名称: chrg_comm_parse_msg
函数描述: 解析请求的消息
输入参数: pCOMM: 消息结构
输出参数: -
返回说明: -
其它说明: 分命令处理对应消息。地址为广播时不应答
*****************************************************************/
static int chrg_comm_parse_msg (struct chrg_comm_t *pCOMM)
{
if (RT_NULL == pCOMM) {
return -1;
}
if (pCOMM->rx_len < 8) {
return -2;
}
if (0 != mb_crc16(pCOMM->rx_buf, pCOMM->rx_len)) {
rt_kprintf("crc %04X ", mb_crc16(pCOMM->rx_buf, pCOMM->rx_len-2));
return -3;
}
int i = 0, ret = -1;
rt_uint16_t crc = 0;
eMBException eStatus = MB_EX_ILLEGAL_FUNCTION;
rt_uint8_t address = 0, functionCode = 0x00;
address = pCOMM->rx_buf[0];
functionCode = pCOMM->rx_buf[1];
if ((address != pCOMM->addr)&&(MB_ADDRESS_BROADCAST != address)) {
return ret;
}
struct code_func_t *pFunc = RT_NULL;
for (i = 0; i < MB_HANDLERS_MAX; i++) {
pFunc = &funcHandlers[i];
if (RT_NULL == pFunc) {
break;
}
if ((functionCode == pFunc->code)&&(RT_NULL != pFunc->func)) {
eStatus = pFunc->func(pCOMM->rx_buf, pCOMM->rx_len,
pCOMM->tx_buf, &pCOMM->tx_len);
break;
}
}
if (MB_ADDRESS_BROADCAST != address) {
pCOMM->tx_buf[0] = address;
if (MB_EX_NONE != eStatus) {
pCOMM->tx_buf[1] = (functionCode | MB_FUNC_ERROR);
pCOMM->tx_buf[2] = eStatus;
pCOMM->tx_len = 3;
}
crc = mb_crc16(pCOMM->tx_buf, pCOMM->tx_len);
u16_to_u8v(crc, &pCOMM->tx_buf[pCOMM->tx_len]);
pCOMM->tx_len += 2;
ret = chrg_tty_send(pCOMM->tty, pCOMM->tx_buf, pCOMM->tx_len);
}
return ret;
}
/*****************************************************************
函数名称: chrg_comm_thread_entry
函数描述: 对外RS485通信线程体
输入参数: *data: 本线程信息
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
void chrg_comm_thread_entry (void *data)
{
struct chrg_thread_t *pTHR = (struct chrg_thread_t *)data;
if (RT_NULL == pTHR) {
return ;
}
int len = 0;
struct chrg_tty_t *pTTY = RT_NULL;
struct chrg_comm_t *pCOMM = &chrgcomm;
pTTY = chrg_tty_create(pCOMM->devname, BAUD_RATE_115200, 0, 8, 1);
if (RT_NULL == pTTY) {
LOG_E("tty can't create.");
return ;
}
chrg_tty_set_recv_tmo(pTTY, 8);
if (chrg_tty_connect(pTTY) != RT_EOK) {
chrg_tty_destory(pTTY);
return;
}
chrg_tty_mode_set(pTTY, 0);
pCOMM->tty = pTTY;
while (1) {
rt_memset(pCOMM->rx_buf, 0, sizeof(pCOMM->rx_buf));
len = chrg_tty_recv(pTTY, pCOMM->rx_buf, sizeof(pCOMM->rx_buf));
if (len <= 0) {
rt_thread_mdelay(1);
continue;
}
pCOMM->rx_len = len;
pCOMM->tx_len = 0;
chrg_comm_parse_msg(pCOMM);
}
}