51单片机开发环境搭建以及入门汇编代码象棋小子10482729751.51

51单片机开发环境搭建以及入门汇编代码Proteus中文入门教程.doc,讲述了Proteus如何搭建电路以及进行51单片机的仿真

棋童1048272975

一、51单片机概述

51单片机是所有兼容Intel 8031指令系统的单片机的统称。 目前教材基本上都是以早期的MCS-51为原型来讲解微型计算机的原理及其接口技术。 早期的51单片机功能较弱,需要扩展ROM、RAM等,才能构成更为复杂的系统。 如今流行的8位51单片机比早期的芯片有更多的功能扩展,性能也很强。 生产51单片机的厂家有很多,如Atmel的at80c51系列、华邦w78c051系列、宏晶stc80c51系列等,其中台湾宏晶STC系列51单片机在国内特别受欢迎。 因此,笔者采用宏碁高性价比的51单片机stc12c5a60s2来进行开发讲解。 这款51单片机已经是宏昌的第N代产品了。 其主要特点如下:

1.1. 增强型8051 CPU,1T,单时钟/机器周期,指令代码与传统8051完全兼容;

1.2. 工作频率范围:0-35MHz,相当于普通8051的0~420MHz;

1.3. 用户应用空间为60K字节,芯片上集成1280字节RAM;

1.4. 36个通用I/O口(以PDIP40封装为例),可设置为准双向口/弱上拉、推挽/强上拉、仅输入/高阻、开漏、每个I/O端口驱动能力可以达到20mA,但整个芯片最大不要超过55Ma;

1.5. ISP(In-System Programmable)/IAP(In-Application Programmable),无需专用编程器,也无需专用仿真器,直接通过串口(P3.0/P3.1)下载用户程序。

1.6. 内部集成MAX810专用复位电路、2通道PWM、8通道高速10位A/D转换(250K/S)、EEPROM、看门狗、内部RC振荡器、4个定时器、7通道外部I/O口中断等

特别需要注意的是,stc的新一代单片机具有1T单时钟/机器周期,这与教材中介绍的早期51单片机具有12T单周期不同。 在软件中实现延时时,需要注意剩余的扩展特殊功能寄存器。 请参考stc12c5a60s2的数据手册。

2. 51单片机编程环境概述 2.1. 代码编译工具

51单片机开发软件基本采用Keil C51集成开发环境。 Keil C51是德国Keil Software公司(被ARM收购)生产的51系列兼容单片机C语言软件开发系统。 它提供了C编译器、宏汇编、连接器、库管理和强大的仿真调试器等。最新版本已达到uVision5。 这里需要注意的是,Keil C51 与 ANSI C 并不完全相同。由于 Keil C51 是面向 51 单片机的,为了更好地细化 51 架构,Keil C51 扩展了一些特有的关键字、语法描述等。例如,用code来描述放置在代码区的常量,用data来描述直接寻址区的变化,用sfr来声明特殊功能寄存器等。

51单片机开发环境搭建以及入门汇编代码象棋小子10482729751.51

图2.1-1

2.2. 代码调试工具 2.2.1. Keil自带仿真调试器

除了编译和链接工具外,Keil集成开发环境还附带了强大的仿真调试器。 当然,软仿真可以看到Keil编译出来的汇编代码,单步调试可以跟踪各个寄存器的状态变化。 但软仿真无法获得真实的外部输入状态,例如模拟真实开发板的按键输入。 在调试代码时,我们经常需要知道编译器是否按照要求编译了代码。 因此,我们可以让编译器输出它如何编译和链接文件。 我们可以通过检查这些来了解编译器在编译c时生成的汇编代码和链接符号。 、内存分配等信息。 Keil可以在Target属性中设置Listing列。 例如,C 编译器列表选项是 c 编译器输出选项。 点击Assembly Code,会在.lst文件中输出c编译对应的汇编代码。 C Preprocessor Listing是c编译器预处理输出的信息,AssemblerListing是汇编器输出的处理信息,LinkerListing是链接器输出的处理信息(在.m51后缀文件中)。 这包括编译器对内存和每个函数的分配。 通常可以通过跟踪查看编译后的汇编代码以及代码的链接信息来确定代码的问题。

51单片机开发环境搭建以及入门汇编代码象棋小子10482729751.51

图2.2.1-1

51单片机开发环境搭建以及入门汇编代码象棋小子10482729751.51

图2.2.1-2

2.2.2. Proteus仿真软件

