打印

求解 STC keil 数组定义在idata中赋值出错的问题

[复制链接]
2906|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
沙发
小了个明|  楼主 | 2017-7-27 10:28 | 只看该作者
RF_BufRam[0]=RF_DataRam[0];
RF_BufRam[1]=RF_DataRam[1];
RF_BufRam[2]=RF_DataRam[2];
将数组进行赋值运算    发现第RF_BufRam[1], RF_BufRam[2] 组赋值结果正确, RF_BufRam[0]的仿真数据居然没有等于RF_DataRam[0]。
数组定义在idata     ,如果把idata去掉后赋值正常
这是为什么?

使用特权

评论回复
板凳
小了个明|  楼主 | 2017-7-27 10:30 | 只看该作者
unsigned char   idata RF_DataRam[4];      //PT2262 2246总长度为24BIT
unsigned char   idata RF_BufRam[4];      //PT2262 2246总长度为24BIT         把idata去掉后运算结果正常

使用特权

评论回复
地板
小了个明|  楼主 | 2017-7-27 10:32 | 只看该作者
还有一个问题  这段RF解码程序以前在STM8 IAR的是没问题的  现在移植到STC后经常运行一段时间后就死掉了。很头疼啊

使用特权

评论回复
5
ningling_21| | 2017-7-27 11:42 | 只看该作者
小了个明 发表于 2017-7-27 10:32
还有一个问题  这段RF解码程序以前在STM8 IAR的是没问题的  现在移植到STC后经常运行一段时间后就死掉了。 ...

是不是在赋值的时候,数组的内容被(在中断内)改变了?

使用特权

评论回复
6
小了个明|  楼主 | 2017-7-27 11:59 | 只看该作者
ningling_21 发表于 2017-7-27 11:42
是不是在赋值的时候,数组的内容被(在中断内)改变了?

恩,这段程序就在PCA捕获中断里面的。

使用特权

评论回复
7
小了个明|  楼主 | 2017-7-27 12:04 | 只看该作者
ningling_21 发表于 2017-7-27 11:42
是不是在赋值的时候,数组的内容被(在中断内)改变了?

仿真的时候   watch窗口看变量  RF_DataRam[0]=0X35,  
单步运行RF_BufRam[0]=RF_DataRam[0];
赋值过来RF_BufRam[0]却等于0X24?
后面RF_BufRam[1],RF_BufRam[2]的结果都没问题

使用特权

评论回复
8
小了个明|  楼主 | 2017-7-27 12:44 | 只看该作者
这个数组只有在PCA中断内使用,其他地方都没有调用。
而且现在只开了PCA捕获中断和定时器中断,应该不是被其他程序打乱了。

使用特权

评论回复
9
ningling_21| | 2017-7-27 14:44 | 只看该作者
小了个明 发表于 2017-7-27 12:44
这个数组只有在PCA中断内使用,其他地方都没有调用。
而且现在只开了PCA捕获中断和定时器中断,应该不是被 ...

干脆去掉 idata 算了或换为 data

使用特权

评论回复
10
小了个明|  楼主 | 2017-7-27 17:33 | 只看该作者
去掉可以解决问题,但是解决的不明不白啊。
data就只有128byte,以后其他地方也出现这问题怎么办?

使用特权

评论回复
11
小了个明|  楼主 | 2017-7-27 17:33 | 只看该作者
ningling_21 发表于 2017-7-27 14:44
干脆去掉 idata 算了或换为 data

使用特权

评论回复
12
逍遥派掌门| | 2017-7-28 14:24 | 只看该作者
volatile

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
小了个明 + 1 很给力!
13
linqing171| | 2017-7-28 22:06 | 只看该作者
把赋值运算的反汇编贴上来。

使用特权

评论回复
14
小了个明|  楼主 | 2017-7-29 08:51 | 只看该作者

应该是编译器把运算优化了,感谢你的帮助!

使用特权

评论回复
15
小了个明|  楼主 | 2017-7-29 08:56 | 只看该作者
linqing171 发表于 2017-7-28 22:06
把赋值运算的反汇编贴上来。


这是赋值的反汇编,果然加了volatile  就好了。
前辈可以解释一下吗?没有学过汇编直接写C。
这段代码我猜是编译器没有直接从 RF_DataRam[0]取值,而是直接从寄存器中取了个变量赋值。这样理解对吗?

使用特权

评论回复
16
linqing171| | 2017-7-29 09:25 | 只看该作者
小了个明 发表于 2017-7-29 08:56
这是赋值的反汇编,果然加了volatile  就好了。
前辈可以解释一下吗?没有学过汇编直接写C。
这段代码我 ...

代码贴的不全。
RF_BufRam[0]=R7
RF_BufRam[1]= idata[0x19]
RF_BufRam[2]= idata[0x1A]
这个最前面的R7是从很久之前的来的。

我大胆猜测,根本原因是  你调用这个函数的的地方(上级函数)使用了using,而本函数没有使用using。并且你默认开启了C51的ARG功能导致的。

