一,堆栈在汇编的作用,以及PUSH ACC 和 PUSH PSW

  • 通过最简单的8051单片机RAM的分配可知,单片机从烧程序到达到一定的工作过程。首先明白为什么要引如“烧”写的过程 。我们知道一般我说存储器ROM和RAM。首先ROM内存大,保存数据时间长,但这样也限制了ROM不能做到随时随写,因为为了达到内存大,存储更多逻辑,还要长期保存,其芯片设计目前不能达到随时改逻辑。
  • 于是RAM孕育而生,RAM的功能就是随便写,随便读,各个部分的高低电平(就是硅晶体电子上浮下移)——逻辑结构可以根据处理器(内核)不断的修改,处理速度块。
  • 为了完成固定保存逻辑,又要可以随时改变逻辑,就形成了ROM存程序,存表格数据,而RAM存数据,就是CPU(处理器)根据一行行(各个地址)要求,在RAM执行相应的操作。
  • 那么问题来了,RAM是怎样保存运行ROM的程序,以及CPU怎样在ROM得到逻辑识别作用RAM?

这就是RAM有特殊功能区,如上图,在8051单片机中,RAM有516个单元存储(也就是寄存器),ROM存储的程序就是调用RAM的各个寄存器完成逻辑。

比如 :在ROM存储  MOV A, #20H

MOV P1, A

