从范围值使用 for 循环

Using for loop from range value

我从中得到了一些数据table:

是否可以使用(for循环)?

最近用了(if else)函数,但是好像太长了

我是 C 编程新手。这是我完成的代码(如果还有的话)功能:

        if (0 < result < 409  ) // 0 to 408
        {
            volt = 0 ;
        }
        else if (409 < result < 818 ) //408 to 817
        {
            volt = 1 ;
        }
        else if (818 < result < 1227 ) //818 to 1226
        {
            volt = 2 ;
        }
        else if (1227 < result < 1636 ) //1227 to 1635
        {
            volt = 3 ;
        }
        else if (1636 < result < 2045 ) // 1636 to 2044
        {
            volt = 4 ;
        }
        else if (2045 < result < 2454 ) // 2045 to 2453
        {
            volt = 5 ;
        }
        else if (2454 < result < 2863 ) //2454 to 2862
        {
            volt = 6 ;
        }
        else if (3271 < result < 2863 ) //2863 to 3271
        {
            volt = 7 ;
        }
        else if (3860 < result < 3272 ) //3272 to 3860
        {
            volt = 8 ;
        }
        else if (4094 < result < 3861 ) //3861 to 4094
        {
            volt = 9 ;
        }

        else if (result >= 4095 ) //4095++
        {
            volt = 10 ;
        }

首先,409 < result < 818 不是一个表达式,它的作用与您认为它在 C 中的作用相同。它在数学上可能有意义,但 C 需要您稍微具体一些:

(409 < result) && (result < 818)

Explaining further, the expression 409 < result < 818 will first work out the truth value for 409 < result, giving either zero or one, which we'll call X. Then the result of that will be fed into X < 818 to give a new truth value.

So, in that case, you'll always get true simply because an X of zero or one is always less than 818. The following program shows this in action:

#include <stdio.h>

void Between400And600 (int n) {
    printf ("%d between 400 and 600? Old = %d, new = %d\n",
        n,
        400 < n < 600,
        (400 < n) && (n < 600));
}

int main (void) {
    Between400And600 (111);
    Between400And600 (555);
    Between400And600 (999);
    return 0;
}

The first result on each line is your original one, old. The second is my suggested fix, new. As you can see, all of your expressions give 1 (true) while the fix only gives true for the value between the limits:

111 between 400 and 600? Old = 1, new = 0
555 between 400 and 600? Old = 1, new = 1
999 between 400 and 600? Old = 1, new = 0

最重要的是,您的某些范围检查已关闭,数字的顺序不正确。除了我不知道的一些高阶数学的可能性之外,没有数字可以同时大于 3860 和小于 3272

else if (3860 < result < 3272 ) //3272 to 3860

而且,最重要的是,独占使用 < 而不是 <= 意味着您 缺少 某些情况,例如何时result409.

如果您只是想用一种简洁的方式进行映射,我会选择类似的方法:

unsigned int getVolt (unsigned int adc) {
    if (adc <  409) return 0;
    if (adc <  818) return 1;
    if (adc < 1227) return 2;
    if (adc < 1636) return 3;
    if (adc < 2045) return 4;
    if (adc < 2454) return 5;
    if (adc < 2863) return 6;
    if (adc < 3272) return 7;
    if (adc < 3681) return 8;
    if (adc < 4095) return 9;
    return 10;
}

并用以下方式调用它:

volt = getVolt (result);

它更短、更清晰,因此更不容易出错。

鉴于除最后一个以外的所有项都是 409 的倍数,您可以将其进一步缩短,例如:

unsigned int getVolt (unsigned int adc) {
    if (adc < 4090) return adc / 409;
    if (adc < 4095) return 9;
    return 10;
}

但是在那种情况下你会失去清晰度(和灵活性,如果阈值发生变化)所以我可能会坚持我的第一个实现,因为它不是 太大 .当然,如果最终是五十个 if 语句,我可能会寻找更好的解决方案,但十行代码也不错。


如果您想使代码相对较短,但仍允许进行大量检查,则可以 table 使用类似于以下内容的驱动程序:

unsigned int getVolt (unsigned int adc) {
    const static unsigned thresholds[] = {
         409,  818, 1227, 1636, 2045, 2454, 2863, 3272, 3681, 4095,
         // as many entries as you need.
    };
    const static int sz = sizeof(thresholds) / sizeof(*thresholds);

    for (int idx = 0; idx < sz; idx++)
        if (adc < thresholds[idx])
            return idx;

    return sz;
}

有一个限制,即 return 值必须从零开始连续(与索引相同,0..9 加上默认值 10)但这没关系你的具体情况。

同上 paxdiablo 所说的第一部分,但为了回答您的问题,您 可以 将其放入 for 循环中,但是如果您查看您的数字,范围每个 if/else if 代码块中的数字是相同的; 409. 然后在该块内,设置伏特 = 您所在部分的编号。在第一部分中设置伏特 = 0,在第二部分中设置伏特 = 1,依此类推。由于每个部分的范围每次都增加 409,因此您可以将您编写的所有内容替换为 volt = result / 409.

记住(假设结果是一个整数)c 语言将使用整数除法处理 result/409。因此,如果结果 >= 0 且 < 409,则 result/409 等于 0。如果结果 >= 409 且 < 818,则 result/409 等于 1,依此类推。然而,这确实意味着如果结果 = 4094,伏特将等于 9,这不是您的图表所说的应该发生的情况,但可能是您想要的。

如果您需要做类似的事情(范围不断增加),那么您可能会想要使用 for 循环。 for 循环也应该更快(我认为)。你必须再次利用你的范围以 409 的恒定增量上升的事实,所以做类似

的事情
for (int i = 0; i < max; i++ )
{
    int lowerBound = (result / i);
    int upperBound = (result / i + 408);
    //or something
    //...other necessary code here...
}

它只是一个 12 位(4096 计数)ADC,具有 10V 的满量程输入。它在该范围内是线性的,因此不需要 table 或循环:

#define ADC_BITS       12
#define ADC_MIN_VOLTS  0
#define ADC_MAX_VOLTS  10

#define ADC_COUNTS     (1 << ADC_BITS)
#define ADC_VRANGE     (ADC_MAX_VOLTS - ADC_MIN_VOLTS)


double adc_counts_to_volts(int counts)
{
    return counts * (double)ADC_VRANGE / ADC_COUNTS;
}

您可以将其替换为整数版本以提供整数输出:

int adc_counts_to_volts(int counts)
{
    return counts * ADC_VRANGE / ADC_COUNTS;
}