原因找到了,问题出在下面这条语句,原因详见8楼机长的分析解答。感谢大家特别是机长和14楼的指点。
sum1 = ADC_VAL*ADC_VAL;
上面这条语句,我曾用sum1 = (u32)(ADC_VAL*ADC_VAL)语句,一直困扰在这里。按照机长的分析,由于ADC_VAL*ADC_VAL的乘积是16位,所以前面的 (u32)强制转换32位没起作用,高位都补0了,因此正确的语句就是:
sum1 =(u32)ADC_VAL*ADC_VAL;
在调试一个C51程序时需要用到乘除法,但结果跑飞了,请大家帮忙看看是哪里出错了。
ai8051u的P1.7对输入电压进行ADC采样20次,采样后的数据放在数组 u16 idata ADC_Buffer[20]中,采样数值限制在 1290-2757之间。
在调用Calculation_ADC_rms ( )函数时,返回值跑飞了,但是如果直接返回idata ADC_Buffer中的任意值又是正确的。
下面是Calculation_ADC_rms ( )函数:返回的rms值并不等于ADC_Buffer[0]。
- Calculation_ADC_rms ( )
- {
- u8 i = 0 ;
- u16 diff = 0;
- u32 sum = 0; // 乘积存放变量
- u32 sum1 = 0; // 乘积存放变量
- u16 rms = 0; // 返回值
-
-
- diff = ADC_Buffer[0];
- sum1 = diff*diff;
- rms = (u16)sum1/diff; // 如运算正确,则rms值=ADC_Buffer[0]。
-
- return rms;
- }
复制代码 项目资源分配如下:
P1.7为ADC采样输入,采样数值限制在 1290-2757之间
P0^0-7接LCD1602 的 LCD_B0-B7
P1^0接LCD_RS,P1^1接LCD_RW,P1^2接LCD_ENA。
下面附上完整的项目:
ai8051+AD - test.rar
(129.95 KB, 下载次数: 55)
下面是所用到的库函数(擎天柱例程里面所附):
COMM.rar
(194.09 KB, 下载次数: 62)
补充:该运算函数在乘数小于或者等于255时,返回值正确,只要大于255返回值就跑飞了。经测试,rms只返回了低8位。
请教大家是u32 sum1语句定义无效,还是rms = (u16)(sum1/diff)这条语句有问题呢?
- u16 Calculation_ADC_rms (u16 ADC_VAL )
- {
- u8 i = 0 ;
- u16 diff = 0;
- u32 sum = 0; // 乘积存放变量
- u32 sum1 = 0; // 乘积存放变量
- u16 rms = 0; // 返回值
- ADC_VAL = 255;
- diff = ADC_VAL;
- ADC_VAL = 255;
- diff = 255; //乘数只有小于或等于255时返回值正确
- sum1 = ADC_VAL*ADC_VAL;
- rms = (u16)(sum1/diff);
- return rms;
- }
复制代码
已解决:由于乘数小于255时运算的结果正确,猜测是16位数据只有低8位参与了乘法运算,而8位数据的乘法是正确的,因此把乘数和被乘数均分拆为高、低8位,分别进行低8位、高8位的相乘,得出乘积的低16位和高16位,最后合并成32位乘积。
不过非常奇怪的是,32位数据除以16位数据结果是正确的,不知道为什么乘法运算不对,这个究竟是编译软件、库函数还是其他什么原因就不得而知了。
|