【问题标题】:calculation in C for C2000 deviceC2000 设备的 C 语言计算
【发布时间】:2014-05-22 12:57:38
【问题描述】:

我的 C 代码有问题。我有一个 ADC,它将用于确定是否关闭(跳闸区)我正在使用的 PWM。但我的计算似乎没有按预期工作,因为 ADC 在错误的电压电平下关闭了 PWM。我将变量初始化为:

float32 current = 5;
Uint16 shutdown = 0;

然后我计算为:

// Save the ADC input to variable
adc_info->adc_result0 = AdcRegs.ADCRESULT0>>4;              //bit shift 4 steps because adcresult0 is effectively a 12-bit register not 16-bit, ADCRESULT0 defined as Uint16

current = -3.462*((adc_info->adc_result0/1365) - 2.8);

// Evaluate if too high or too low
if(current > 9 || current < 1)
{
    shutdown = 1;
}
else
{
    shutdown = 0;
}

之后我使用这个 if 语句:

if(shutdown == 1)
{
    EALLOW;                                                 // EALLOW protected register
    EPwm1Regs.TZFRC.bit.OST = 1;                // Force a one-shot trip-zone interrupt
    EDIS;                                                   // end write to EALLOW protected register
}

所以如果电流高于 9 或低于 1,我想触发 PWM,这应该分别与 3428 (0xD64) 的 adc 结果一致。 ADC 值分别对应于电压 0.2V 和 2.51V。 ADC 在电压 0 和 3V 之间以 12 位精度进行测量。

但是,事实并非如此。相反,跳闸区在大约 1V 和 2.97V 时关闭。那我做错了什么?

【问题讨论】:

  • 为什么不直接使用adc_info-&gt;adc_result0呢? if ((273.0 &lt;= adc_info-&gt;adc_result0) &amp;&amp; (adc_info-&gt;adc_result0 &lt;= 3428.0)) shutdown = 0; else shutdown = 1;
  • if current is above 9 or below 1 which 单位在哪里? Ampsmilli amps 还是什么?
  • pmg - 如果我想更改限制,设置限制会更容易。如果不先将它们转换为安培,这些样本不会告诉我任何事情。 SGG - 单位是安培。 1/1365 是 V/样本,-3.462 是 A/V

标签: c embedded adc


【解决方案1】:
adc_info->adc_result0/1365

假设浮点数时您是否在此处进行了整数除法

试试这个修复:

adc_info->adc_result0/1365.0

另外,@pmg 的建议很好。当您可以立即将 ADC 值与已知界限进行比较时,为什么还要花费周期来计算电压?

if (adc_info->adc_result0 < 273 || adc_info->adc_result0 > 3428)
{
    shutdown = 1;
}
else
{
    shutdown = 0;
}

如果您不想硬编码计算的界限(这是完全可以理解的),那么将它们定义为根据您想要硬编码的值计算得出:

#define VOLTAGE_MIN 0.2
#define VOLTAGE_MAX 2.51
#define AREF 3.0
#define ADC_PER_VOLT (4096 / AREF)

#define ADC_MIN (VOLTAGE_MIN * ADC_PER_VOLT) /* 273 */
#define ADC_MAX (VOLTAGE_MAX * ADC_PER_VOLT) /* 3427 */

/* ... */
    shutdown = (adcresult < ADC_MIN || adcresult > ADC_MAX) ? 1 : 0;
/* ... */

当您确定掌握了 C 语言中的 integer division rules 后,请考虑在您的代码风格中添加一些内容:始终使用小数编写常数系数和除数(以确保它们获得浮点类型),例如10.0 而不是 10除非你明确表示整数除法和截断。有时使用适当的后缀指定float literal precision 也是一个好主意。

【讨论】:

  • adc_result0 在结构中被定义为 Uint32。
  • 所以我是对的。您进行整数除法,这会截断结果的小数部分。通过将1365 设为浮点常量而不是整数来强制它浮动。
  • 现在可以直接使用边界了。但它仍然不能解释我在计算中做错了什么。我在 matlab 中做了完全相同的计算,得到了我期望的结果。
  • 因为预期的类型是float32,所以使用 float 字面量!不要使用 double 文字,不要使用 int 文字。 VOLTAGE_MIN 0.2f4096f / AREF 等等。
  • 这样我就不会再犯同样的错误,只要我指定其他常量与我发送到的变量的数据类型相同,我的陈述就可以了吗?我想在计算浮点数时使用我的 Uint32(这是一个很长的,顺便说一句)变量是可以的,但我使用的常量也需要是浮点数?还是我误会了?
猜你喜欢
  • 2012-05-14
  • 2023-04-09
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
  • 2014-05-08
相关资源
最近更新 更多