</pre><p>今天在看modbus通信的时候,发现一种比较好的设置一段连续内存bit位的方法。</p><p>两个函数 xMBUtilGetBits 和 xMBUTilSetBits。</p><p><pre name="code" class="cpp">UCHAR xMBUtilGetBits(UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits) {
USHORT usWordBuf;
USHORT usMask;
USHORT usByteOffset;
USHORT usNPreBits;
/* Calculate byte offset for first byte containing the bit values starting
* at usBitOffset. */
usByteOffset = (USHORT) ((usBitOffset) / BITS_UCHAR);
/* How many bits precede our bits to set. */
usNPreBits = (USHORT) (usBitOffset - usByteOffset * BITS_UCHAR);
/* Prepare a mask for setting the new bits. */
usMask = (USHORT) ((1 << (USHORT) 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 (UCHAR) usWordBuf;
}
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);
/* Calculate byte offset for first byte containing the bit values starting
* at usBitOffset. */
usByteOffset = (USHORT) ((usBitOffset) / BITS_UCHAR); //usByteOffset
/* How many bits precede our bits to set. */
usNPreBits = (USHORT) (usBitOffset - usByteOffset * BITS_UCHAR); //usNpreBits
/* Move bit field into position over bits to set */
usValue <<= usNPreBits; //MoveValue over bits to set
/* Prepare a mask for setting the new bits. */
usMask = (USHORT) ((1 << (USHORT) 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 = (USHORT) ((usWordBuf & (~usMask)) | usValue);
/* move bits back into storage */
ucByteBuf[usByteOffset] = (UCHAR) (usWordBuf & 0xFF);
ucByteBuf[usByteOffset + 1] = (UCHAR) (usWordBuf >> BITS_UCHAR);
}
对一大块内存需要设定特殊位置的bit还是比较好的,不过是以字节对齐的方式
xMBUtilGetBits函数:
xMBUtilSetBits 函数
parameter:
UCHAR *ucByteBuf
USHORT usBitOffset
UCHAR ucNBits
UCHAR ucValue
ucByteBuf:需要设置位的数据内存
usBitOffset: 偏移从第0位开始的偏移量
ucNBits: 需要设置位的位置MASK
ucValue: 设置值
UCHAR dataBuf[4]={0xff,0xfc,0x00,0x00};
xMBUtilSetBits(dataBuf,0, 8,0x00);
xMBUtilSetBits(dataBuf,8,1,0x01);
xMBUtilSetBits(dataBuf,16,0,0x1);
结果:dataBuf[4] = {0x00,0xfd,0x01,0x00};
setBits:xMBUtilSetBits(UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits,UCHARucValue)
ucByteBuf 内存排列:XXXXXXXXXXXXXXXX XXXXXXXX XXXXXXXX
usBitOffset:0-78-15 16-23 24-32
ucNBits:1-8
ucValue:新值
getBits:xMBUtilGetBits(UCHAR* ucByteBuf, USHORT usBitOffset, UCHAR ucNBits)
ucByteBuf 内存排列:XXXXXXXXXXXXXXXX XXXXXXXX XXXXXXXX
usBitOffset:0-7 8-15 16-23 24-32
ucNBits:1-8
resData = xMBUtilGetBits(dataBuf,8,8); resData为0xfd