该方法用来设置线圈的数据,贴上部分代码。 我们知道Modbus为数据为大端模式(高地址放在低位,低地址放在高位),这样可以按着我们的习惯来设置IO数据。如下为设置多个线圈帧。 今天就以这样的组合看modbus协议如何发送和解析的协议帧的。 下图是我的测试记录,可以看到差异差异就是倒数第3个字节
框选1:发送的报文Tx:008108-01 0F 0B B8 00 10 02 03 00 43 68 框选2:发送的报文Tx:008116-01 0F 0B B8 00 10 02 03 C0 43 38 下面先了解下 GD32单片机是大端还是小端模式
{
uint16_t data= 0x1122;
uint8_t *usdat = (uint8_t*)&data;
LOGE("0x%x,%x",(uint8_t*)&usdat[0],usdat[0]);
LOGE("0x%x,%x",(uint8_t*)&usdat[1],usdat[1]);
}
打印结果: 可以看到,针对GD32单片机来说,数据低位保存在低地址上,即“小弟弟”–>小低低模式。
接着上面的,目前我先把3000开始的2个线圈打开了,可以看到协议数据部分是03 00, 由于modbus是大端模式,单片机是小段模式,则低位的3000和3001寄存器对应的状态是0x03,即低位的2个灯亮了。
eMBErrorCode
eMBRegCoilsCB(MBObj_t *pMbObj, UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode)
{
eMBErrorCode eStatus = MB_ENOERR;
short iNCoils = (short)usNCoils;
unsigned short usBitOffset;
usAddress = usAddress -1;
LOGD("codi");
if ((usAddress >= REG_COILS_START) &&
(usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE))
{
usBitOffset = (unsigned short)(usAddress - REG_COILS_START);
switch (eMode)
{
case MB_REG_READ:
while (iNCoils > 0)
{
*pucRegBuffer++ =
xMBUtilGetBits(ucRegCoilsBuf[pMbObj->portId], usBitOffset,
(unsigned char)(iNCoils >
8 ? 8 :
iNCoils));
iNCoils -= 8;
usBitOffset += 8;
}
break;
case MB_REG_WRITE:
LOGD("ncoils:%d",iNCoils);
{
UCHAR *Psrc = ucRegCoilsBuf[pMbObj->portId];
while (iNCoils > 0)
{
xMBUtilSetBits(Psrc++, usBitOffset,
(unsigned char)(iNCoils > 8 ? 8 : iNCoils),
*pucRegBuffer++);
iNCoils -= 8;
}
{
UCHAR *PpduBUf = NULL;
master_ops->pvGetPduBuffer(&PpduBUf);
if (MB_FUNC_WRITE_SINGLE_COIL == PpduBUf[MB_PDU_FUNC_OFF]) {
} else if (MB_FUNC_WRITE_MULTIPLE_COILS == PpduBUf[MB_PDU_FUNC_OFF]) {
}
}
}
break;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
void
xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits,
UCHAR ucValue )
{
USHORT usWordBuf;
USHORT usMask;
USHORT usByteOffset;
USHORT usNPreBits;
USHORT usValue = ucValue;
assert( ucNBits <= 8 );
assert( ( size_t )BITS_UCHAR == sizeof( UCHAR ) * 8 );
usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR );
usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR );
usValue <<= usNPreBits;
usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 );
usMask <<= usBitOffset - usByteOffset * BITS_UCHAR;
usWordBuf = ucByteBuf[usByteOffset];
usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;
usWordBuf = ( USHORT )( ( usWordBuf & ( ~usMask ) ) | usValue );
ucByteBuf[usByteOffset] = ( UCHAR )( usWordBuf & 0xFF );
ucByteBuf[usByteOffset + 1] = ( UCHAR )( usWordBuf >> BITS_UCHAR );
}
|