对于加了volatile好了,是因为volatile不让它从缓存的R7取数,而是重新取了一遍。 如果真的是我说的这个alias register原因导致的,如果你有移位、传递变量过多等等情况下,均会很多种错。

你先单步走到这里,看psw里面的RS也就是寄存器bank组是否是0。然后看看反汇编里面是有使用的AR7.

使用特权

评论回复
17
小了个明|  楼主 | 2017-7-29 09:57 | 只看该作者
linqing171 发表于 2017-7-29 09:25
代码贴的不全。
RF_BufRam[0]=R7
RF_BufRam[1]= idata[0x19]

这段函数的确是在PCA中断中调用的,   void PCA_isr() interrupt 7 using 1     使用了  using 1   !

1.  这个截图使用的是R0,因为 我改回来了idata
unsigned char  idata RF_DataRam[4]={0,0,0,0};      //PT2262 2246总长度为24BIT
unsigned char  idata RF_BufRam[4];      //PT2262 2246总长度为24BIT
而上一张图定义用的是xdata  ,因为昨天一直在修改程序做实验没有改回来。可能会误导大家了
unsigned char xdata RF_BufRam[4];      //PT2262 2246总长度为24BIT

2.alias register  在这里是什么意思?有什么办法可以关闭或者解决吗?我百度了没有找到答案。希望前辈如果不耽误时间的话,可以再次帮忙解答一下。

使用特权

评论回复
18
linqing171| | 2017-7-29 11:07 | 只看该作者
你的图的左边,寄存器的PSW的RS值为1,说明你这个函数或者上级函数using 1了。
而你右边图的C:135A行直接把 07的值放到了@R0页就是1C地址的RF_BufRam[0],而参考你前面有个if里面使用了RF_DataRam[0], (你的汇编没有抓到此处),我估计是RF_DataRam[0]被分配到了R7,下面第一次用的时候直接从R7取了。
可是在PSW的RS不是0的情况下,R7和07地址不是一个。

解决方案1:
你把这个函数也加上using 1,你会发现C:0x135A的反汇编会变为 MOV @R0,0x0F

解决方案2:
禁止使用R7的别名AR7,
2.1  把Project、Options、C51 里面的 Don't use absolute register accesses勾上,这样所有的函数都没有办法使用别名了。对于8051 MOV R0,R1 这种指令就从 MOV R0,0x01这么一条变为经过其它寄存器中转的两条了。比如XCHG A,R2 ; XCHG A,R1 ; 或者 MOV A,R2; MOV R1,A 也是两条指令,不过破坏了A。
2.2 在Project Options 的Misc Controls里面填上  NOAREGS ,缺点同上。
2.3 在这个函数的前面加上单独pragama加上  NOAREGS,这样其它函数的效率不变。
2.4 ... ...


对于很多新手,Keil(有些是8051架构的)的很多坑都要挨个踩,比如using,比如pdata越界,比如链接不上用null,比如堆栈空间不计算,比如xxxxxx。ARM那种统一编址的问题会少很多。

对于using的这个问题,我有个小工具,可以根据静态调用树扫出来。 但是函数指针的就不行了,不完善,所以就不能给大家分享了。除了寄存器bank,像有些产品的sfr bank、code bank、pdata bank等等也都有容易出错的地方,都需要一个个的小工具来帮助。

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
小了个明 + 3 很给力!
19
linqing171| | 2017-7-29 11:21 | 只看该作者
1 不定义成idata的时候,是绝对地址访问,8051的绝对地址访问效率非常高,也是arm等后来的cpu无法企及的。 粗略估计,生成的代码不会放到R7里了,所以不会有此using问题。
2 加入了volatile后,此变量每次用的时候都会重新读,不会使用之前取过的一次,目前在R7的缓存的内容。 但是其它没有加volatile的变量会有出错的风险,加了volatile会导致效率下降。
3 解决的不明不白的问题是不行的,必须找到根因。
4 我不是前辈,只是以前用过十来个厂家的51(一半是读书的时候用的,8051的PSW的RS是读书的时候选修赵教授的课学的)。做过51的模拟器和仿真器。做过其它内核的SOC的C编译器,所以知道各种运行到返回、行号错误等等各种调试过程中IDE现象的原因。我相信你把keil的帮助看一遍,然后做个模拟器,基本这些东西也就都懂了。

使用特权

评论回复
评分
参与人数 2威望 +4 收起 理由
hestering + 1 很给力!
小了个明 + 3
20
小了个明|  楼主 | 2017-7-29 11:21 | 只看该作者
linqing171 发表于 2017-7-29 11:07
你的图的左边,寄存器的PSW的RS值为1,说明你这个函数或者上级函数using 1了。
而你右边图的C:135A行直接把 ...

学习了,我也是刚从STM32转过来,发现那边没问题的代码移植后出现各种莫名其妙的问题。
只能怪自己基础没打好。
谢谢您的指点。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

130

帖子

3

粉丝