以前没有怎么用C51写过较大的程序,这次因为一个项目的原因,用C51写程序,踩了很多坑,这里总结分享一下,愚人千虑必有一得。
## 常见的中断陷阱之一: volatile变量
如果,中断中修改了一个变量的值,这个变量会被另外的函数访问,这个变量应该声明为 volatile
## 常见的中断陷阱: 临界区
用于中断的引入,程序中产生了真正的并发。
假设有一个变量a,在中断服务isr和funA中都访问了同一个变量a,而对a的操作是非原子的(即对a的操作需要多于1条指令),那么可能发生的情况是funA对a的操作还没有完成,中断发生了,等中断返回,回到funA后,变量a的值已经被破坏了,但funA并不知道,因此将得到了一个错误结果。
对中断和普通函数共享变量的访问,应该是原子操作。如果不是原子操作,那么对变量访问期间,应该关闭中断。
显然,16或32bit 变量操作,在8位CPU中,是非原子的,对他们的操作应该关闭中断。
还有一些8位变量的操作也是非原子操作。操作flags |= 0x80在51单片机中,是非原子的。
## 常见的中断陷阱: 堆栈溢出
中断的返回地址和寄存器是保存在堆栈之中的,所以中断执行时,应该有足够的堆栈空间。
堆栈溢出通常发生在非常深的子程序调用中。
## 常见的中断陷阱: 使用不可重入的函数
特别值得说明的是,整数乘法、浮点数操作可能使用外部的支持函数来实现的。
尽可能避免在中断中调用不可重入的函数,因为这很可能产生难以发现的bug
函数funA是不可重入的,在其内部使用了固定地址的存储空间;若funA在执行过程中,被某一个中断打断,而该中断服务函数又调用了funA,那么中断将破坏原本funA的执行现场,导致错误。这种错误不一定会发生,但如果发生,将非常难于发现。
### 不可重入的函数什么时候会导致错误
C51在固定的位置分配变量的存储空间。一个函数,如果在执行中途,被中断打断,而且中断中又再次调用该函数,那么中断就可能破坏掉原来的执行现场(分配在固定空间的值)导致执行出错。
离线
楼主说的应该是Keil的C51吧。其实SDCC也是类似的,建议先好好读一遍SDCC的手册,这样可以加深理解。
离线
尽量不要使用51吧,问题太多了。只能避免,不能解决
我觉得51本身倒不会有很多问题,虽然架构确实过时了,但是还是够用的。
51的问题可能更多地出在编译器上,由于架构特殊,C编译器的用法和标准的GNU C Compiler有一些差距,在优化等方面也有所不如。可能对51来说,复杂一些的程序还是要自己写汇编来得靠谱。
离线
51确实太多不方便的地方,但是架不住便宜啊,有的小项目,51单片机只要1元左右。
离线
51确实太多不方便的地方,但是架不住便宜啊,有的小项目,51单片机只要1元左右。
STM8s003、N76E可以了解下
离线
n76e就是51啊,以前stm8s003确实很便宜,但有一段时间涨到了3元左右,一大票的003兼容国产51出来。
离线