13 51 MCU compilation: use Keil C51 simulator for IO input and print the input results [13 of the series of tutorials]

51 MCU assembly: use Keil C51 simulator for IO input and print the input results [13 of the series of tutorials]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 介绍:	【51单片机汇编】用Keil C51模拟器对IO口输入,并产生中断,在模拟器输出窗口用串口打印出来
; NOTE:		File format: UTF-8
; 备注:	1、本工程默认使用Keil模拟器运行,无需硬件;按F7编译后,按Ctrl+F5运行,
;			调出UART #1窗口(要先运行程序):点击软件的View-->Serial Windows-->UART #1,
;			后续要在Keil软件的UART #1窗口中看串口的输出结果;
;			2、点击软件Peripherals-->IO-Ports-->Port 0,调出IO0输入的窗口,第一行选中
;			bit1,在第二行bit1的位置勾选就是输入1,取消勾选就是输入0;此时如果勾选了,
;			下面UART #1窗口就会不断输出Hello world,取消勾选了就停止输出;
; 作者		将狼才鲸
; 日期		2023-06-11
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    • The effect of the Keil simulator running:
      insert image description here
  • Part of the source code display:

;;
; 包含头文件和其它源文件,也可以用#include <REGISTERS51.INC>,同样有效;
; 被包含的文件不要用END指令放在文件尾,否则编译器会报错
$INCLUDE(REGISTERS_51.INC)	; AT89C51芯片寄存器定义
$INCLUDE(START.ASM)			; 上电复位入口,和中断处理入口
$INCLUDE(IRQ.ASM)			; 中断处理程序的中转环节
$INCLUDE(RESET.ASM)			; 进行一些跳转到C语言之前的寄存器配置工作
$INCLUDE(DEVICE_INIT.ASM)	; 汇编的系统初始化函数

EXTERN CODE(_MAIN)	; 1、声明.c文件中的main()函数,或者.asm中的_MAIN函数;C语言中的函数
					;	只要前面加上下划线,就能被汇编中识别;同样的,汇编中的函数
					;	如果前面有下划线,去掉下划线后就能被C语言代码识别;
					;	函数名会忽略大小写,_Main,_main都会有效
					; 2、EXTERN类似于C语言的extern,打破文件包含关系,可以调用任意文件中的函数;
					; 3、EXTERN后面可以跟各种伪指令,EXTERN CODE表示代码段空间的地址(或称之为函数);
					; 4、和PUBLIC成对使用,函数原始位置要输出这个名称;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 汇编主函数 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
; 功能:先不使用C语言的main函数,而是所有功能都用汇编完成
; 参数:无
; 返回:无
;;
ASM_MAIN:
	; 从串口打印开机信息
	LCALL UART_PRINT

	;;
	; 轮询IO口输入是否被改变,有改变则打印信息;也可以像之前的教程3的定时器Demo那样,
	; 将IO口的输入做成在中断中响应,并在IO输入中断中设置断点来达到测试目的;
	CLR P0.1	; 先将IO口拉低(认为该IO是输入输出双向的),后续通过模拟器来拉高拉低
LOOP_IO_INPUT_CHECK:
	LCALL IO_INPUT_CHECK
	LJMP LOOP_IO_INPUT_CHECK	; 死循环

	; 汇编Boot完成后进入C语言主函数
	LCALL _MAIN	; 跳转到C语言的main函数
	RET

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 私有函数 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INFO_PRINT_1:			; 类似于字符串常量宏定义
DB 'Hello world!....'	; DB类似于C语言定义一个常量,当前总共16字节数据
INFO1_LEN EQU 10H		; 类似于#define INFO1_LEN 0x10

