打印
[51单片机]

keilc51中 高深莫测的 寄存区组的问题

[复制链接]
2363|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
446005031|  楼主 | 2016-2-22 16:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
中断函数和中断被调函数必须:
必须在同一寄存器组!必须在同一寄存器组!必须在同一寄存器组!重要的时间说三遍。

例如:using 1 ,2 ,3 ....... 这些都是对寄存器组的使用修改。

使用芯片 stc15f2k60s2

本人才疏学浅,刚接触单片机不到一年,在写一个中断程序的时候出现一个问题:



一个A函数中比较1==1的时候,结果竟然不相等!!!

这个A函数是串口中断函数中调用的函数,在中断中调用就不相等。但是在main中调用就一切正常。

喜欢各位大神给小弟解释一下。

我还是个菜鸟,现在去学习一下去。

相关帖子

沙发
xyz549040622| | 2016-2-22 22:59 | 只看该作者
我猜测,是不是优化的问题呢。你这样测试,把1赋值给a,1赋值给b,比较a和b,这样看结果。

使用特权

评论回复
板凳
ayb_ice| | 2016-2-23 08:59 | 只看该作者
不是什么优化问题引起的,是使用不对,这里会产生寄存器组切换与保存,破坏了别人正在使用的寄存器或者有返回值时寄存器已经不对了

使用特权

评论回复
评分
参与人数 1威望 +5 收起 理由
xyz549040622 + 5 赞一个!
地板
sjnh| | 2016-2-23 09:22 | 只看该作者
中断调用的函数是可重入的

变量这类都要考虑优化,volatile之类

使用特权

评论回复
5
446005031|  楼主 | 2016-2-23 09:36 | 只看该作者
xyz549040622 发表于 2016-2-22 22:59
我猜测,是不是优化的问题呢。你这样测试,把1赋值给a,1赋值给b,比较a和b,这样看结果。 ...

对,当时我就是这么测试, 有问题,最后发现  中断函数 和中断被调函数不在同一寄存器组,然后去了using 2之后就可以了, 具体我也不太懂 那天有个人大神告诉我是栈冲突。

使用特权

评论回复
6
446005031|  楼主 | 2016-2-23 09:37 | 只看该作者
ayb_ice 发表于 2016-2-23 08:59
不是什么优化问题引起的,是使用不对,这里会产生寄存器组切换与保存,破坏了别人正在使用的寄存器或者有返 ...

恩恩  应该是这类的原因,得去研究研究

使用特权

评论回复
7
446005031|  楼主 | 2016-2-23 09:37 | 只看该作者
sjnh 发表于 2016-2-23 09:22
中断调用的函数是可重入的

变量这类都要考虑优化,volatile之类

  恩恩 好的 谢谢

使用特权

评论回复
8
ywlzh| | 2016-2-23 09:41 | 只看该作者
多方面思考问题的来源,我门一般是通过反汇编,去看程序怎么分配的,值究竟在哪里被改变了。

使用特权

评论回复
9
446005031|  楼主 | 2016-2-23 09:43 | 只看该作者
ywlzh 发表于 2016-2-23 09:41
多方面思考问题的来源,我门一般是通过反汇编,去看程序怎么分配的,值究竟在哪里被改变了。 ...

恩恩  汇编有点基础,但是有时候总是懒得看,逐渐的拾回来吧。

使用特权

评论回复
10
oufuqiang| | 2016-2-23 12:44 | 只看该作者
也碰到过,但没有深究。今天搜索了几篇**看了看。也没能深刻理解
http://blog.csdn.net/zyboy2000/article/details/4164905
http://blog.csdn.net/leizi_chn/article/details/7244377

kei帮助:
Register Banks
In all members of the 8051 family, the first 32 bytes of DATA memory (0x00-0x1F) is grouped into 4 banks of 8 registers each. Programs access these registers as R0-R7. The register bank is selected by two bits of the program status word, PSW.

Register banks are useful when processing interrupts or when using a real-time operating system because the MCU can switch to a different register bank for a task or interrupt rather than saving all 8 registers on the stack. The MCU can then restore switch back to the original register bank before returning.

The using function attribute specifies the register bank a function uses. For example:

void rb_function (void) using 3
  {
  .
  .
  .
  }
The argument for the using attribute is an integer constant from 0-3. Expressions with operators are not allowed. The using attribute is not allowed in function prototypes. The using attribute affects the object code of the function as follows:

The currently selected register bank is saved on the stack at function entry.
The specified register bank is set.
The former register bank is restored before the function is exited.
The following example shows how to specify the using function attribute and what the generated assembly code for the function entry and exit looks like.

stmt level  source

   1
   2         extern bit alarm;
   3         int alarm_count;
   4         extern void alfunc (bit b0);
   5
   6         void falarm (void) using 3  {
   7   1           alarm_count++;
   8   1           alfunc (alarm = 1);
   9   1         }


ASSEMBLY LISTING OF GENERATED OBJECT CODE

      ; FUNCTION falarm (BEGIN)
0000 C0D0       PUSH  PSW
0002 75D018     MOV   PSW,#018H
                      ; SOURCE LINE # 6
                      ; SOURCE LINE # 7