就是ROM发给CPU要给ACC寄存器(ACC其实就是标识符在RAM的位置高128位FSR(特殊功能寄存器)的地址0EH赋值,然后把RAM的ACC(地址E0H)赋值给P1,这里P1也是RAM寄存器(存储单元)存储位置的标识符在90H。

  • 那么问题来了,堆栈SP有什么作用?
  • 首先讲栈的作用;

堆栈就是在执行PUSH ###,把它压倒栈里,把数据保存起来,(注意这里一切都在RAM里面完成),就是在RAM开辟一段空间,当压入时,就是把压入的值赋给栈的寄存器(注意RAM所有地址都叫寄存器)

例如:MOV 30H,#22H

 PUSH 30H

          MOV 30H,#01H

   /%%%MOV A ,30H

  POP  30H

  MOV  A, 30H

如上程序,第一段就是把22h的16进制数存到地址为30H寄存器(寄存器上,其实像 P1,TCON,TMOD,都是RAM寄存器的标识符,他们都表示地址,这里30H是用户自定义区,在汇编编译器没有赋值标识符,当然高手就是直接可以调用头文件直接把每个位置附上标识符),然后执行PUSH 30H,就是把RAM30H单元存储的值(22H)放在栈里,,之后,在对地址30H赋值01H,在“////%%%"A的值为01H,之后再POP 30h,,这里POP只是标记弹出在最后压栈的数据,给30H,也就是30H存储值又恢复22H。

以上就是堆栈的功能(默认都学过C语言,栈是先进后出,在51压栈指针增)

  • 那么问题来了,堆栈是在什么地方堆栈?

这就引出今天讲的重点,堆栈指针SP,指针就是告知对于压入的数据和调用子程序的开始地址和中断时程序运行的地址。但是在RAM中像什么通用寄存器,用户自定义区,可位寻址区,特殊寄存器区,其实没有什么界限,原理上堆栈开始位置可以设置任何区域。但但但是,不要覆盖我们可能要用的寄存器(RAM地址)。

在8051单片机中,栈的默认位置为07H,通过以上RAM地址可以看到,在07H寄存器以上又其他通用寄存器,和位寻址寄存器,用户自定义寄存器。如果当启动中断,调用子函数,或者压栈,栈会保存地址信息,保存压栈的内容,这是原来在(注意当栈确定位置时,压栈数据存储在储存位置上个,如栈起始为07H,进栈存储在08H),08H,09H,的数据就会被覆盖,当调用08H,09H的数据原来数据就没有了,会造成程序紊乱。

所以这也是汇编的弊端,在C语言写程序不管调用多个程序,多个子程序,多少中断,C语言会自动分配合适的栈地址,所以C语言,甚至高级语言基本没有调用栈的程序。(例如在我们学习C语言,老师就讲递归的害处,因为递归是从后往前算,当要得到一个值,要找前面的值,每调用一次,函数的地址就要压栈,当调用多次,把栈的范围扩大到本程序要用的地址(如特殊功能寄存器),就会造成程序崩溃)。

但是在我们单片机汇编语言中,我们是面向寄存器的语言,要时刻关注各个寄存器运行情况。下面来举几个具体的例子。

举例:堆栈SP和RAM

MOV    A,  #00H
  SETB    RS0
  CLR      RS1  //启用通用寄存器第1组,这时R0的地址为08H

  MOV   R0, A
  MOV   30H, #0FFH  //给用户自定义区30H,赋值为FFH
  MOV   31H, #0EEH  //给用户自定义区30H,赋值为EEH
  PUSH   30H   //把30H的值压倒栈,这里是默认07H为栈的初始位置,在07H,这样08H的值为FFH
  PUSH   31H   // 把31H的值压倒栈,这里是默认07H为栈的初始位置,
                     //因为之前已压一个在07H,这样08H的值为EEH
   POP    30H  //表示弹出栈口的值,给地址30H,因为栈是先进后出,30H地址存储EEH
   POP    31H//同理31H地址的值为FFH
  MOV  A, R0  //最后由于之前进栈操作把原来R0的值覆盖,得到现在R0的值为FFH

之前的C语言,定义unsigned char u;就是编译器在RAM已经生成个存储u的数据,我们不用管,在调用子函数,中断函数,也是C语言已经设置好了堆栈空间,存储函数入口地址。

现在,在汇编,我们经常会遇到修改栈指针就是修改进栈地址,防止我我们设置的寄存器的影响。

汇编模板

ORG  0000H
AJMP MAIN
ORG  0030H //在40H开始写程序,因为在0000H-0030H的ROM有中断入口
MAIN:

MOV SP ,#50H  //现在使用的单片机的RAM有很大空间,目前我写函数时直接修改栈地址50H
                            //这样在30H-50H,我可以随意赋值,且不会覆盖,如:MOV 3FH,#0FFH
                             //对于改栈指针最好在主函数执行第一个改

MOV  30H,  #00H  //首先这个程序存储在ROM中,//
                                 //然后这个程序执行的任务就是把RAM的30H寄存器(地址)赋值00H
   MOV  31H,  #00H
   MOV  32H,  #00H
   CLR    RS0
   CLR    RS1         //调用通用寄存器组0
   MOV  A,     30H
   MOV  R0 ,#31H
   MOV  A, @R0
   ACALL DELAY500MS   //把子函数调用开始位置数据压倒栈里

//注意调用子函数,特别是含有通用寄存器,或者SFR,要想到会不会对主函数有影响
//保险起见,对于封闭的子函数都调用通用寄存器3,主函数都调用通用寄存器组0
DELAY500MS:   
   SETB RS0
   SETB  RS1  //调用通用寄存器3
    MOV R7,#17H
DL1:
    MOV R6,#98H
DL0:
    MOV R5,#46H
    DJNZ R5,$
    DJNZ R6,DL0
    DJNZ R7,DL1
   CLR    RS0
   CLR    RS1   //调用通用寄存器组0
    RET

二,中断和定时器的基础知识

2.1中断

在看逻辑图和寄存器映射编写自己的程序是要注意两点:1,逻辑关系走向,2,寄存器是否可以位寻址。

CPU在正常执行程序的过程中,由于某种已经预见到的外部或CPU内部事件的发生,使CPU暂停执行当前的程序,而去处理临时发生的事件,在事件处理完毕后,再返回原先暂停的程序继续向下执行,这个过程叫做中断(Interrupt)。

编者按:下图是51系列的中断(在我们现在大部分是STC89C52,它又加了额外的中断和优先级(但兼容51),这里就不详细描述,具体可以根据数据手册的流程图配置)这里讲解中断定时器,以及配置都是根据以下的逻辑图和他们对应的寄存器(当然如果可以位寻址,可以根据逻辑图直接配置,问题是有的寄存器不能位寻址)

由图可知,80C51单片机的5个中断源分别是:2个外部中断(由ND、xn引脚输入中断请求信号)、2个片内定时器/计数器溢出中断(TO、T1)和1个片内串行口中断。TCON、SCON是用来存放各中断源的中断申请标志的寄存器;IE是用来设置是否允许中断源中断的寄存器;IP是用来设置中断源优先级别的寄存器;硬件查询是相同优先级的中断源再进行排队的硬件电路。
TCON、SCON、IE和IP是与中断相关的寄存器,下面分别对这4个寄存器的用法进行详细介绍。

1定时器控制寄存器TCON(Timer ControlRegister)。

TCON为定时器/计数器TO、T1的控制寄存器,同时也锁存了TO、T1的溢出中断和2个外部中断请求的标志位。TCON的单元地址为88H,可位寻址,这些中断请求标志位可以用软件查询。TCON的格式及与中断有关的位的功能如下。
 

上面的逻辑图,可以地IE1,IE2,IT1,IT0,分别是中断请求标志位,都可以在完成中断自动清零。

3串行口控制寄存器SCON(Serial ControlRegister)。

SCON的低两位锁存了串行口发送中断和接收中断请求标志位。SCON的单元地址为98H,可位寻址。SCON的格式和与中断有关的位的功能如下。(由上章串口通信,这里SCON是一部分)


TI:串行口发送中断请求标志位。当串行口发送完一个数据帧时,将TI置位(TI=1),向CPU申请中断。
RI:串行口接收中断请求标志位。当串行口接收完一个数据帧时,将RI置位(RI=1),向CPU申请中断。

 注意在串口中断时,中断标志位不能自动清零(也就是术语:硬件清零),在编程时跳到中断要清零(软件清零)。

4中断允许寄存器IE(Interrupt EnableRegister)

对于各个中断源的中断允许控制位,当其为1时,允许中断;当其为0时,禁止中断。中断允许寄存器IE的单元地址是0A8H,各控制位(位地址为0A8H~0AFH)可位寻址,故用户既可以用字节传送指令又可以用位操作指令来对各个中断请求加以控制。画×的位未用到,可设置为0。

EA:中断允许总控制位。若EA=0,则所有中断源的中断请求均被禁止;若EA=1,则所有中断源的中断请求均被允许,但中断请求最终能否被CPU响应,还取决于IE中各中断源的中断允许控制位的状态。EX0和EX1:EX0为外部中断0的中断允许控制位;EX1为外部中断1的中断允许控制位。
ETO和ET1:ETO为定时器/计数器TO的溢出中断允许控制位;ET1为定时器/计数器T1的溢出中断允许控制位。
ES:串行口中断允许控制位。

5中断优先级寄存器IP(Interrupt Priority Register)

CPU在某一时刻只能响应一个中断源的中断申请,如果有很多的中断源同时申请中断,到底应该响应哪一个呢?可以通过设定优先级别的方法来解决这个问题。80C51单片机的5个中断源,均可由程序设置为高优先级中断或低优先级中断,谁的优先级别高,就先响应谁。每个中断源的中断优先级都通过中断优先级寄存器IP统一设置。IP的格式和与优先级设置有关的位的功能如下。

PX0和PX1:PX0是外部中断0的中断优先级控制位;PX1是外部中断1的中断优先级控制位。
PTO和PT1:PTO为定时器/计数器TO的溢出中断优先级控制位;PT1为定时器/计数器T1的溢出中断优先级控制位。
PS:串行口中断优先级控制位。
当某个中断源的优先级控制位为1时,设置为高优先级中断;为0时,设置为低优先级中断。IP的单元地址为0B8H,各控制位(位地址为0B8H~0BCH)可位寻址,故用户既可以用字节传送指令,又可以用位操作指令来对各个中断源的优先级进行设置。单片机复位时,IP=00H,即所有中断源为低优先级中断。

6中断的处理过程

中断的处理过程大致可分为4步:中断请求、中断响应、中断处理和中断返回。
1.中断请求
当中断源发出中断请求时,将相应的中断请求标志位置“1”,向CPU请求一次中断服务。如果中断允许寄存器IE中的总控开关和相应的分控开关是闭合的,那么这个中断标志位就会传送到CPU中。
2.中断响应
CPU响应中断时,先置位相应的优先级状态触发器,指明CPU开始处理的中断源的优先级别,以屏蔽后面的同级或低级中断请求;然后自动清除相应的中断标志(TI或RI除外);最后再执行由硬件自动生成的长调用指令(LCALL),该指令将程序计数器PC的内容(主程序被中断的地址,也称断点地址)压入堆栈保护起来,再将对应的中断服务程序的首地址(也称中断入口地址或中断矢量地址)装入程序计数器PC,使CPU去执行中断服务程序。注意,断点地址被压入堆栈保护起来了,但对诸如PSW、累加器A等寄存器的数据并没有保护,需要时可在中断服务程序中完成保护任务。系统规定的各中断源相对应的中断服务程序的中断入口地址见

ORG 0003H ;外部中断0的中断入口地址
AJMP  EXT0 ;转移到0200H单元

7代码示例端(注意通用寄存器的改变):

通过这个基础设置,也就是更具逻辑图,以及寄存器(可位寻址与不可位寻址)可是自行设计中断,这里就不详细描述了,我所讲的还是跟上个一样,就是调用子函数的通用寄存器的改变,以及中断的改变,如下示例,就是简单的外部中断0,下降沿有效。实验证明在PUSH PSW ;只是保存程序状态字,如保存通用寄存器组,但是当在中断仍然改变通用寄存器的值,它还会对主函数造成影响,原来不管中断还是调用子程,默认都是调用通用寄存器组0,为了避免影响,在汇编的子程序开始修改组别,调用末尾在改回来。在C语言有个interupt using 1; 就是调用通用寄存器组1.

LED EQU P2
ORG 0000H
AJMP MAIN
ORG 0003H  //中断的处理过程:2.中断响应之外部中断0的地址,必须要这样的格式
AJMP EXT0
ORG 0040H  //因为我用的是stc52系列
MAIN:
SETB IT0   //1定时器控制寄存器TCON(Timer?ControlRegister)。设置下降沿有效
SETB EX0  //4中断允许寄存器IE(Interrupt?EnableRegister) 开中断0
SETB EA   //4中断允许寄存器IE(Interrupt?EnableRegister) 最高级控制所有中断
SETB PX0
MOV A,#01H
CLR RS0
CLR RS1
MOV R7,#0FHLOOP:;CPL A;MOV LED,A   //连接方式灌电流,电源-电阻-二极管-Px,低电平亮;ACALL DELAY800MSMOV LED,R7                                           //用于检验;;ACALL DELAY800MS;RL AAJMP LOOP  //没有中断的LEDEXT0:   //中断处理程序PUSH PSWPUSH ACC;SETB RS0;SETB RS1   /////////修改寄存器MOV R7,#0F0HMOV LED,R7                                           //用于检验;ACALL DELAY1S;ACALL DELAY1SPOP ACCPOP PSWCLR RS0CLR RS1RETIDELAY1S:   ;误差 0usMOV R1,#0A7H
DL11:MOV R2,#0ABH
DL00:MOV R3,#10HDJNZ R3,$DJNZ R2,DL00DJNZ R1,DL11NOPRETDELAY800MS:   ;误差 0usMOV R4,#5FH
DL1:MOV R6,#8AH
DL0:MOV R5,#1DHDJNZ R5,$DJNZ R6,DL0DJNZ R4,DL1NOPNOPRET   END

51单片机中断的调用寄存器组(PSW)的作用,以及汇编堆栈的作用,堆栈指针的SP的使用方法,RAM的运行和ROM在单片机具体运行和C语言的优势和中断,定时器基础知识(上)相关推荐

  1. Keil C51中断编程中寄存器组的选用与保护

    Keil C51中断编程中寄存器组的选用与保护 http://www.you01.com/article-14002-1.html

  2. 电机控制基础——定时器基础知识与PWM输出原理

    单片机开发中,电机的控制与定时器有着密不可分的关系,无论是直流电机,步进电机还是舵机,都会用到定时器,比如最常用的有刷直流电机,会使用定时器产生PWM波来调节转速,通过定时器的正交编码器接口来测量转速 ...

  3. 51单片机定时器基础知识

    定时器初值计算 经验总结:定时器0工作方式1的溢出中断初始值计算 1.晶振11.0592M 11.0592MHz除12为921600Hz,就是一秒921600次机器周期,50ms=46080次机器周期 ...

  4. 106划为c语言16进制数,计算机基础知识题(含答案)

    <计算机基础知识题(含答案)>由会员分享,可在线阅读,更多相关<计算机基础知识题(含答案)(27页珍藏版)>请在人人文库网上搜索. 1.第第1 1章章 计算机基础知识计算机基础 ...

  5. stm32高级定时器 基础知识

    stm32高级定时器 高级定时器时基单元: 包含一个16位自动重装载寄存器 ARR 一个16位的计数器CNT,可向上/下计数 一个16位可编程预分频器PSC,预分频器时钟源有多种可选,有内部的时钟.外 ...

  6. 专升本招生考试应试宝典之计算机基础知识(上)

    第一章计算机基础知识 第一节计算机基本知识 一. 计算机的诞生 人类历史上第一台电子计算机是由美国宾夕法尼亚大学的莫克利教授和他的学生埃克特设计,并于1946年2月15日在宾夕法尼亚大学成功投人运行, ...

  7. 计算机基础知识上实验课教案,高中信息技术上册《第4课 计算机基础知识》教案...

    高中信息技术上册<第4课 计算机基础知识>教案 第4课 计算机基础知识 设计 要素 设 计 内 容 练习 内容 分析 本节通过上机练习让学生了解计算机文化的概念,介绍信息对人类社会发展地作 ...

  8. 计算机基础知识上教案,第一章 计算机基础知识教案

    <计算机文化基础>教案 第一章计算机基础知识 一.课程的性质和任务 "计算机文化基础"是大学非计算机各专业学生必修的公共基础课.课程内容着重计算机的基础知识.基本概念和 ...

  9. C语言教程(三):基础知识(续)

    参考:<标准C语言基础教程>(第四版)[美] Gary J.Bronson 著 张永健 等译 1. 前文回顾 首先我们先对上次留下的小问题进行解答,答案其实很简单,和我来看一下代码吧~ # ...

最新文章

  1. MariaDB表表达式(2):CTE
  2. 中文按拼音首字母排序的C++实现方案
  3. lnmp环境搭建:Centos7 + Nginx1.12.2 + Mysql-5.6.38 + PHP7.2.0
  4. 卫星导航定位 -- 坐标系统与时间系统
  5. 服务器换完主板后无盘进不了系统,更换主板后主板认不出硬盘无法进入系统的办法 – 手机爱问...
  6. C# 生成高清缩略图
  7. ArcGIS 城市生活区用地适宜性评价(一)
  8. GraPhlAn:最美进化树或层级分类树学习笔记
  9. 把mysql数据展示为图表_怎么从数据库中调出数据并生成动态图表?
  10. 测试版ios15怎么信任软件,苹果ios15描述文件位置在哪 ios15授权信任设置方法教程...
  11. CentOS7安装PHP5.3.28
  12. vue中Echart如何打包下载图片
  13. idea无法下载源代码
  14. 识别音标python_音标可以识别单词吗?
  15. 时光荏苒,岁月静好-----2013年终总结
  16. 两种方法实现文字阴影效果
  17. 微型计算机第六章课后答案,微型计算机原理及其接口技术第六章部分习题.doc...
  18. 服务器查看系统盘位置,服务器上查看硬盘位置
  19. IOS——获取当前运营商(获取漫游接入网络的运营商)
  20. Linux 网络编程——TCP/IP 数据包格式解析

热门文章

  1. 小程序云开发,CMS内容管理系统
  2. 整车电源状态 K15 KL30 KL31
  3. CSS/HTML 网页添加网易云歌曲插件
  4. Web 图片引用之相对路径与绝对路径
  5. AD练习笔记 USB-TTL转换器
  6. 千峰课程网安笔记(1)
  7. 键盘的 SysRq按键使用详解
  8. SQL server 2012 下载,安装,磁力链接,下载地址 2020.11.28
  9. Arduino通过RXTX联通JAVA实现数字温度计案例
  10. 【navicat】定时清除数据库备份,并保留最近7天