搜索
bottom↓
回复: 15

在keil 4下 遇到一个 idata的离谱的运算错误问题 ,大家帮忙看看

[复制链接]

出0入91汤圆

发表于 2023-1-9 10:06:28 | 显示全部楼层 |阅读模式
本帖最后由 ackyee 于 2023-1-9 10:09 编辑

程序大概是这样的

unsigned int idata a=0;
unsigned int idata b=0;


然后一个函数里这样调用


a=dat;   (dat是串口进来的  unsigned char 型)  测试的时候dat永远都发送1
b=a*100;    这里就会出错,每次 执行这一句 得到的结果都不一致  





然后离谱的事情是  把定义的idata 删除掉,  结果又正确了

或者更离谱的事是, 把 unsigned int idata b 改成 unsigned long idata b   结果也正确了


不知道是程序问题 还是 keil 的问题  还是其他啥问题,  单片机是 stc12c5a60s2


因为dat的数据发送的时候都是用1来替代的, 所以 这个*100不可能溢出,  而且  不加idata的时候 运算结果永远是正确的

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入475汤圆

发表于 2023-1-9 10:19:10 | 显示全部楼层
首先你确保你的dat是对的?为啥非得要从串口来?直接赋值不行吗?
纯软件仿真看一下单步执行的时候各个变量的变化,各个值是不是对的,哪里开始出错了

第二就是看你 的idata定义的变量是分配到了哪里的地址了,有没有超过实际芯片的位置,

单独运行这几句,不出错就是你其它地方影响了,

出0入91汤圆

 楼主| 发表于 2023-1-9 10:20:44 | 显示全部楼层
本帖最后由 ackyee 于 2023-1-9 10:24 编辑
1a2b3c 发表于 2023-1-9 10:19
首先你确保你的dat是对的?为啥非得要从串口来?直接赋值不行吗?
纯软件仿真看一下单步执行的时候各个变量 ...
(引用自2楼)


dat 的值是对的, 因为我串口同时输出a 和b 的值  a的值永远都是1,b的值是错的 ‘


刚刚试了 直接给a赋值1  问题也存在

出0入91汤圆

 楼主| 发表于 2023-1-9 10:22:20 | 显示全部楼层
1a2b3c 发表于 2023-1-9 10:19
首先你确保你的dat是对的?为啥非得要从串口来?直接赋值不行吗?
纯软件仿真看一下单步执行的时候各个变量 ...
(引用自2楼)

keil  idata 默认是 128-255地址段吧,这部分没特别设置过,  而且我把大部分变量都  注释掉了   data区总占用 只剩下100字节左右了,问题依旧

出0入91汤圆

 楼主| 发表于 2023-1-9 10:26:15 | 显示全部楼层
1a2b3c 发表于 2023-1-9 10:19
首先你确保你的dat是对的?为啥非得要从串口来?直接赋值不行吗?
纯软件仿真看一下单步执行的时候各个变量 ...
(引用自2楼)

卧槽 好像发现问题了, 把这个代码放到   串口中断的外面, 好像就不存在问题了,     现在怀疑是串口中断的堆栈区溢出了

出50入58汤圆

发表于 2023-1-9 11:15:28 | 显示全部楼层
题外话,楼主不是搞FPGA的吗?

出0入91汤圆

 楼主| 发表于 2023-1-9 12:45:17 | 显示全部楼层
鲜衣怒马 发表于 2023-1-9 11:15
题外话,楼主不是搞FPGA的吗?
(引用自6楼)

  这年头 啥都得会点

出0入0汤圆

发表于 2023-1-9 15:02:11 | 显示全部楼层
ackyee 发表于 2023-1-9 10:26
卧槽 好像发现问题了, 把这个代码放到   串口中断的外面, 好像就不存在问题了,     现在怀疑是串口中 ...
(引用自5楼)

keil 51记得默认只有函数返回地址放在堆栈里,局部变量用的是分析法,分析各个函数的调用关系,决定哪些变量可以放到一个物理地址。

出0入55汤圆

发表于 2023-1-9 15:25:59 来自手机 | 显示全部楼层
楼主打印是用printf(%d)吗?改成对应的,比如字节就用bd%,半字用d%,字用ld%,如果还是不行,直接用if认证一下结果,8位单片机用printf往往很奇怪

出0入0汤圆

发表于 2023-1-9 15:34:34 | 显示全部楼层
dat 强制转换到  int类型的试试a=  (unsigned int )dat;

出0入91汤圆

 楼主| 发表于 2023-1-9 16:50:35 | 显示全部楼层
xy3dg12 发表于 2023-1-9 15:02
keil 51记得默认只有函数返回地址放在堆栈里,局部变量用的是分析法,分析各个函数的调用关系,决定哪些 ...
(引用自8楼)

我相当于  UART 接收的  代码里  放了一个子函数,子函数里再加入了  刚才的 赋值操作, 现在把子函数的赋值操作  拿出来 直接放在UART的接收代码里   就不会出问题了

所以大概率是  UART 中断   加上 终端内部的函数嵌套 导致的 堆栈溢出了,现在感觉很多次实验下来 都指向问题  是堆栈溢出导致的  

出0入0汤圆

发表于 2023-1-9 17:34:31 | 显示全部楼层
看了标题就觉得是堆栈的问题。

51 idata xdata要注意的

出0入0汤圆

发表于 2023-1-9 17:41:10 | 显示全部楼层
ackyee 发表于 2023-1-9 16:50
我相当于  UART 接收的  代码里  放了一个子函数,子函数里再加入了  刚才的 赋值操作, 现在把子函数的 ...
(引用自11楼)

51由于自身的限制,所以它的C和现代CPU的C有很大区别,默认局部变量不是放在堆栈里的。
最好还是调试下汇编代码。

出0入475汤圆

发表于 2023-1-9 19:57:45 来自手机 | 显示全部楼层
楼主既然是中断函数里面跑的,对于51这类8位机,按照常理是尽量快速操作。那么临时变量首选通用data区域,这样操作起来cpu会少跑很多条指令,你不信看下汇编代码就知道了,以及能用byte的不要用双字节,更不要用4字节。所以为啥你非的弄个idata这些自己都搞不太懂的东西,

出0入91汤圆

 楼主| 发表于 2023-1-9 21:18:26 | 显示全部楼层
1a2b3c 发表于 2023-1-9 19:57
楼主既然是中断函数里面跑的,对于51这类8位机,按照常理是尽量快速操作。那么临时变量首选通用data区域, ...
(引用自14楼)

用idata 是因为我的这个程序里变量有点多 ,所以我把 int以上的  变量都用idata 标记了 ,这样不会造成  0-128区域 数据溢出的情况 ,结果今天碰到了堆栈溢出的问题了

出1310入193汤圆

发表于 2023-1-9 21:47:26 来自手机 | 显示全部楼层
莫名其妙的故障
差不多就是溢出
堆栈溢出,数字越界等等。就是这么无敌。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-16 05:50

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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