;;
; 函数功能:	串口发送字符串数据
; 参数:		无,使用全局变量INFO_PRINT_1
; 返回值:		无
;;
UART_PRINT:
	; 局部变量R0,类似于C语言中for循环中的i;
	; A,类似于地址中的数据buf[i];
	MOV  A, R0		; 将通用寄存器R0存到ACC累加器,累加器调用时可以用名字ACC,可以用名字A,
					; 写程序时常用ACC作一个变量,类似于C语言的int tmp,然后使用tmp
	PUSH ACC		; 1、压栈R0,防止之前别人有用通用寄存器,先压栈报错,别破坏别的
					; 中断或函数已经存过的值;
					; 2、R0~R7相当于C语言定义了int tmp0; ~ int tmp7;七个全局变量,每个函数
					; 都很少使用局部变量,而是使用这些全局变量,因为R0~R7速度快,因为大家都用,
					; 所以函数进入和退出要压栈推栈;你只需要知道哪些会被别人用,和本函数会用
					; 哪些R0~R7之间的全局变量,然后处理对应的R0~R7寄存器即可;
					; 3、C语言的函数执行也有压栈弹栈操作,不过是编译器自动完成的,所以
					; 嵌入式编程时还需要注意堆栈大小,不能在函数内定义超出堆栈长度的数组,
					; 否则程序会跑飞;

	MOV  R0, #00H	; 类似于:int i = 0;
LOOP_PRINT_1:
	MOV  DPTR, #INFO_PRINT_1	; 1、把字符串指针放入DPL DPH数据指针中,DPTR是两个寄存器合在一起的名字
								; 2、不像C语言定义一个char *buf; 可以直接使用buf里的数据,
								; 汇编使用缓存或数组地址时要先放进DPTR,DPTR就类似于buf地址;
								; 3、立即数常量的使用前加#号,这种固定用法和指令集有关
	MOV  A, R0			; for (int A = 0;... 此时将A寄存器作为类似C语言里循环的i变量
	MOVC A, @A + DPTR	; A = *(A + DPTR), 整条语句是一条固定的指令,这里的@是一个固定的用法
						; MOVC是查表指令,也是类似于C语言的=赋值,还有@取址的效果;
						; 类似于C语言的for(...i++) {
    
    A = buf[i];}
	LCALL UART_SEND		; 1、从串口发送1个字节,串口收发中断都是一个字节一次,不像有些32位
						; CPU的串口模块,串口中断来时会携带长度信息,一次收多字节数据;
						; 2、传入参数为A: 要发送的一个字节;
	INC  R0			; R0++,类似于C语言中for循环的i++
	CJNE R0, #INFO1_LEN, LOOP_PRINT_1	; 1、比较累加器和立即数,不相等则转移
										; 2、立即数宏定义的使用前加#号,这种固定用法和指令集有关

	POP  ACC		; 弹栈
	MOV  R0, A		; 将压入的值还原
	RET				; 函数返回

;;
; 功能:串口发送1字节数据(非中断模式,是轮询模式)
; 参数:A	1字节数据
; 返回:无
;;
UART_SEND:
	MOV SBUF, A
LOOP_LB_SEND_WAIT:	; 等待最后一个bit发送完成
	MOV A, SCON
	ANL A, #02H	; 查询发送中断标志,一个字节是否发送完成;A &= (0x1 << 1); 从0算起的第1bit
	JZ  LOOP_LB_SEND_WAIT	; A为0则跳转,if (A == 0) continue
	ANL SCON, #0FDH			; C语言:SCON &= 0xFD,也就是SCON &= ~(0x1 << 1),清除发送中断标志
	RET

IO_INPUT_CHECK:
	; 轮询并等待IO P0.1变成高电平
LOOP_IO_P0_1_WAIT:
	MOV C, P0.1	; 将IO电平读到进位C位(PSW寄存器的CY)
	JNC LOOP_IO_P0_1_WAIT	; 进位C为0则跳转,if (C == 0) continue;
	; 打印IO信息
	LCALL UART_PRINT	; 已获取到IO变高,打印Hello world
	RET

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	END

Guess you like

Origin blog.csdn.net/qq582880551/article/details/131158460