如何正确地从uint16_t变量中提取一个特定位

时间:2016-02-22 09:50:40

标签: c++ embedded wrapper bit

长话短说,我目前正在用C ++编写C ++包装器,用于提取嵌入式系统寄存器的值。为了监控发生的情况,我需要为某些寄存器读取一个位的值,并为每个寄存器创建一个getter。

基本上,我希望我的方法从存储到uint16_t变量中的位返回一个bool。在一个'天真'和没有咖啡因的方法我做了类似的事情:

bool getBusyDevice(int fd) // fd stands for file descriptor, for each instance of the class
{
    uint16_t statusRegVal = 0;
    get_commandReg(fd, &statusRegVal); // C-library function to get the value of status register
    uint16_t shift = 0; // depends on the bit to access - for reusability
    bool Busy = (bool) (statusRegVal >> shift);
    return busy;
}

我对结果不太满意,我想知道是否有“正确”的方法来做到这一点......

非常感谢您的建议!

5 个答案:

答案 0 :(得分:5)

获得一位的正常方法是使用按位运算符&。像例如statusRegVal & bitValue。如果设置了该位,则结果将等于bitValue,这意味着要获得布尔结果,您可以进行简单的比较:statusRegVal & bitValue == bitValue

因此,如果要检查是否设置了位0(值为0x0001),那么您可以简单地执行

return statusRegVal & 0x0001 == 0x0001;

答案 1 :(得分:1)

为什么不使用模板:

template<int SHIFT>
bool boolRegVal(uint16_t val) {
   return val & (1 << SHIFT);
}

然后用法:

boolRegVal<4>(statusRegVal);

答案 2 :(得分:1)

为了更好地了解您的需求,请查看以下链接

掩蔽:https://en.wikipedia.org/wiki/Mask_(computing)

位操作:https://en.wikipedia.org/wiki/Bit_manipulation

结论: 如果要读取变量(寄存器)中的特定位数,则应使用具有位位置的变量进行MASK。 说你有2Byte变量(u16Reg)并且你想读取位[5,7]所以, value = ((u16Reg & 0x00A0) >> 5)。 在您的情况下,您想要读取一位并返回状态 TRUE FALSE

value = ((u16Reg & (0x0001 << n)) >> n)

其中n是您要读取的位数。

让我们理解它。 说u16Reg = 0x529D = 0b0101001010011101; bit [0] = 1且bit [15] = 0;你想获得第9位。 因此,首先要确保除了你的所有位都是零(9)。

(0b0101001010011101 & (0x0001 << 9))      = 
(0b0101001010011101 & 0x0200)             = 
(0b0101001010011101 & 0b0000001000000000) =
(0b0000001000000000)                      = 0x0200

这意味着如果您的意思是nonZero为TRUE,则为TRUE。但如果TRUE表示0x01,则应将此位移至位[0],如下所示: (0x0200 >> 9) = 0x0001为真  如果你能理解这一点,你可以更简单地说:

value = ((u16Reg >> n) & 0x0001)

答案 3 :(得分:0)

铸造bool不会有帮助,因为它不是1位类型。 你必须清理剩下的部分,然后检查你是否有0。

您可以这样做:

 bool Busy =  ((statusRegVal >> shift) & 1) ? true : false;

答案 4 :(得分:0)

标准库提供了用于操作位的std :: bitset。这是一个例子,但我相信你能猜出它的作用。

#include <bitset>
#include <iostream>

using namespace std;

int main(int, char**){

    typedef bitset<sizeof(int)*8> BitsType; //or uint16_t or whatever
    BitsType bits(0xDEADBEEF);

    for(int i = 0; i < 5; ++i)  //access the bits
       cout << "bits[" << i << "] = " << bits[i] << '\n';

    cout << "bit[3] = " << bits[3] << '\n'; //original
    bits.flip(3);
    cout << "bit[3] = " << bits[3] << '\n'; //b[3] = !b[3]

   return 0;
}

操作符[](size_t)被重载以返回引用,因此您也可以分配它。例如bits[4] = false。最后,当玩完你的位:)你可以转换回长(或ulong)或在你的情况uint16_t value = static_cast<uint16_t>(bits.to_ulong())。感谢stdlib。