本仓库相关网址:
CSDN文章地址(待添加)
Gitee工程和源码地址 - https://gitee.com/langcai1943/8051-from-boot-to-application
相关仓库:
嵌入式整体介绍,里面也描述了部分8051的内容:
才鲸嵌入式 / 嵌入式知识图谱WiKi - https://gitee.com/langcai1943/embedded-knowledge-wiki
C语言框架讲解,让你对C语言要学哪些东西有一个完整的了解:
embedded_programming_skills/ 0_doc / 02-C语言框架讲解.md - https://gitee.com/langcai1943/embedded_programming_skills/blob/develop/0_doc/02-C语言框架讲解.md
$NOMOD51 ; Ax51宏汇编器控制命令:禁止预定义的8051
;------------------------------------------------------------------------------
; File Encoding: UTF-8
; 将狼才鲸于2022-09-29创建工程时,从Keil选择设备列表中的设备描述中拷贝过来的
; 芯片介绍:
; flexible configurable, single-clock 8051 compatible IP core with
; 9.4 to 12.1 times more performance than legacy 80C51
; (with Dhrystone v1.1 Benchmark on identical clock speed,
; depending on the MDU, number of DPTR and
; auto inc/dec/switch implementation).
;
; Optional features:
; 32 I/O lines,
; three 16-bit timer/counters,
; compare/capture unit (CCU),
; 18 interrupts/4 priority levels or 6 interrupts/2 priority levels,
; two serial interfaces (UARTs),
; serial peripheral interface (SPI),
; I2C interface,
; secondary I2C interface,
; 16-bit multiplication-division unit (MDU),
; multiple DPTR with auto-increment/auto-switch support,
; 15-bit programmable watchdog timer with configurable prescaler,
; power management unit (PMU),
; direct memory access (DMA) controller,
; real time clock (RTC),
; internally and externally generated wait states,
; software reset,
; program and data memory extension up to 8MB (banking).
;
; Optionally available: On-Chip Debug Support for
; Keil uVision Debugger.
;
; The R8051XC IP core can be implemented in FPGA and ASIC.
;
; *** This device is configured for 8 DPTR registers ***
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; This file is part of the C51 Compiler package
; Copyright (c) 1988-2005 Keil Elektronik GmbH and Keil Software, Inc.
; Version 8.01
;
; *** <<< Use Configuration Wizard in Context Menu >>> ***
;------------------------------------------------------------------------------
; STARTUP.A51: This code is executed after processor reset.
;
; To translate this file use A51 with the following invocation:
;
; A51 STARTUP.A51
;
; To link the modified STARTUP.OBJ file to your application use the following
; Lx51 invocation:
;
; Lx51 your object file list, STARTUP.OBJ controls
;
;------------------------------------------------------------------------------
;
; User-defined <h> Power-On Initialization of Memory
;
; With the following EQU statements the initialization of memory
; at processor reset can be defined:
;
; <o> IDATALEN: IDATA memory size <0x0-0x100>
; <i> Note: The absolute start-address of IDATA memory is always 0
; <i> The IDATA space overlaps physically the DATA and BIT areas.
; IDATA是8051 0x00~0x7F的128个iRAM区域
; 8051是8位CPU,数据总线8位,地址总线16位,地址范围0x0000~0xFFFF,但是地址分为0x0000~0x00FF和0x0100~0xFFFF两部分;
; 0x00~0xFF 256个地址属于iRAM,里面既有外设寄存器,也有CPU寄存器,也有通用寄存器;
; 0x0100~0xFFFF可以认为是64k 扩展RAM;
; 其中0x00~0x7F 128个是CPU通用的寄存器、可位寻址的寄存器,还有可作为堆栈区域的iRAM,这里称为iDATA;
; 另外0x80~0xFF 128个,属于SFR特殊功能寄存器,主要是外设寄存器和CPU寄存器。
IDATALEN EQU 80H ; 只是一个宏定义,8051通用寄存器的个数,0x00~0x7F
;
; <o> XDATASTART: XDATA memory start address <0x0-0xFFFF>
; <i> The absolute start address of XDATA memory
XDATASTART EQU 0 ; 64K扩展RAM的起始地址
;
; <o> XDATALEN: XDATA memory size <0x0-0xFFFF>
; <i> The length of XDATA memory in bytes.
XDATALEN EQU 0 ; 64K扩展RAM的长度,最大64K,最小0
;
; <o> PDATASTART: PDATA memory start address <0x0-0xFFFF>
; <i> The absolute start address of PDATA memory
PDATASTART EQU 0H ; 外部64K扩展RAM中的低256字节起始地址,这部分地址操作比较特殊
;
; <o> PDATALEN: PDATA memory size <0x0-0xFF>
; <i> The length of PDATA memory in bytes.
PDATALEN EQU 0H ; 外部64K扩展RAM中的低256字节总长度
;
;</h>
;------------------------------------------------------------------------------
;
;<h> Reentrant Stack Initialization
;
; The following EQU statements define the stack pointer for reentrant
; functions and initialized it:
;
; <h> Stack Space for reentrant functions in the SMALL model.
; <q> IBPSTACK: Enable SMALL model reentrant stack
; <i> Stack space for reentrant functions in the SMALL model.
; 是否初始化堆栈,大概几十个字节
IBPSTACK EQU 0 ; set to 1 if small reentrant is used.
; <o> IBPSTACKTOP: End address of SMALL model stack <0x0-0xFF>
; <i> Set the top of the stack to the highest location.
; 可重入堆栈(仿真栈)的最高地址,一般是0xFF,0x00~0x1F是四组R0~R7寄存器,0x20~0x2F是位寻址区域,0x30开始是堆栈的默认起始地址
IBPSTACKTOP EQU 0xFF +1 ; default 0FFH+1
; </h>
;
; <h> Stack Space for reentrant functions in the LARGE model.
; <q> XBPSTACK: Enable LARGE model reentrant stack
; <i> Stack space for reentrant functions in the LARGE model.
XBPSTACK EQU 0 ; set to 1 if large reentrant is used.
; <o> XBPSTACKTOP: End address of LARGE model stack <0x0-0xFFFF>
; <i> Set the top of the stack to the highest location.
; 扩展RAM中堆栈的栈顶在64K的位置
XBPSTACKTOP EQU 0xFFFF +1 ; default 0FFFFH+1
; </h>
;
; <h> Stack Space for reentrant functions in the COMPACT model.
; <q> PBPSTACK: Enable COMPACT model reentrant stack
; <i> Stack space for reentrant functions in the COMPACT model.
PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.
;
; <o> PBPSTACKTOP: End address of COMPACT model stack <0x0-0xFFFF>
; <i> Set the top of the stack to the highest location.
; 扩展64K RAM中低256字节中作为堆栈,栈顶0xFF
PBPSTACKTOP EQU 0xFF +1 ; default 0FFH+1
; </h>
;</h>
;------------------------------------------------------------------------------
;
; Memory Page for Using the Compact Model with 64 KByte xdata RAM
; <e>Compact Model Page Definition
;
; <i>Define the XDATA page used for PDATA variables.
; <i>PPAGE must conform with the PPAGE set in the linker invocation.
;
; Enable pdata memory page initalization
; 64扩展RAM需要进行分页读取256字节x256页
PPAGEENABLE EQU 0 ; set to 1 if pdata object are used.
;
; <o> PPAGE number <0x0-0xFF>
; <i> uppermost 256-byte address of the page used for PDATA variables.
PPAGE EQU 0
;
; <o> SFR address which supplies uppermost address byte <0x0-0xFF>
; <i> most 8051 variants use P2 as uppermost address byte
; 高地址字节占用P2 IO口锁存器地址0xA0,这应该是一种约定俗成的用法
PPAGE_SFR DATA 0A0H
;
; </e>
;------------------------------------------------------------------------------
; Standard SFR Symbols
; SFR特殊功能寄存器(芯片寄存器和外设寄存器)地址定义
ACC DATA 0E0H
B DATA 0F0H
SP DATA 81H
DPL DATA 82H
DPH DATA 83H
; 声明本文件模块函数入口
; 这也是一个标量,这个标量会在别的地方真正定义
NAME ?C_STARTUP ; 芯片上电时运行的第一条语句所在处
?C_C51STARTUP SEGMENT CODE ; 声明代码段名
?STACK SEGMENT IDATA ; 声明iRAM数据段名
;;以下是再定位内部RAM数据段
RSEG ?STACK ; 用再定位段做当前段,以下的内容都放在这个数据段中
DS 1 ; 从当前位置预留1字节空间备用
EXTRN CODE (?C_START) ; 声明外部有main函数入口
PUBLIC ?C_STARTUP ; 输出本地的模块名标量
;;以下是绝对代码段
CSEG AT 0 ; 绝对代码段,地址从零开始
?C_STARTUP: LJMP STARTUP1 ; 本程序第一行运行的代码
;;以下是绝对代码段
RSEG ?C_C51STARTUP ; 用再定位段做当前段,以下内容放在当前端
STARTUP1:
; 清0x00~0x7F区域的寄存器
IF IDATALEN <> 0 ; 如果0x00~0x7F 127个通用寄存器数量不等于0,则进行以下处理
MOV R0,#IDATALEN - 1 ; 将最大的地址暂存到寄存器1
CLR A ; 寄存器2赋值0(清寄存器)
IDATALOOP: MOV @R0,A ; 将当前地址的寄存器赋值0
DJNZ R0,IDATALOOP ; R0减1不为零则跳转到IDATALOOP标号继续执行;deduct减去,add加上
ENDIF
; 清64K所有的扩展RAM
IF XDATALEN <> 0
MOV DPTR,#XDATASTART ; 将外部RAM起始地址0x00赋值给寄存器0;DPTR是16位的访问扩展RAM的地址
MOV R7,#LOW (XDATALEN) ; 长度低字节赋值到寄存器0
IF (LOW (XDATALEN)) <> 0 ; 如果低字节不为0
MOV R6,#(HIGH (XDATALEN)) +1 ; ; 进行256字节(BANK)对齐,只要一个BANK有数据,则清整个BANK
ELSE ; 如果低字节为0
MOV R6,#HIGH (XDATALEN) ; 长度高字节赋值到寄存器1
ENDIF
CLR A
XDATALOOP: MOVX @DPTR,A ; 赋值一个外部RAM地址为0;低256字节需要用MOVX @R0
INC DPTR ; 外部64K RAM地址自增1
DJNZ R7,XDATALOOP ; 双层循环的第一层循环
DJNZ R6,XDATALOOP ; 双层循环的第二层循环
ENDIF
; 定义好扩展64K RAM高地址值
IF PPAGEENABLE <> 0
MOV PPAGE_SFR,#PPAGE
ENDIF
; 清64K外部RAM中特殊的低256字节
IF PDATALEN <> 0
MOV R0,#LOW (PDATASTART) ; 给变量0赋值特殊RAM起始地址,限定256以内
MOV R7,#LOW (PDATALEN) ; 给变量1赋值特殊RAM长度,限定256以内
CLR A
PDATALOOP: MOVX @R0,A ; 地址清零;地址自增;长度未循环完则一直循环
INC R0
DJNZ R7,PDATALOOP
ENDIF
; 如果需要,则定义各栈顶地址
; 8051数据存放的位置有几类,读写的速度也不一样,和32位CPU不一样:
; data:内部256字节iRAM,idata:64k扩展RAM的低256字节部分,
; pdata:R0 R1寻址的扩展64k RAM,xdata:DPTR寻址的扩展64k RAM
; 8051中分为硬件栈和仿真栈
IF IBPSTACK <> 0
EXTRN DATA (?C_IBP) ;
; 仿真栈所在的iRAM地址栈顶,比如0xFF
MOV ?C_IBP,#LOW IBPSTACKTOP
ENDIF
; 如果需要,定义64K扩展RAM中的栈顶
IF XBPSTACK <> 0
EXTRN DATA (?C_XBP)
MOV ?C_XBP,#HIGH XBPSTACKTOP
MOV ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF
; 如果需要,定义64K扩展RAM中的低256字节的栈顶
IF PBPSTACK <> 0
EXTRN DATA (?C_PBP) ; Keil内部函数指针,
MOV ?C_PBP,#LOW PBPSTACKTOP
ENDIF
MOV SP,#?STACK-1 ; iRAM数据段地址
; This code is required if you use L51_BANK.A51 with Banking Mode 4
;<h> Code Banking
; <q> Select Bank 0 for L51_BANK.A51 Mode 4
#if 0
; <i> Initialize bank mechanism to code bank 0 when using L51_BANK.A51 with Banking Mode 4.
EXTRN CODE (?B_SWITCH0) ; 初始化扩展RAM bank0
CALL ?B_SWITCH0 ; init bank mechanism to code bank 0
#endif
;</h>
LJMP ?C_START ; 跳转到main函数执行
END ; 汇编文件结束