Proteus软件是英国Lab Center Electronics公司推出的一款EDA工具软件。 它不仅具有其他EDA工具软件的仿真功能,还可以仿真微控制器和外围器件。 Proteus具有电路仿真功能,可以仿真一些最基本的电子元件,如LED、数码管、键盘等,可以仿真51单片机的代码运行。 这里需要说明的是,请务必不要将仿真电路效果图与真实的硬件开发混淆。 电路仿真软件往往是逻辑电路连接,根本不能用来解释真实的硬件开发过程。 另外,Proteus在模拟51单片机时也会出现一些逻辑问题。 例如,在硬件上实际可运行的代码无法在Proteus上模拟达到效果。 只需修改代码顺序即可。 简而言之,Proteus 可以胜任小型代码。 如果代码太复杂,模拟任务就会达到100%,就无法再进行模拟了。 因此,笔者建议初学者可以先使用Proteus进行仿真,进行一些基础练习,熟悉汇编语言、51单片机状态变化、C语言等,验证对51单片机架构和代码实现的理解。 理解。 学习到一定程度后,还需要一块51开发板进行开发实践。 毕竟仿真软件只能仿真少数外设,无法仿真复杂的硬件和代码。

51单片机开发环境搭建以及入门汇编代码象棋小子10482729751.51

图2.2.2-1

2.3. 代码烧写工具

通过STC_ISP工具下载Keil C51编译的hex文件并连接串口线(一般使用USB转串口线)。 代码编程和传输是通过51单片机的uart串口信号线Tx和Rx完成的。 stc单片机实现isp下载是因为芯片内部有厂家固化的代码。 上电复位后,首先执行固化的代码,检测串口是否收到特定命令,如果有特定命令,则进入下载模式,与上位机的ISP下载软件通信,将代码下载到微控制器的ROM区域。 如果没有有效的串口下载命令,则跳转执行真正的用户代码,即从0000H开始执行代码。

51单片机开发环境搭建以及入门汇编代码象棋小子10482729751.51

图2.3-1

3.组装流水灯入门代码

笔者认为学习51单片机不仅仅是通过别人的例子用C语言来模仿和编写类似的功能。 你必须清楚自己的编码意图,这样才能不带任何套路地掌控代码的编写。 因此,学习51单片机实际上更准确的是学习微型计算机的原理和接口技术。 微型计算机的原理和接口技术对于51、arm或其他架构的MCU是通用的。 通过51学习微机原理会涉及到汇编语言,因为只有汇编语言才能直接描述51内部工作状态。作为经历过的人,笔者建议初学者先从51微机原理和汇编开始。 C语言只是对汇编语言的一些处理过程进行了简化和封装。 学完了汇编,C语言自然也就达到相应的水平了。 另外,对于软件错误调试,只能跟踪汇编代码并检查寄存器的状态。 如果想要学习ARM,从事更深入的嵌入式开发,汇编是必不可少的。

3.1. 硬件原理图

P0口连接8个LED。 当CON2短路时,只要P0口相应位为0(低电平),相应的LED就会点亮。 另外请解释一下为什么P0对应位为1时不点亮而是用0点亮。 这是因为传统的51单片机I/O口是弱上拉,高电平无法输出大电流(相对低电平)。 平拉电流估计为ua级,但几ma的低级灌电流不是问题。 对于stc系列51单片机,I/O口可以配置为推挽输出,这样高低电平都可以达到20ma的输出/灌电流(手动数据)。

51单片机开发环境搭建以及入门汇编代码象棋小子10482729751.51

图3.1-1

3.2. 项目建设

打开Keil C51,Project->NewuVersion Project,保存工程后,选择51单片机,CPU为Atmel的AT89C52。 这里需要注意的是,Keil没有stc系列的51单片机可供选择。 只要是51核的,Keil下任意一个都可以。 一个制造商可以为任何 51 微控制器编写代码,因为这些代码都是兼容的。 不同厂家的芯片之间的区别只是ROM大小、RAM大小、片上外设以及一些厂家特定的特殊功能寄存器的定义。 这些都可以在项目和代码中重新定义,编译器会按照要求老老实实地编译代码。 选择cpu后,会提示是否将51的启动代码添加到工程中。 由于我们是用汇编语言编写的,所以这里不需要它。 添加启动代码后,会和我们自己的汇编代码定义冲突。 这里需要说明的是,启动代码是初始化C环境所需的文件。 启动代码会在C代码运行时设置栈,清除全局变量,静态变量区等。这就是为什么我们在c文件中定义一个全局变量,这个变量的默认初始值为0(C标准)。

