历史上的今天
今天是:2025年02月05日(星期三)
2020年02月05日 | 建立一个属于自己的AVR的RTOS(第二篇:人工堆栈)
2020-02-05 来源:eefocus
第二篇:人工堆栈
在单片机的指令集中,一类指令是专门与堆栈和PC指针打道的,它们是
rcall相对调用子程序指令
icall间接调用子程序指令
ret子程序返回指令
reti中断返回指令
对于ret和reti,它们都可以将堆栈栈顶的两个字节被弹出来送入程序计数器PC中,一般用来从子程序或中断中退出。其中reti还可以在退出中断时,重开全局中断使能。
有了这个基础,就可以建立我们的人工堆栈了。
例:
#include voidfun1(void) { unsignedchari=0; while(1) { PORTB=i++; PORTC=0x01<<(i%8); } } unsignedcharStack[100];//建立一个100字节的人工堆栈 voidRunFunInNewStack(void(*pfun)(),unsignedchar*pStack) { *pStack--=(unsignedint)pfun>>8;//将函数的地址高位压入堆栈, *pStack--=(unsignedint)pfun;//将函数的地址低位压入堆栈, SP=pStack;//将堆栈指针指向人工堆栈的栈顶 __asm____volatile__("RET t");//返回并开中断,开始运行fun1() } intmain(void) { RunFunInNewStack(fun1,&Stack[99]); } RunFunInNewStack(),将指向函数的指针的值保存到一个unsignedchar的数组Stack中,作为人工堆栈。并且将栈顶的数值传递组堆栈指针SP,因此当用"ret"返回时,从SP中恢复到PC中的值,就变为了指向fun1()的地址,开始运行fun1(). 上面例子中在RunFunInNewStack()的最后一句嵌入了汇编代码"ret",实际上是可以去除的。因为在RunFunInNewStack()返回时,编译器已经会加上"ret"。我特意写出来,是为了让大家看到用"ret"作为返回后运行fun1()的过程。
上一篇:AVR下载线存在问题
下一篇:AVR常用库函数介绍
史海拾趣
|
开机的时候那个消磁按钮上的红色指示灯不停的闪,按一下会进行消磁动作,但好像不能完成消磁,数码管显示364一闪一闪的。 有时候开机一段时间后能消磁成功,有时候开机几个小时也不行。用过的DD指导一下,是有故障还是我使用问题?… 查看全部问答> |
|
如题,这个恐怕是大家经常遇到的问题吧? 一种方法是: 在任何时候都把“程序规模”限制在你所能够掌控的范围内。 那如果超过范围咋办?模块化——合理划分和封装细节。其实如果是自上而下的设计(通常如此),模块化设计是非常自然的事(因为 ...… 查看全部问答> |
|
最近看了一个电路,就是在触摸屏的四根线上,分别接了4个屏蔽电阻下拉接地。 想请教一下: 1。为什么触摸屏那四根线要下拉?我看很多触摸屏的电路,没有下拉使用也很正常啊! 2。为什么要用屏蔽电阻?普通电阻不行吗?会造成什么样的影响? 麻 ...… 查看全部问答> |




