【问题标题】:Efficient Average of Three Values in CC中三个值的有效平均值
【发布时间】:2016-03-15 23:30:42
【问题描述】:

我们正在从引脚读取一些信号,并根据这些读数设置更多事件。

为了安全起见,我想对引脚进行 3 次采样,比较三个值并使用最常见的值(即样本 A 为 1,B 为 3,C 为 1,我想使用 1,如果 AB 和C 都是 2 然后使用 2 但是如果 A 是 1 , B 是 2 并且 C 是 3,我想再次捕获三个样本。

目前我正在使用:

int getCAPValues (void)
{
//  Get three samples to check CAP signals are stable:  

        uint32_t x = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN;           // First set of CAP values
        for (uint32_t i = 0; i < 7; i++) dummy = i;                                                     // Pause
        uint32_t y = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN;           // second set
        for (uint32_t i = 0; i < 7; i++) dummy = i;                                                     // Pause
        uint32_t z = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN;           // third set

        if (x == y) || (x == z)
        {
            //use the x value
        }
        else if (y == z)
        {
            // use the y value
            x = y;
        }
        else
        {           
            x = -1;
        }

    return x;
}

但这对我来说似乎不是很有效,有没有更好的方法来做到这一点?

这是在 C 语言的 SAMD21 Xplained Pro 开发板上。

编辑:

我已根据答案更改了代码,仅读取“z”值(如果将要使用),并使用 delay_us() 而不是虚拟循环:

int getCAPValues (void)
{
//  Get three samples to check CAP signals are stable:  

        uint32_t x = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN;           // First set of CAP values
        delay_us(1);
        //for (uint32_t i = 0; i < 7; i++) dummy = i;                                                   // Pause
        uint32_t y = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN;           // second set
        // Using most common value, or error code of -1 if all different

        if (!(x == y))
        {
            delay_us(1);
            //for (uint32_t i = 0; i < 7; i++) dummy = i;                                               // Pause
            uint32_t z = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN;       // third set
            if (x == z)
            {
                // use the x/z value
                return x;
            }
            else if (y == z)
            {
                // use the y/z value
                return y;
            }
            else
            {           
                return -1;
            }
        }
    return x;
}

【问题讨论】:

  • 编译器可能会优化出for (uint32_t i = 0; i &lt; 7; i++) dummy = i;,因为它是无操作的。改用睡眠。
  • 听起来更适合 codereview.stackexchange.com
  • 我认为取值的逻辑无法进一步改进。为什么你认为它效率低下?
  • 如果x == y 测试z 没有意义,但除此之外,它看起来对我来说非常理想。也许尽管 OP 希望函数在每次迭代中花费大致相同的时间。不过,您需要修复那个“延迟”循环。
  • 您计算的是“模式”,而不是“平均值”。

标签: c processing-efficiency


【解决方案1】:

如果x==y,您将使用x 的值。因此,在这种情况下,您可以躲避第三次阅读。

我不知道你的价值观有多不稳定,但如果有争议的价值观实际上很少见,它可以有效地几乎翻倍性能以避免第二次延迟。

确实,如果它们并不罕见,那么整个理由可能是无效的。

int getCAPValues (void)
{
//  Get three samples to check CAP signals are stable:  

        uint32_t x = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN;           // First set of CAP values
        for (uint32_t i = 0; i < 7; i++) dummy = i;                                                     // Pause
        uint32_t y = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN;           // second set
        if(x!=y){
            //x & y are different. Get a tie-breaker...
            for (uint32_t i = 0; i < 7; i++) dummy = i;                                                     // Pause
            uint32_t z = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN;           // third set
            if (y == z) {
                // use the y value
                x = y;
            } else if(x!=z){
                //tie-breaking failed...
                x=-1;
            }
        }
        return x;
}

PS:我也认为你应该使用 `usleep()' 而不是虚拟循环。这取决于您的平台上可用的内容。

【讨论】:

  • 也许是 usleep() 而不是 sleep()。另外你可以在y==z 时直接return y(不分配x)。 -1 相同。
  • @AndyHall 我错过了最后一个小调整,避免了y!=z 时的最终 if 语句。享受吧。
【解决方案2】:

如果您可以假设xyz01。然后你可以只使用x+y+z&gt;1(如果它们中的大多数是1,那么总和大于1,比较计算结果为1,否则计算结果为0)。

否则,您的(第二个)解决方案可能是最有效的。至少如果你不知道结果的概率。除了休眠一微秒,这将是最耗时的操作。

您应该考虑的是,由于读取可能是非易失性的,因此如果您实际执行第三次读取,它可能会有所不同。此外,您也许应该考虑是否需要完全重新阅读。例如,如果您认为如果来自端口的前三个读取都不同,并且第四个读取等于第二个或第三个,您可以这样做,您可以将其用作优化。例如:

 x = read_port();
 y = read_port();

 if( x == y )
    return x;

 for(;;) {
    z = read_port();
    if( z == x || z == y )
        return z;
    x = y;
    y = z;
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    • 2017-02-06
    • 2020-03-19
    • 2015-05-03
    相关资源
    最近更新 更多