从一个变量的位到另一个变量的有效映射

时间:2015-06-23 07:25:44

标签: c++ c bit-manipulation

我有4个Uint32变量名为lowLevelErrors1,lowLevelErrors2 ...最多4个。这些变量代表低级错误。我需要将它们映射到名为userErrors的Uint64变量。 userError的每个位表示向用户显示的错误,由于一个或多个低级错误,可以设置该错误。换句话说,每个低级错误都映射到1个用户错误。可以将2个或更多低级别错误映射到同一用户错误。

让我们将其缩小为2x Uint8低级别错误和1x Uint8用户错误,以便我们看到一个示例。

示例:如果设置了以下任何低级错误{ERR_VOLT_LOW || ERR_NO_BATTERY || ERR_NOT_CHARGING}(对应于lowLevelErrors1的第0位,第2位和第3位),然后设置用户错误US_ERR_POWER_FAIL(这是userErrors的第5位)。

所以我能想到的唯一方法是为每个lowLevelErrors变量设置一个map数组,用于映射到userErrors的相应位。

/* Let's say the lowLevelErrors have to be mapped like this:
lowLevelErrors1 bit maps to userError bit
        0                         5 
        1                         1
        2                         5
        3                         5
        4                         0
        5                         2
        6                         7
        7                         0

lowLevelErrors2 bits maps to userError bit
        0                         1
        1                         1
        2                         0
        3                         3
        4                         6
        5                         6
        6                         4
        7                         7
*/

Uint8 lowLevelErrors1 = 0;
Uint8 lowLevelErrors2 = 0;
Uint8 userErrors = 0;

Uint8 mapLLE1[8] = {5, 1, 5, 5, 0, 2, 7, 0};
Uint8 mapLLE2[8] = {1, 1, 0, 3, 6, 6, 4, 7};

void mapErrors(void)
{
    for (Uint8 bitIndex = 0; bitIndex < 8; i++)
    {
        if (lowLevelErrors1 && (1 << i))  //If error bit is set
        {
            userErrors |= 1 << mapLLE1[bitIndex];  //Set the corresponding user error
        }
    }

    for (Uint8 bitIndex = 0; bitIndex < 8; i++)
    {
        if (lowLevelErrors2 && (1 << i))  //If error bit is set
        {
            userErrors |= 1 << mapLLE2[bitIndex];  //Set the corresponding user error
        }
    }

}

此实现的问题是需要映射数组。我将需要4x uint8数组[32] = 128 uint8变量,并且我们在微控制器上的内存不足。

有没有其他方法可以使用更少的RAM来实现相同的功能?

2 个答案:

答案 0 :(得分:2)

您有128个输入位,每个输入位都映射到0到63的位数。因此,这是128 * 6 = 768位的信息,除非有一些常规模式,否则至少需要96个字节的存储空间它

所以你需要至少96个字节;即使这样,它也将被存储为打包的6位整数。解包这些整数的代码可能比通过打包它们节省的32个字节花费更多。

所以你基本上有三个选择:一个128字节的数组,如你所说;打包的6字节整数;或者一些易于解包的错误代码的常规分配(如果修复了特定的错误代码映射,则不可能这样做。)

答案 1 :(得分:0)

由于您没有给出包含所有错误的完整示例,因此很难说什么是最好的&#34;&#34;方法,但我会构建一个&#34; mask&#34;和&#34;价值&#34;:

这样的事情:

struct Translate
{
    uint32_t mask;
    // Maybe have mask[4]?
    uint64_t value;
};

// If not mask[4], the 
Translate table[] = 
{
    {  ERR_VOLT_LOW | ERR_NO_BATTERY | ERR_NOT_CHARGING, 
       // If mask[4] then add 3 more values here - expect typically zeros
       US_ERR_POWER_FAIL },
    ... 
};

我不确定哪个更有意义,在表中有4个不同的值,或者有4个不同的表 - 这取决于你从LowLevel1和LowLevel2,LowLevel2和LowLevel4等出错的频率映射到相同的错误。但是,通过将多个错误的映射存储到一个值,您应该这样做。

现在,一旦我们有了数据结构,代码就变成了:

 for(auto a : table)
 {
     if (a.mask & lowLevelErrors1)
     {
       userErrror |= a.value; 
     }
  }