找回密码
 立即注册
查看: 1049|回复: 17

请大家帮忙看看乘除法结果数据跑飞的原因是什么 | 已解决,见8楼

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-12-18 09:07:02
已绑定手机

13

主题

25

回帖

139

积分

注册会员

积分
139
发表于 2025-11-14 23:29:06 | 显示全部楼层 |阅读模式
原因找到了,问题出在下面这条语句,原因详见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]。
  1. Calculation_ADC_rms ( )
  2. {
  3.         u8  i = 0 ;
  4.         u16 diff = 0;
  5.         u32 sum = 0;        //        乘积存放变量
  6.         u32 sum1 = 0;        //        乘积存放变量
  7.         u16 rms = 0;    //  返回值
  8.         diff = ADC_Buffer[0];
  9.     sum1 = diff*diff;
  10.     rms = (u16)sum1/diff;         //        如运算正确,则rms值=ADC_Buffer[0]。
  11.         return rms;
  12. }
复制代码
项目资源分配如下:
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, 下载次数: 54)
下面是所用到的库函数(擎天柱例程里面所附):
COMM.rar (194.09 KB, 下载次数: 61)

补充:该运算函数在乘数小于或者等于255时,返回值正确,只要大于255返回值就跑飞了。经测试,rms只返回了低8位。
请教大家是u32 sum1语句定义无效,还是rms = (u16)(sum1/diff)这条语句有问题呢?

  1. u16 Calculation_ADC_rms (u16 ADC_VAL )
  2. {
  3.         u8  i = 0 ;
  4.         u16 diff = 0;
  5.         u32 sum = 0;        //        乘积存放变量
  6.         u32 sum1 = 0;        //        乘积存放变量
  7.         u16 rms = 0;    //  返回值
  8.         ADC_VAL = 255;
  9.         diff = ADC_VAL;
  10.         ADC_VAL = 255;
  11.         diff = 255;                          //乘数只有小于或等于255时返回值正确
  12.     sum1 = ADC_VAL*ADC_VAL;
  13.     rms = (u16)(sum1/diff);
  14.     return rms;
  15. }
复制代码

已解决:由于乘数小于255时运算的结果正确,猜测是16位数据只有低8位参与了乘法运算,而8位数据的乘法是正确的,因此把乘数和被乘数均分拆为高、低8位,分别进行低8位、高8位的相乘,得出乘积的低16位和高16位,最后合并成32位乘积。
不过非常奇怪的是,32位数据除以16位数据结果是正确的,不知道为什么乘法运算不对,这个究竟是编译软件、库函数还是其他什么原因就不得而知了。






回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:587
  • 最近打卡:2025-12-18 12:29:34

9

主题

563

回帖

3809

积分

论坛元老

积分
3809
发表于 2025-11-15 11:43:01 | 显示全部楼层
这函数很奇怪,
定义函数都不声明参数变量类型和返回值变量类型吗?
这样做实际返回什么结果?
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:641
  • 最近打卡:2025-12-17 10:15:23
已绑定手机
已实名认证

123

主题

3278

回帖

8316

积分

版主

积分
8316
发表于 2025-11-15 14:45:53 | 显示全部楼层


函数未声明返回值,所以默认为void类型
此时只能return; 结束,返回一个值当然是不正常的
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-12-18 09:07:02
已绑定手机

13

主题

25

回帖

139

积分

注册会员

积分
139
发表于 2025-11-15 16:07:42 | 显示全部楼层
王*** 发表于 2025-11-15 14:45
函数未声明返回值,所以默认为void类型
此时只能return; 结束,返回一个值当然是不正常的
...

请问是修改成这样吗:u16 Calculation_ADC_rms()
修改后返回值还是不对,但是,如果不使用乘除法,直接赋值给rms并返回,如:rms = ADC_Buffer[0],返回值就是正确的,不知道是什么原因。谢谢。

点评

删除掉LIB库或者更新到最新的LIB试试?  详情 回复 发表于 2025-11-15 16:24
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-12-18 09:07:02
已绑定手机

13

主题

25

回帖

139

积分

注册会员

积分
139
发表于 2025-11-15 16:16:03 | 显示全部楼层
网*** 发表于 2025-11-15 11:43
这函数很奇怪,
定义函数都不声明参数变量类型和返回值变量类型吗?
这样做实际返回什么结果? ...

我是在 Calculation_ADC_rms函数里面直接调用ADC_Buffer的值参与运算。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:641
  • 最近打卡:2025-12-17 10:15:23
已绑定手机
已实名认证

123

主题

3278

回帖

8316

积分

版主