0005 0500   R   INC   alarm_count+01H
0007 E500   R   MOV   A,alarm_count+01H
0009 7002       JNZ   ?C0002
000B 0500   R   INC   alarm_count
000D  ?C0002:
                      ; SOURCE LINE # 8
000D D3         SETB  C
000E 9200   E   MOV   alarm,C
0010 9200   E   MOV   ?alfunc?BIT,C
0012 120000 E   LCALL alfunc
                      ; SOURCE LINE # 9
0015 D0D0       POP   PSW
0017 22         RET
      ; FUNCTION falarm (END)
In the previous example, the code starting at offset 0000h saves the initial PSW on the stack and sets the new register bank. The code starting at offset 0015h restores the original register bank by popping the original PSW from the stack.

Note

The using attribute may not be used in functions that return a value in registers. You must exercise extreme care to ensure that register bank switches are performed only in carefully controlled areas. Failure to do so may yield incorrect function results. Even when you use the same register bank, functions declared with the using attribute cannot return a bit value.
The using attribute is most useful in interrupt functions. Usually a different register bank is specified for each interrupt priority level. Therefore, you could assign one register bank for all non-interrupt code, a second register bank for the high-level interrupt, and a third register bank for the low-level interrupt.

Copyright © Keil, An ARM Company. All rights reserved.

使用特权

评论回复
11
coody| | 2016-2-23 13:28 | 只看该作者
中断中不要用using

使用特权

评论回复
12
446005031|  楼主 | 2016-2-23 13:41 | 只看该作者
oufuqiang 发表于 2016-2-23 12:44
也碰到过,但没有深究。今天搜索了几篇**看了看。也没能深刻理解
http://blog.csdn.net/zyboy2000/articl ...

谢谢!

使用特权

评论回复
13
446005031|  楼主 | 2016-2-23 13:41 | 只看该作者
coody 发表于 2016-2-23 13:28
中断中不要用using

为啥

使用特权

评论回复
14
446005031|  楼主 | 2016-2-23 13:42 | 只看该作者
coody 发表于 2016-2-23 13:28
中断中不要用using

为啥啊,小弟菜鸟求大神指点

使用特权

评论回复
15
xyz549040622| | 2016-2-23 13:45 | 只看该作者
ayb_ice 发表于 2016-2-23 08:59
不是什么优化问题引起的,是使用不对,这里会产生寄存器组切换与保存,破坏了别人正在使用的寄存器或者有返 ...

说的有道理。

使用特权

评论回复
16
xyz549040622| | 2016-2-23 13:47 | 只看该作者
在某一时刻,只能选用一个寄存器组。搜索可以通过软件对程序状态字PSW中RS0、RS1两位的设置来实现。设置RS0、RS1时,可以对PSW采用字节寻址方式,也可以采用位寻址方式,间接或直接修改RS0、RS1的内容。
例如,若RS0、RS1均为1时,则选用工作寄存器3组为当前工作寄存器。若需要选用工作寄存器2组,则只需将RS0该为0,可用位寻址方式来实现。
特别是在中断嵌套时,只要通过软件对程序状态字PSW中的RS0、RS1两位进行设置,切换工作寄存器组,就可以极其方便地实现对工作寄存器的现场保护。

网上找到的,一直没考虑过这个问题。看来51的水也是很深的。

使用特权

评论回复
17
446005031|  楼主 | 2016-2-23 13:55 | 只看该作者
xyz549040622 发表于 2016-2-23 13:47
在某一时刻,只能选用一个寄存器组。搜索可以通过软件对程序状态字PSW中RS0、RS1两位的设置来实现。设置RS0 ...

也就是说 using 1 2 3 ...这个语句也就是在 修改rs0 和rs1呗,  学习了! 其实你这么一说,我倒是想起来这就是大学课程 单片机原理  中 一开始学的。有人总说 “大学学的呀都没用~~”   , 书到用时方恨少,钱到月底不够花。

使用特权

评论回复
18
xyz549040622| | 2016-2-23 14:32 | 只看该作者
446005031 发表于 2016-2-23 13:55
也就是说 using 1 2 3 ...这个语句也就是在 修改rs0 和rs1呗,  学习了! 其实你这么一说,我倒是想起来 ...

尤其是理论联系实际起来,是很不容易的,那会讲的都是汇编,基本上都没有什么深入,现在碰到问题想起来,都是那时候的基础。

使用特权

评论回复
19
446005031|  楼主 | 2016-2-23 14:50 | 只看该作者
xyz549040622 发表于 2016-2-23 14:32
尤其是理论联系实际起来,是很不容易的,那会讲的都是汇编,基本上都没有什么深入,现在碰到问题想起来, ...

对对对, 说的好!志同道合!:handshake

使用特权

评论回复
20
yhn1973| | 2016-2-23 15:45 | 只看该作者
这东西没什么高深莫测的,只要记住一个原则:相同的中断优先级用相同的寄存器组,不同的中断优先级用不同的寄存器组。
主程序默认是用寄存器组0的,因此中断程序中要用1、2、3组。

使用特权

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

本版积分规则

7

主题

35

帖子

0

粉丝