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

Efficient mapping from bits of one variable to another

本文关键字:变量 另一个 有效 映射 一个      更新时间:2023-10-16

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

让我们将其缩小到2个Uint8低级别错误和1个Uint 8用户错误,这样我们就可以看到一个示例。

示例:如果设置了以下任何低级别错误{ERR_VOLT_low|ERR_NO_BATTERY|ERR_NOT_CHARGING}(对应于lowLevelErrors1的位0、位2和位3),则设置用户错误US_ERR_POWER_FAIL(即userErrors的位5)。

因此,我能想到的唯一方法是为每个lowLevelErrors变量创建一个映射数组,用于映射到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来实现相同的功能?

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

因此,您至少需要96个字节;即便如此,它也将被存储为压缩的6位整数。解包这些整数的代码可能比打包它们节省的32个字节花费更多。

因此,您基本上有三种选择:如您所建议的,一个128字节的数组;压缩的6字节整数;或者更容易解包的错误代码的一些规则分配(如果特定的错误代码映射是固定的,则这是不可能的)。

由于您还没有给出一个包含所有错误的完整示例,因此很难说什么是"最佳"方法,但我会构建一个"掩码"answers"值"的表:

类似这样的东西:

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; 
     }
  }
相关文章: