
此示例使用汇编在Puzhong微控制器上实现简单的秒表功能,并带有一个复位按钮.
创建一个新的keil项目,创建一个新的.asm文件并将其添加到项目中,而无需添加startup.a51文件
在编写代码之前,请先谈谈随后编写51程序集所必需的一些基本知识,因为程序集与硬件密切相关,因此如果不了解它们就无法编写这些程序
1. 单片机上电后的一般操作过程
MCU有自己的检测和编程程序. 上电后在某个引脚上检测到某个信号时,从串口发送的数据将被编程到程序存储器中(从0000H开始),
然后执行编程的程序,否则执行最后的编程程序.
微控制器执行的第一条指令是程序存储器中的0000H内容. 通常,在此处将跳转指令写入主程序的起始地址(例如1000H,例如,不一定要在此处)
当执行主程序时,如果发生中断,它将跳转到程序存储器中的固定地址(例如T0会跳转到000BH),一般在这里写一条跳转指令,以便程序跳转到中断处理程序<
此处的固定地址是所谓的中断向量. 因此我们编写51汇编程序必须首先在这些地址上编写跳转指令

2. 一些常用的寄存器
将不再提及与微控制器的配置有关的特殊寄存器,例如P0,TMOD等,并且与编写C语言时几乎相同. 工作寄存器更多地参与编写汇编.
还有A,B寄存器,DPTR寄存器,PSW寄存器,SP寄存器等,这里专门提到工作寄存器,其他百度可以.
工作寄存器有4组,每组都是8个工作寄存器R0~R7,通过PSW中的RS1、RS0两位来选择使用哪一组,如果不选,默认是选择第0组。
RS1RS0组合为00时,选中第0组工作寄存器,R0~R7地址为00H~07H;(这里的地址为内部RAM区)
RS1RS0组合为01时,选中第1组工作寄存器,R0~R7地址为08H~0FH;
RS1RS0组合为10时,选中第2组工作寄存器,R0~R7地址为10H~17H;
RS1RS0组合为11时,选中第3组工作寄存器,R0~R7地址为18H~1FH。
进入中断时,可以通过改变RS1RS0来分别使用不同的R0-R7
3、51个单片机的存储器结构

编写汇编代码以确保上面的图片清晰可见,因为汇编直接操作上述内存,并且不同的内存区域可能使用不同的指令.
程序存储器用于在程序编译后保存指令,这些常数只需要读取而无需修改. 读取是通过MOVC命令实现的,示例如下
disBuf: DB 00H,01H,02H,03H,04H,05H,06H,07H

MOV DPTR,#disBuf
MOV A,00H;表示读取disBuf的第一个,01H读取第二个
MOVC A,@ A + DPTR;从rom获取数据
我还是不明白. 像DB这样的伪指令只能用于在微控制器中定义常量(在ROM中)吗?在8086中似乎是一个变量
我尝试了几次,但没有找到好的答案. 最后,变量定义直接是“变量名EQU内部ram的地址”要实现
数据存储器是RAM区域,分为片内和片外. 用于访问的说明不同. 片上直接MOV就足够了. 片外ram只能通过A寄存器读取或访问(请参见表中的特定附件说明)
在这里您可以发现51单片机的数据存储区和代码存储区是分开的. 从这个角度来看,它是一个哈佛结构,但是获取和读取数据是分时的. 曼结构的特征. . . 因此存在争议
4. 掌握调试技巧
毕竟,汇编程序直接操作内存,因此调试的使用非常重要. 这是一些关键用途


第一个位置是从左到右: 重置(簇头启动),全速运行,停止,单步运行(输入子程序)单片机汇编,单步运行(子程序不进入单步运行)
第二个块可以看到常用寄存器的值,其中R0指的是R0的第一组,如果要查看其他组,则必须使用第三个块的功能
第三个块用于查看内存中的值,如下所示:
在“存储器”窗口中输入地址值,结果是程序代码区域的内容. 要查看各个存储区的内容单片机汇编,只需在“地址”框中输入“字母: 地址”以显示相应的存储值. 字母可以是C,D,I,X,这表示:
C: 代码存储空间
D: 直接访问片上存储空间
I: 间接寻址片上存储空间
X: 扩展了外部RAM空间

如果输入“ d: 0x30”,则可以在芯片上显示可直接寻址的30H存储空间的内容.
您还可以使用右键单击“修改内存”选项来修改指定内存的内容.
第四个街区,指定地点的断点
5. 汇编代码说明
我个人容易出错的一点是,当我为寄存器分配一个常量值时,我常常忘记使用#号. 汇编语言和C语言习惯不同. 我必须在常量值前面加上#号,否则它将被视为该值所表示的地址的内容
例如,MOV R0,0x01会将内部RAM地址为0x01的存储单元的内容复制到R0. 要将R0分配为1,应将其写为: MOV R0,#0x01
还有一个代码段,用于手动安排起始位置. 确保分段之间没有重叠(我不知道它是否可以自动排列)
好的,知道了这些之后,您就可以根据此说明开始编写汇编代码,我将其直接粘贴
duan EQU P0; wei EQU P2; key BIT P3.7; ORG 0000H AJMP MAIN;绝对转移指令,2kb范围(11位)内跳转 LJMP16位 64kb范围内跳转 ;短转移指令的功能是先使程序计数器PC加1两次(即:取出指令码),然后把加2后的地址和rel相加作为目标转移地址。因此,短转移指令是一条相对转移指令,是一条双字节双周期指令 ORG 0030H;指明后面的程序从程序存储器的0030H单元开始存放 DELAY200US: ;@11.0592MHz NOP NOP NOP PUSH 30H PUSH 31H MOV 30H,#2 MOV 31H,#179 NEXT: DJNZ 31H,NEXT DJNZ 30H,NEXT POP 31H POP 30H RET ORG 0060H ;DISPLAY子程序 DISPLAY: PUSH ACC;不能写A,此处ACC代表地址,push后跟地址,代表把地址内的内容压入栈中 PUSH 00H;R0 PUSH 06H;R6 PUSH 07H;R7 PUSH 83H;DPH PUSH 82H;DPL MOV R6,#01H;位选数据,01指的是缓冲区最低位数据 MOV R7,#08H;循环次数 FLAG: MOV duan,#0x00;消影 MOV A,R6 CPL A;取反 MOV wei,A;位选 MOV A,#disBufDat ADD A,R7 SUBB A,#0X08 MOV R0,A MOV A,@R0;读出要显示的数据到A MOV DPTR,#disTab MOVC A,@A+DPTR;从rom取数据,取出要显示的数据对应的段码 MOV duan,A;段选 MOV A,R6 RL A MOV R6,A;更新下一次位选 LCALL DELAY200US DJNZ R7,FLAG POP 82H;DPL POP 83H;DPH POP 07H POP 06H POP 00H POP ACC RET ORG 0100H ;定时器中断0初始化 T0_INIT: MOV TMOD,#0X01 MOV TH0,#0X3C MOV TL0,#0XB0 SETB EA SETB TR0 SETB ET0 RET ORG 0130H ;T0中断处理程序 INT_TIMERE0: PUSH ACC SETB RS0 MOV TH0,#0X3C MOV TL0,#0XB0 INC R0 MOV A,R0 SUBB A,#0X14 JB CY,SECFLAG MOV R0,#0x00 INC sec SECFLAG: CLR RS0 POP ACC RETI ORG 000BH ;定时器/计数器T0入口地址 LJMP INT_TIMERE0 ;跳转到定时器/计数器中断服务程序中去 disTab: DB 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40;0-f,空白,横杠的段选数据 disBufDat EQU 47H;定义显示缓冲数据变量区,8个 disBufDatHead EQU 40H //单片机上显示在最左边 sec EQU 48H ;主程序 ORG 0180H MAIN: MOV SP,#0X60;将0x60到0x7f设为堆栈区 LCALL T0_INIT MOV disBufDatHead,#0X00 MOV disBufDatHead+1,#0X00 MOV disBufDatHead+2,#0X11 MOV disBufDatHead+3,#0X11 MOV disBufDatHead+4,#0X11 MOV disBufDatHead+5,#0X11 MOV disBufDatHead+6,#0X11 MOV disBufDatHead+7,#0X11 MOV sec,#0X3A WHILE: JB key,KEYSCAN MOV sec,0x00 KEYSCAN: MOV A,sec SUBB A,#3CH;超过60s归零 JB CY,CLEAR MOV sec,#0X00;clr加ram地址无效 CLEAR: MOV A,sec MOV B,#0AH DIV AB;A/B,商存到A中,余数存B中 MOV disBufDatHead,A MOV disBufDatHead+1,B LCALL DISPLAY LJMP WHILE;循环 END;
总体思路是先初始化T0和显示缓冲区,然后在随后的while循环中将sec变量连续反汇编到显示缓冲区中(如果它大于或等于60 clear),则调用DISPLAY子例程显示,如果按按钮清除秒数
display子例程很难看. 功能是将内部ram40h到47h的8个字节用作显示缓冲区. 这8个字节对应8个数码管,每个数码管在相应的字节中显示内容.
它最初旨在用于外部击键. . . 结果,我停止使用时钟了. 搜索了很长时间后,我没有发现任何问题. 我必须先完成任务,然后再说.
说明说明:
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/dianqi/article-192503-1.html
是要进行民煮选举的
一个让人随便入侵领海领空的国家还谈什么强国
中国虽然国大人多