3.3. 代码编写

新建文件,命名为LEDs.ASM,ASM是51汇编文件后缀,保存并添加到工程中。 代码注释中解释了汇编的一些基本用法。 更多汇编用法请谷歌、百度。 这里需要说明的是,51单片机的第一条指令位置在0H,相邻的地址分配给相应的中断。 因此,第一条指令常常会跳转以避开中断向量地址区域。 下面的代码实现8个LED灯依次点亮,点亮延时1s。 该汇编代码模仿了C语言函数的结构化编程。 您可以类似地了解C编​​译器如何处理C函数并生成汇编语言。 当然编译器汇编的质量基本上无法达到手工汇编的质量。

组织 0H ; 表示紧随其后的指令地址为0000H

JMP 开始; 无条件跳转到Begin以避免中断向量地址

ORG 0BH ;000BH为定时器T0的中断处理入口

JMP T0_INT; T0定时器中断未使用,仅用于代码说明

T0_INT:

; 当中断发生时,当前程序运行地址PC会自动压入栈sp

; 中断处理完毕后,使用RETI中断返回,将栈sp从栈中弹出到PC并返回中断程序。

雷蒂

LED1 EQUP0.0; LED1由P0口的bit 0控制,类似如下

LED2 设备 P0.1

LED3 EQU P0.2

LED4 EQU P0.3

LED5 EQU P0.4

LED6 EQU P0.5

LED7 EQU P0.6

LED8 EQU P0.7

组织100H

开始:

MOV P0,#0xff;P0口输出全1,所有LED熄灭

环形:

; R6和R7是传递给调用函数的参数。 参数为 16 位,需要 2 个字节。

; _Delay_ms对应的c函数原型为void Delay_ms(intnCount)

; 总延时nCount * 1ms(12M普通8051),对于stc指令周期1T

; 延迟 nCount * (1/6)ms (12M)

清除 LED1; 直接位清除指令,清除P0口的位0,LED1点亮

MOV R7,#(1000&0xff); 参数为1000,正常8051延时为1s

MOV R6, #((1000>>8) & 0xff) ; 16位变量需要2个字节

调用_Delay_ms; 延迟n倍1ms(正常51),延迟n倍1/6ms(stc 51)

设置 LED1; 直接位设置指令,设置P0口的位0,LED1熄灭

清除 LED2

MOV R7,#(1000&0xff); 普通8051延时为1s,stc要从1000改为1000*6

MOV R6, #((1000>>8) & 0xff) ; 让编译器来计算而不是手动计算。

CALL_Delay_ms

设置LED2

清除 LED3

MOV R7,#(1000&0xff)

MOV R6, #((1000>>8) & 0xff)

CALL_Delay_ms

设置LED3

清除 LED4

MOV R7,#(1000&0xff)

MOV R6, #((1000>>8) & 0xff)

CALL_Delay_ms

设置LED4

清除LED5

MOV R7,#(1000&0xff)

MOV R6, #((1000>>8) & 0xff)

CALL_Delay_ms

SETB LED5

清除 LED6

MOV R7,#(1000&0xff)

MOV R6, #((1000>>8) & 0xff)

CALL_Delay_ms

SETB LED6

清除LED7

MOV R7,#(1000&0xff)

MOV R6, #((1000>>8) & 0xff)

CALL_Delay_ms

SETB LED7

清除LED8

MOV R7,#(1000&0xff)

MOV R6, #((1000>>8) & 0xff)

CALL_Delay_ms

SETB LED8

MOV P0,#0; 常数存储在直接地址中,P0口清零,LED全亮。

MOV R7,#(1000&0xff)

MOV R6, #((1000>>8) & 0xff)

CALL_Delay_ms

MOV P0,#0xff

MOV R7,#(1000&0xff)

MOV R6, #((1000>>8) & 0xff)

CALL_Delay_ms

JMP 循环; LOOP循环

; 遵循keil c和汇编调用规则来命令函数和传递参数。 您现在可以忽略它们。

; 使用CALL调用函数将导致硬件将调用PC地址压入堆栈。

; 处理完毕后,使用RET函数返回,将栈sp从栈中弹出到PC并返回到调用程序

_延迟_毫秒:

推ACC; 子函数需要使用累加器,需要将其压入堆栈,以避免覆盖调用前的值。

推 PSW; 程序状态寄存器已使用,需要压入堆栈

