我想用PIC18F14K50的模数转换器外设计算电压。结果在0-1023 (10位)之间.所以我用了这个简单的计算:
uint16_t voltage = ADC_Result * 5000 / 1023;然而,结果是不正确的。我猜发生了算术溢出。我尝试了许多括号的组合,改变元素的顺序等等。
使用下面的代码,当ADC_Result为1023时,最好的结果是4088;这实际上离5000很远。
uint16_t voltage = ADC_Result * (5000 / 1023);我应该怎么做才能在上述计算中得到更好的结果?请不要建议浮点数,因为它们会在MCU中造成灾难!他们使用了大量的资源,却没有任何真正的好处。
发布于 2020-06-19 16:05:44
您可以在中间乘法中使用更宽的类型,例如:
uint16_t voltage = (uint32_t)ADC_Result * 5000 / 1023;编辑
如果1023的除法太慢,则可以通过将5000 / 1023更改为5005 / 1024来获得大致相等的转换,这可以为除法使用快速的位移位:
uint16_t voltage = (uint32_t)ADC_Result * 5005 >> 10;注: 1023 * 5005 / 1024≃5000.1123
发布于 2020-06-19 16:06:01
对于此计算,应使用更宽的整数类型,如uint32_t。
在您的例子中,1023 * 5000 == 3192 (因为实际结果5115000不适合),所以这是不正确的。5000 / 1023 == 4,这是整数除法的预期结果。将ADC_Result除以1023将导致同样的行为。
您可以将其计算到uint32_t中,然后检查它是否适合uint16_t
uint32_t result_tmp = ADC_Result * (5000 / 1023);
uint16_t result;
if (result > 0xffff) {
// this won't fit
} else {
result = (uint16_t) result_tmp;
}发布于 2020-06-20 01:14:39
我该怎么做才能在上面的计算中得到更好的结果?
OP的代码溢出了1‘6位的数学。
为了得到一个正确和全面的结果,使用更广泛的数学和偏移量。
// uint16_t voltage = ADC_Result * 5000 / 1023;
uint16_t voltage = (ADC_Result * 5000LU + 1024u/2) / 1024u;
// or
#include <stdint.h>
...
uint16_t voltage = (ADC_Result * UINT32_C(5000) + 1024u/2) / 1024u;L in 5000LU至少提供了32位的数学运算.
使用U进行可能更简单/更快的数学计算,并且在ADC_Result不是负的情况下进行更简单的舍入。
+ 1024/2的效果是从圆到最近而不是截断。
考虑到A/D转换器的通常特性,使用1024而不是1023进行正确的缩放。副作用: 1024的速度更快,是2的力量.
https://stackoverflow.com/questions/62474149
复制相似问题