C中三个值的有效平均值
我们正在读取一些引脚信号,并根据此读数设置更多事件。
为了安全起见,我想对引脚进行3次采样,比较三个值并使用最常见的值(即样本A是1,B是3,C是1,如果AB和C都是,我想使用1 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;
}
如果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()'而不是虚拟循环。 这取决于您的平台上可用的功能。
如果您可以假设x
, y
和z
是0
或1
。 然后你可以使用x+y+z>1
(如果它们大多数是1
那么总和大于1
,比较结果为1
,否则结果为0
)。
否则你的(第二个)解决方案可能是最有效的。 至少如果你不知道结果的可能性。 此外,睡眠时间为1微秒,这将是最耗时的操作。
你应该考虑的是,因为读取可能是非易失性的,所以如果你真的做了第三次读取,它可能会有所不同。 你也应该考虑是否需要重新阅读。 例如,如果您认为如果从端口读取的前三个读数都是不同的,并且第四个读取值等于第二个或第三个读取值,那么您可以使用它作为优化。 例如:
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;
}
链接地址: http://www.djcxy.com/p/31079.html
上一篇: Efficient Average of Three Values in C
下一篇: Maven set dependency mediation strategy to newest rather than nearest