MOV A,R0; 使用R0寄存器,没有直接寄存器名push指令

推ACC; 将堆栈推入累加器

金属氧化物A,R1; 使用R1寄存器,以同样的方式压栈

普沙克

; 下面是16位减1减法运算,高8位在R6,低8位在R7

; 数据操作涉及进位/借位,只能通过累加器ACC完成

延迟:

CLR C; 清除借用标志

MOV A,R7; 低 8 位值被赋予累加器。 只有累加器操作的指令。

SUBB A,#1; 减1,会改变程序状态标志(进位/借位)

MOV R7,A; 运算结果返回原变量

JNC 延迟一次; 如果没有借位,则说明未达到延迟次数,延迟一次跳转。

CLR C; 发生借位,需要将高8位R6减1

MOV A、R6

SUBB A,#1

MOV R6,A

JNC 延迟一次; 高8位没有减为0,说明延迟次数还没有达到。

POP ACC; 高8位也为0,低8位不能再借用。 延迟返回

MOV R1,A; 返回时先出栈,出栈的顺序与压入栈的顺序相反。

POP ACC; 并且PUSH和POP指令必须一一对应,否则程序就得飞了

MOV R0,A

POP PSW

POP ACC

RET; 子函数返回,与c函数相同

; DelayOnce执行的机器周期总数为1+R0*(1+R1*2+2)+2=997

; 如果普通51晶振是12M,每个机器周期是1us,那么DelayOnce延迟就是1ms。

; 对于stc51,使用相同的晶振,命令速度快6倍,DelayOnce延时1/6ms

延迟一次:

MOV R0,#2; 普通51个机器周期1(stc指令比普通快6倍)

延迟1:

MOV R1,#247; 普通51个机器周期1(stc快6倍)

DJNZ R1, $ ; R7减1不为0,跳转到当前地址循环,机器周期数2

DJNZ R0,延迟1; 机器周期数 2(stc 快 6 倍)

JMP 延迟; 延迟一次,机器周期数2(stc快6倍)

结尾 ; 汇编代码结束

3.4. 代码执行

在Keil上选择Create HEX File复选框来编译并生成hex文件。 可以直接在Keil中调试,通过查看P0口数据的变化来跟踪代码。 注意将模拟时钟设置为12M。 更直观的是使用Proteus搭建51单片机仿真电路,将8个LED连接到P0口,就可以看到效果。 注意将模拟时钟设置为12M。 如果你有51开发板,只需将代码下载到单片机中即可(但对于stc 1T 51单片机,需要修改代码中的延时参数)。

51单片机开发环境搭建以及入门汇编代码象棋小子10482729751.51

图3.4-1 Proteus仿真代码效果图

4. 总结

作者对51单片机进行了概述(以stc12c5a60s2为例),并讲解了其基本编译、调试工具、环境搭建。 本文简单给出了使用C函数结构编写的流水冷的汇编代码,让读者对汇编有一个初步的了解以及C编译和汇编的过程。 由于作者知识有限,文章中的一些个人观点可能非常片面,文章中可能存在一些问题。 有很多错误,请指正。

由于一项技术不可能用三言两语解释清楚,因此作者只能在文章中进行简单描述。 一些初学者可能会发现常规组装太困难。 作者想要解释的是,学习是一个渐近的过程。 只要学会了流程,就会有潜移默化的进步。 笔者认为以下信息与本文的研究相关,推荐大家学习或参考。

A。 stc12c5a60s2数据手册非常有用。 包含大量的编程实例代码和详细的stc51系列单片机寄存器编程说明。

b. 微控制器初学者实验指南.doc。 它仅适用于初学者。 讲述如何连接USB转串口线下载代码、keil安装和工程构建。

C。 Keil软件用户手册.ppt,简要讲解了Keil软件项目的搭建和调试。

d. Proteus中文入门教程.doc,讲述Proteus如何搭建电路并模拟51单片机。

e. 51汇编指令.ppt,里面很好的介绍了51汇编指令的使用、伪指令等,但是细节还不够。 例如,没有解释指令执行后堆栈的变化。 51微机原理教材的汇编指令信息是最好的。

F。 LEDs.ASM,汇编工程代码,添加到keil工程中进行编译。

单片机

单片机学习过程中的酸甜苦辣只有学过的人深有体会

2024-2-7 6:01:17

单片机

51、MSP430、STM32、TMS、AVR单片机之间的优缺点

2024-2-7 7:01:35

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索