专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
调了2天的51单片机程序,发现了一个问题,这算不算是Keil C51的BUG?
2019-03-24 17:42
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
51单片机
14103
10
1386
本帖最后由 bobde163 于 2016-3-18 11:39 编辑
用Keil C51调了2天的51单片机程序,主要功能是使用定时器0实现一路模拟串口,但是在使用中模拟串口发送的数据全都是0,串口发送的字节帧格式都是对的,一个起位,8个数据位,一个停止位,说明是要发送的数据全都变为了0。使用软件仿真调试,查看汇编代码,反复分析才确定了问题的根本原因,跟51单片机内部的4个寄存器组有莫大的关系。
1、
1、在进入定时器0的中断函数前,可以看到系统还是使用的是默认的寄存器组0,由于设置中断函数使用寄存器组2,所以在进入中断函数前,除了对原来的运行数据进行入栈操作外,最后还切换到了寄存器组2,这里没有问题。
2、在中断函数中调用了带参数的函数VUartTransmitByte(*Ptr)(注:Ptr是一个指向字节数据的指针,指针变量地址为0x3D,位于data段)。在图中可以看到在汇编代码中,在实际调用函数前,先对参数进行了传递,使用R7进行参数的传递,之后正式进入函数内部,此处也没有问题。
3、在正式进入函数中时,从汇编代码中可以看到,第一条被执行的指令是MOV R5,0x07;这里就是第一个出问题的地方,结合后面的代码分析,这条指令的作用是将传递进来的参数(存在寄存器组2中的R7中)又转存到R5中,R7又作其他用途。但是这条指令却用的是0x07地址,0x07是寄存器组0中的R7寄存器,此时系统选用的还是寄存器2,应该使用的R7或者0x17,这是导致数据错误的第一个地方。
4、之后便执行到移位操作和与操作部分if(dat & (0x01 << (TxBitCnt - 1))),从汇编出来的代码可以看到TxBitCnt - 1这一步是没有问题的,结果存放在R7中,接下来就是要执行移位操作,代码先是将需要移位的位数(就是TxBitCnt - 1的值,存放在R7中)放到R0中MOV R0,0x07;才会进入循环移位的代码部分,但是这条指令系统却是使用寄存器组0中的R7,而不是存储真正位数和寄存器组2中的R7,导致移位结果全为0。这个错误是和上一条错误是一样的。
5、我去掉定时器0中断使用寄存器组2的设置(using 2),系统就会使用默认的寄存器组0,只是进入中断函数前,会先把R0到R7的值压入堆栈,会多一些开销,但是程序运行就对了,发送的数据也都是正确的。
6、这个问题曾经遇到过,调了一周,最后只知道是只要在中断中调用个别函数,就会导致发送函数异常,没有找到原因,现在看来可能也是这个原因导致的。
6、疑问:这个问题的产生是和我代码有关系吗?这个不知道大家有没有遇到过呢?这算不算是一个Keil C51的BUG呢?
此帖出自
小平头技术问答
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
10条回答
ntmusic
2019-03-26 02:19
个人感觉,既然用C语言了,就不要涉及到编译器编译层面上的控制,比如指定寄存器组(Using)。提高执行效率的想法很好,但目前编译器的优化和单片机的执行速度已经大大提高了,强行指定一方面不利于程序移植,一方面容易带来异常,得不偿失。如果真的要提高效率,可以直接用汇编和C混编。最后对于你这个问题,我觉得你只是指定了在中断函数中强制寄存器组,但在中断中调用的函数是在中断函数外被编译的,并不属于中断函数域,所以不受中断函数的寄存器组指定影响。
加载中...
查看其它10个回答
一周热门
更多
>
相关问题
相关文章
基于51单片机的计算器设计
0个评论
51单片机300个proteus仿真实例下载
0个评论
51单片机 蜂鸣器
0个评论
51单片机驱动RC522模块
0个评论
基于51单片机的指纹密码锁
0个评论
AT89C51单片机制作简易密码锁
0个评论
51单片机汇编语言计数器
0个评论
51单片机精确延时设计
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
一周热门 更多>