我正在为红外摄像机编程。但是用于存储刷新率的内部寄存器(共16位的9、8和7位)当然只接受1和0。例如,值0b110表示32Hz,0b111表示64Hz。查看刷新率控制图片时,如何最好地将介于0.5Hz和64Hz之间的给定整数(refresh_rate)值转换为0b000-0b111?

老实说,我还没有尝试过任何东西,因为我认为这需要一个怪异的技巧。但是我一直在考虑一个可查询的表,我认为这是可能的,但是需要更多的内存,并且由于它是在Arduino Due上编程的,因此必须提高内存效率。

注意:您可以看到refresh_rate是一个uint16_t,它不接受诸如0.5Hz之类的浮点值,但是,我可能不会使用0.5Hz设置。

// the end-user currently has to pass a value between 7 and 0
void mlx90650::set_refresh_rate(uint16_t refresh_rate) {
    // So the refresh rate may not be higher than 7 (0b111) since this register only
accepts 3 bits. The memory map is:
/*
    | decimal | bits  |
    (decimal 0) 0 0 0 IR refresh rate = 0.5Hz
    (decimal 1) 0 0 1 IR refresh rate = 1Hz
    (decimal 2) 0 1 0 IR refresh rate = 2Hz (default)
    (decimal 3) 0 1 1 IR refresh rate = 4Hz
    (decimal 4) 1 0 0 IR refresh rate = 8Hz
    (decimal 5) 1 0 1 IR refresh rate = 16Hz
    (decimal 6) 1 1 0 IR refresh rate = 32Hz
    (decimal 7) 1 1 1 IR refresh rate = 64H
*/
}

我希望此函数将例如64Hz转换为0b111。

最佳答案



一种方法是看到目标值每输入一倍就增加一,这意味着它是log2(Hz)+ 1。

所以,你可以写

uint16_t hz_bits(float hz) {
    return static_cast<uint16_t>(round(1.0f + log2(hz)));
}

当然,它需要浮点运算,并且没有高度优化。反过来,
float hz_from_bits(uint16_t hzB) {
    return 0.5f * (1 << hzB);
}

两者都具有您所关心的uint16_t的最低有效位的三位。

如果要使用整数Hz数,而忽略0.5的情况,则log2只是最高设置位的数字:例如,64 = 0b1000000,最高设置位为6(您仍然需要加1以获得7 = 0b111)。

然后,您可以将它们与类似
static const uint16_t HZ_START = 7;
static const uint16_t HZ_LEN = 3;
static const uint16_t HZ_MASK = ((1 << HZ_LEN)-1) << HZ_START;

uint16_t set_hz_bits(uint16_t control, uint16_t hzB) {
    return (control & ~HZ_MASK) | (hzB << HZ_START);
}
uint16_t get_hz_bits(uint16_t control) {
    return (control & HZ_MASK) >> HZ_START;
}

进入
uint16_t set_hz(uint16_t control, float hz) {
    return set_hz_bits(control, hz_bits(hz));
}
float get_hz(uint16_t control) {
    return hz_from_bits(get_hz_bits(control));
}

请注意,实际的位屏蔽和移位是非常机械的-您可以使用以下类似代码轻松地针对各个字段自动执行此操作,并传递HzField对象,而不必记住哪个uint16_t包含基于零的编码Hz值,并包含正确布局的控制寄存器。
template <size_t Bstart, size_t Blen, typename T = uint16_t>
struct BitField
{
    T value; // zero-based, not shifted

    static constexpr T mask() { return ((1 << Blen)-1) << Bstart; }

    static T clear(T r) { return r & ~mask(); }

    void decode(T r) { value = (r & mask()) >> Bstart; }
    T encode(T r) { return clear(r) | ((value << Bstart) & mask()); }
    // etc.
};
using HzField = BitField<7, 3>;

关于c++ - 如何将Hz的 'convert'量更改为适当的字节/位格式?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56365318/

10-11 15:09