积分
8316
发表于 2025-11-15 16:24:33 | 显示全部楼层
kpf*** 发表于 2025-11-15 16:07
请问是修改成这样吗:u16 Calculation_ADC_rms()
修改后返回值还是不对,但是,如果不使用乘除法,直接 ...

删除掉LIB库或者更新到最新的LIB试试?
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-12-18 09:07:02
已绑定手机

13

主题

25

回帖

139

积分

注册会员

积分
139
发表于 2025-11-15 17:12:36 | 显示全部楼层
王*** 发表于 2025-11-15 16:24
删除掉LIB库或者更新到最新的LIB试试?

我之前是用的擎天柱例程里面所附的库文件,这个是下载地址:https://www.stcaimcu.com/forum.p ... 39&page=1#pid130776
从论坛主页下载的最新库函数
{8CCF70B5-534F-43B6-9876-546CB241785C}.png.jpg
但编译时出了好多以下的错误,是不是引脚定义错了呢?
compiling main.C...
../COMM/AI8051U.H(32): error C146: 'PCON': invalid base address
../COMM/AI8051U.H(33): error C146: 'PCON': invalid base address
../COMM/AI8051U.H(34): error C146: 'PCON': invalid base address
../COMM/AI8051U.H(35): error C146: 'PCON': invalid base address
../COMM/AI8051U.H(36): error C146: 'PCON': invalid base address
../COMM/AI8051U.H(37): error C146: 'PCON': invalid base address
../COMM/AI8051U.H(38): error C146: 'PCON': invalid base address
../COMM/AI8051U.H(39): error C146: 'PCON': invalid base address
../COMM/AI8051U.H(52): error C146: 'TMOD': invalid base address
../COMM/AI8051U.H(53): error C146: 'TMOD': invalid base address
../COMM/AI8051U.H(54): error C146: 'TMOD': invalid base address
../COMM/AI8051U.H(55): error C146: 'TMOD': invalid base address
../COMM/AI8051U.H(56): error C146: 'TMOD': invalid base address

而且之前DS1302的头文件编译通过,用新的库函数后出了以下错误提示,不知是什么原因。
DS1302.H(15): error C129: missing ';' before 'code'
{39497003-82AC-49FC-9D85-1E9AB40C0BBD}.png.jpg



回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:682
  • 最近打卡:2025-12-18 09:49:39
已绑定手机

32

主题

370

回帖

3019

积分

论坛元老

机长

积分
3019
发表于 2025-12-2 19:54:51 | 显示全部楼层
  1. sum1 = ADC_VAL * ADC_VAL;
复制代码
你要是瞅一眼生成的汇编就能一目了然了。两个数进行数学运算,会自动强转成范围更大的那个,但赋值不算运算
因为ADC_VAL这个变量是u16的,两个u16相乘结果必然还是u16的。你肯定要说sum1是u32的,那只是把之前已经是u16的乘积放到sum1的低16位而已。
然后再延伸一下,当32位除以16位的时候,会自动使用类型更大的那个,那结果也是32位的,也就是你发现的并没有问题

你可以验证下,如果ADC_VAL是301的话,那么sum1的结果就是25065。25065 = 0x000061E9 = 0x161E9 = 90601 = 301×301

解决办法极其简单:
  1. sum1 = (u32)ADC_VAL * ADC_VAL;
复制代码
以上方案有问题,更正如下:
  1. sum1 = ((u32)ADC_VAL) * ADC_VAL;
复制代码




2 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
业余撸代码,专业开飞机 https://gitee.com/STC-MCU
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:631
  • 最近打卡:2025-12-18 07:04:04

4

主题

509

回帖

2905

积分

金牌会员

积分
2905
发表于 2025-12-2 20:56:45 | 显示全部楼层
hsr*** 发表于 2025-12-2 19:54
你要是瞅一眼生成的汇编就能一目了然了。两个数进行数学运算,会自动强转成范围更大的那个,但赋值不算运算 ...

有道理哎
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-12-18 09:07:02
已绑定手机

13

主题

25

回帖

139

积分

注册会员

积分
139
发表于 2025-12-2 23:18:19 | 显示全部楼层
hsr*** 发表于 2025-12-2 19:54
你要是瞅一眼生成的汇编就能一目了然了。两个数进行数学运算,会自动强转成范围更大的那个,但赋值不算运算 ...

谢谢老机长的解答。我按照你的办法试过了还是不行,不管是用8位编译还是32位编译都不行,实在是想不通问题出在哪里了。下面这个图是32位编译,如果乘数为255,显示FF正确,如果乘数为256,则结果就是0,只保留了低16位。
屏幕截图 2025-12-02 232116.jpg
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-12-18 16:22 , Processed in 0.135719 second(s), 98 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表