电子计算器(汇编)
1. 电子计算器简介
1.1 设计目的
电子计算器相比于人手算可谓有着不可或缺的优势,首先电子计算器有着极高的计算速度,其次它还可以保证很高的稳定性和准确性,这对于学理工科的我们来说可谓是一大帮手,同时由于51单片机的价格低廉,结构简单,这从而使得利用单片机来设计电子计算器拥有极高的价值性和实用性。
1.2 设计要求
本课题的主要内容是采用单片机实现一个简单的电子计算器,通过这个实习进一步加深《C语言程序设计》、《单片机原理及应用》等相关课程中的理论知识,熟练掌握单片机的编程、调试和应用系统的开发。
基本要求:
(1)行列式按键的读取、数码管动态扫描显示;
(2)实现计算结果在0~9999范围内的正负整数的加、减、乘、除。
(3)16个按键的功能划分:
数字键:0-9;
功能键:加法键、减法键、乘法键、除法键、等于键、复位键
发挥部分:
能进行浮点小数的输入及运算。
2. 硬件设计
2.1 51单片机最小系统
51单片机最小系统是指能使单片机正常工作的最简电路,如图2.1所示,其中大体包括三个部分:
- AT89C51单片机;
- 晶振电路模块;
- 复位电路模块。
图2.1 51单片机最小系统
2.1.1 AT89C51单片机
AT89C51是一种带4K字节FLASH存储器的低电压、高性能CMOS 8位微处理器。如图2.1.1所示,AT89C51有40个引脚,32 个外部双向输入/输出(I/O)端口,同时内含2个外中断口,3个16位可编程定时计数器,2个全双工串行通信口,2个读写口线。其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的Flash存储器可有效地降低开发成本。
AT89C51 提供以下标准功能:4k 字节Flash 闪速存储器,256字节片内数据存储器(00H -7FH为片内RAM,80H-FFH为特殊功能寄存器SFR),32 个I/O 口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89C51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
图2.1.1 AT89C51单片机
2.1.2 晶振电路模块
如图2.1.2所示,该模块由一个12MHz的晶振和两个30pF的电容构成,其中晶振的作用是产生一个稳定的时钟信号,而电容的作用则是将晶振中一些无用的高频信号过滤掉,提高整个模块工作的稳定性。
该模块的主要用途有两个:
(1)为单片机的正常工作提供一个稳定的工作时序;
(2)为定时器的定时提供一个准确的脉冲信号,本次实习共使用了两个定时器,其中定时器0设置在了工作模式1,初值为60536,用于每隔5ms执行一次数码管的动态显示工作;而定时器1也设置在了工作模式1,初值为15536,同时外加变量T1_NUM的循环迭代,用于每隔500ms令数码管的某一位片选取反,从而达到闪烁的目的。
图2.1.2 晶振电路模块
2.1.3 复位电路模块
如图2.1.3所示,该模块由一个按钮,一个电容和一个电阻构成,其中电容与电阻构成了一个RC的充电回路,当通电的一瞬间,由于电容两端电压无法瞬间突变,因此RST会在大概50ms的时间内保持高电平,50ms之后RST上的电平则可认为是低电平,这样就能达到上电复位并使单片机正常工作的作用。
同时,在电容的两端还外加了一个轻触按钮,当按下该按钮时,RST上的电平则会重新变为高电平,让单片机复位,而当松开该按钮后,由于电容的充电作用,RST上的电平则会重新置为低电平,单片机正常工作。
图2.1.1 复位电路模块
2.2 矩阵键盘模块
如图2.2所示,该模块由16个轻触按钮构成,其中同一行的按钮的一端都相连,同一列的按钮的一端也相连。在编程时采用行输出,列输入的方法将按键的列信息读入后;再采用列输出,行输入的方法将按键的行信息也读入后,便可得知此刻是哪一个键被按下了。
图2.2 矩阵键盘模块
此外,如表2.2所示,特别说明一下本次矩阵键盘的按键布局。此次矩阵键盘共有16个键,其中有10个为数字键入键,另外6个均为功能键,下面对其各自的用途进行简单的说明:
- C:全部清零键。按下该键后计算器将清零一切信息。
- CE:单个撤回键。按下该键后将向前撤回一个数字或者运算符。
- ".":小数点。按下该键后,编辑位的前一位将会加上一个小数点,而单片机在进行运算时,将会进行浮点运算。
- Operator:运算符。按下该键后运算符将会从"+ - × ÷"这四个运算符中循环替换。
- Confirm:运算符确认键。按下该键后则代表已确认运算符的选择,则数码管会清零,便于下一个运算数的输入。
- "=":等于号。等于按下该键后,单片机将会执行运算并显示结果。
表2.2 矩阵键盘布局
7 |
8 |
9 |
C |
4 |
5 |
6 |
. |
1 |
2 |
3 |
Operator |
CE |
0 |
Confirm |
= |
2.3 数码管显示模块
如图2.3所示,该模块由两个四位的七段共阴极数码管构成,其中段选位为高电平有效,片选位为低电平有效,另外该模块还需特别注意,由于P0口在不加上拉电阻之前是没有任何驱动能力的,因此在连接此模块时,P0口一定要外加上拉电阻。
该模块的主要用途是用于显示矩阵键盘所按下的键值,以及最后计算的结果。
图2.3 数码管显示模块
3. 软件设计(汇编)
3.1 变量的定义
由于本次程序定义的变量较多,所以在介绍各函数之前,先说明一下每个变量的作用和用途。
表3.1.1为用于浮点型运算所定义的变量。
表3.1.1
定义的变量名 |
地址 |
备注 |
NUM1_EXPONENT |
030H |
浮点数1的指数位 |
NUM1_MANTISSA1 |
031H |
浮点数1的尾数位 |
NUM1_MANTISSA2 |
032H |
|
NUM1_MANTISSA3 |
033H |
|
NUM2_EXPONENT |
034H |
浮点数2的指数位 |
NUM2_MANTISSA1 |
035H |
浮点数2的尾数位 |
NUM2_MANTISSA2 |
036H |
|
NUM2_MANTISSA3 |
037H |
|
SUM_EXPONENT |
038H |
结果的指数位 |
SUM_MANTISSA1 |
039H |
结果的尾数位 |
SUM_MANTISSA2 |
03AH |
|
SUM_MANTISSA3 |
03BH |
|
NUM1_DECIMAL_L |
03CH |
运算数1小数部分 |
NUM1_DECIMAL_H |
03DH |
|
NUM2_DECIMAL_L |
03EH |
运算数2小数部分 |
NUM2_DECIMAL_H |
03FH |
表3.1.2为用于使矩阵键盘和数码管正常工作所定义的变量。
表3.1.2
定义的变量名 |
地址 |
备注 |
DELAY1 |
041H |
用于延时函数的循环迭代 |
DELAY2 |
042H |
|
DELAY3 |
043H |
|
T1_NUM |
044H |
用于扩展定时器1的定时时间 |
LED_NUM |
045H |
用于控制数码管每一次显示时打开该位片选的时间 |
LED_CS |
046H |
用于记录数码管每一次显示时需打开的片选 |
TWINKLE |
047H |
用于记录数码管目前闪烁的位置 |
KEY_X |
048H |
用于记录当前按键的行信息 |
KEY_Y |
049H |
用于记录当前按键的列信息 |
KEY_XY |
04AH |
用于记录当前按键的位置,由行信息与列信息按位相与而成 |
表3.1.3为用于记录按键所输入的数及运算数1和运算数2所定义的变量。
表3.1.3
定义的变量名 |
地址 |
备注 |
DECIADD |
04EH |
用于记录小数点在数码管上的地址 |
OPERADD |
04FH |
用于记录运算符在数码管上的地址 |
KEYADD |
050H |
用于记录当前需显示的键值在数码管上的地址 |
KEYNUM1 |
051H |
数码管上的第一个数 |
KEYNUM2 |
052H |
数码管上的第二个数 |
KEYNUM3 |
053H |
数码管上的第三个数 |
KEYNUM4 |
054H |
数码管上的第四个数 |
KEYNUM5 |
055H |
数码管上的第五个数 |
KEYNUM6 |
056H |
数码管上的第六个数 |
KEYNUM7 |
057H |
数码管上的第七个数 |
KEYNUM8 |
058H |
数码管上的第八个数 |
NUM1_LOW |
059H |
运算数1 |
NUM1_HIGH |
05AH |
|
NUM2_LOW |
05BH |
运算数2 |
NUM2_HIGH |
05CH |
表3.1.4为用于双字节移位乘法和双字节移位除法所定义的变量。
表3.1.4
定义的变量名 |
地址 |
备注 |
MULTI1_LOW |
060H |
乘数1 |
MULTI1_HIGH |
061H |
|
MULTI2_LOW |
062H |
乘数2 |
MULTI2_HIGH |
063H |
|
ADDEND_LOW |
064H |
加数 |
ADDEND_HIGH |
065H |
|
PRODUCT_LOW |
066H |
积 |
PRODUCT_HIGH |
067H |
|
DIVIDEND_LOW |
068H |
被除数 |
DIVIDEND_HIGH |
069H |
|
DIVISOR_LOW |
06AH |
除数 |
DIVISOR_HIGH |
06BH |
|
QUOTIENT_LOW |
06CH |
商 |
QUOTIENT_HIGH |
06DH |
|
REMAINDER_LOW |
06EH |
余数 |
REMAINDER_HIGH |
06FH |
表3.1.5最主要为用于将十进制输入转化为二进制数据和将二进制数据转化为十进制输出所定义的变量。
表3.1.5
定义的变量名 |
地址 |
备注 |
POSITION_DEC |
070H |
用于记录十进制数每一位数所在的位置,方便加权求和用 |
POSITION_BIN |
071H |
用于记录二进制数每一位数所在的位置,方便加权求和用 |
LEN_RESULT |
072H |
用于记录输出结果的长度 |
LEN_NUM |
073H |
用于记录被除数左移的次数 |
POPDATA |
074H |
用于暂存出栈数据 |
OPERATOR_MOMENT |
075H |
用于记录临时的运算符,最主要用于改变运算符的显示 |
OPERATOR |
076H |
用于记录最终确定的运算符 |
KEYNUM_LAST |
077H |
用于记录上次显示的字符 |
FLAG_NEGATIVE |
078H |
用于决定输出结果是否需要输出负号 |
FLAG_FLOAT |
079H |
用于决定运算方式是否采用浮点运算 |
LEN1_DECIMAL |
07AH |
用于记录运算数1小数部分的长度,决定了下面比较值的大小 |
LEN2_DECIMAL |
07BH |
用于记录运算数2小数部分的长度,决定了下面比较值的大小 |
NUM1_DECI_COMP |
07CH |
用于记录运算数1转浮点型时小数部分需要比较的值 |
NUM2_DECI_COMP |
07DH |
用于记录运算数2转浮点型时小数部分需要比较的值 |
3.2 中断程序
本次程序共使用了两个中断源,一是定时器0,二是定时器1,其中定时器0用于每隔5ms动态显示一次数码管,定时器1用于每隔1s闪烁一次数码管的某一位。
3.2.1 定时器0中断
当定时器0产生中断时,第一步工作是将所用到的A累加器及工作寄存器中所用到的值放于堆栈中并对定时器0赋初值,其后调用数码管显示函数,流程图如图3.2.1所示,通过在一个极短的间隔内依次选通一个数码管并显示对应的值,从而产生视觉暂留现象,使我们在同一时间内能看到八个数码管所显示的不同的值。最后在完成函数的调用后将堆栈中的内容弹出,并返回主函数。
图3.2.1 数码管显示函数流程图
3.2.2 定时器1中断
当定时器1产生中断时,同样压栈、赋初值,并在第10次进中断时,用"按位与"和"按位或"的方法取反闪烁位,最后出栈,返回主函数。
3.3 主函数
程序在一开始会进行一些初始化的设置,其中包括设置堆栈指针,以及定义定时器工作方式,打开中断和定时器,在完成这些工作后,程序即会进入主函数,如图3.3所示,在程序进入主函数后,会一直循环判断是否有键按下,且按下的键值为多少,该进行何种操作及运算。
图3.3 主函数流程图
3.3.1 矩阵键盘的读取
在经过20ms的延时去抖函数后,若仍有按键被按下,则程序会调用并执行该函数,该函数的流程图如图3.3.1所示,函数会通过行输出,列输入的方法读取矩阵键盘的列信息,再通过列输入,行输出的方法读取矩阵键盘的行信息,再通过"按位与"的方法,将两者组合为按键位置的信息,当使用者松手后,则立刻执行查表程序并得知该按键所需显示的数值后,即可返回主函数并执行下一步的功能。
图3.3.1 矩阵键盘的读取函数流程图
3.3.2 存储运算数
当判断到有运算符或等于号的输入时,则意味着运算数1或运算数2已经输入完成,则程序会调用并执行该函数,如图3.3.2所示,程序会先清零运算数1或运算数2,并通过地址指针的方式,依次向前取数再乘以相应的10的指数并与其相加,从而得到所输入的运算数1或运算数2的真实值。
其中,若运算数为负数,则将储存其补数;若运算数为小数,则将其分为整数部分和小数部分两部分,分别储存。
图3.3.2 存储运算数函数流程图
3.3.3 显示结果
当运算操作完成后,程序会将所得结果送入运算数1中,并调用和执行该函数。如图3.3.3所示,程序会首先判断运算数1的正负,若为负数,则先在数码管的第一位显示负号,并取其补数覆盖原有的运算数1,后与正数的操作相同。
正数的操作为:将运算数1除以10,令商覆盖原有的运算数1并求其余数,并使用PUSH指令,使其余数放于堆栈当中,然后依次循环此操作,直到运算数1除以10的结果为0,则跳出循环,将刚才放入堆栈中的数依次取出给到数码管的当前位进行显示,直至堆栈中的数完全取出。
最后判断小数标志位是否为1,若为1,则清零标志位,显示小数点,并将小数部分的结果给到运算数1,后重复上述步骤,用于显示小数部分的结果。
图3.3.3 显示结果函数流程图
3.3.4 双字节移位乘法运算
由于此次的任务需要进行0~9999的运算,所以编程中需要用双字节来扩充运算数的存储,因而无法使用已给的单字节乘法运算的指令,因此需要根据乘法计算的原理,自行编写双字节移位乘法运算的函数。如图3.3.4所示,双字节移位乘法的步骤如下:首先清零积和计数n(其中计数n用于记录运算数2右移的次数,当运算数2右移向外溢出16次时,则意味着该函数运算完成),然后右移运算数2,使其最低位溢出给C,并自增n,再判断C的值,若C为1,则意味着运算数1需左移n次,并把结果与积相加;若为0,则不进行任何操作,如是循环16次,即可得到最后的积。
图3.3.4 双字节移位乘法函数流程图
3.3.5 双字节移位除法运算
由于此次的任务需要进行0~9999的运算,所以编程中需要用双字节来扩充运算数的存储,因而无法使用已给的单字节除法运算的指令,因此需要根据除法计算的原理,自行编写双字节移位除法运算的函数。如图3.3.5所示,双字节移位乘法的步骤如下:首先清零被除数,然后左移运算数1,使其溢出一位给到被除数,并判断此时的被除数大于或等于除数吗,若大于或等于,则先将被除数减去除数,并置位C且左移商使其放于商的最低位中;否则,清零C并左移商使其放于商的最低位中。如是循环16次,并把此时的被除数的结果给到余数,即可得到运算数1除以运算数2的商和余数。
图3.3.5 双字节移位除法函数流程图
3.3.6 负数乘除法运算
在计算机的存储中,负数是通过取其补数的方法来存储的,而在实际的运算中,补数的加减也确实满足实际的结果,但是在乘除的运算中,却只有正数乘以负数是满足的,其他情况下都不满足实际的结果,因此在乘除的运算当中,需将负数转化为正数来进行运算,再通过运算数负号的个数来判断最后的结果为负还是为正,流程图如图3.3.6所示。
图3.3.6 负数乘除法流程图
3.2.7 浮点型加法运算
浮点型的加法运算是本次任务的重点工作。此工作共包含三部分:
(1)将所输入的小数转化为浮点型的存储格式存储起来;
(2)将所输入的两个浮点型小数通过浮点型相加的函数相加;
(3)将所得到的结果转换为10进制的方式输出于数码管。
(1)转换为浮点型存储格式
首先介绍的是第一步,即把所输入的小数转化为浮点型的存储格式存储起来。如图3.2.7.1所示,首先将运算数的整数部分放入浮点型存储格式中的尾数位的后两个字节当中,其后将浮点型存储格式中的指数部分置为151,其原因是,整数部分在尾数位的左边时所对应的指数部分应该是127,而将其放于尾数位的后两个字节中,也就相当于将整数部分向右移动了24位,因此127+24=151,此时的指数部分为151。
然后左移小数部分的值并判断这个值是否大于所比较的值(关于所比较的值,以下做个简单说明:若小数位中的值为一位数,即6,则意味着此时的小数为0.6,则所比较的值应为10;若小数位中的值为两位数,即66,则意味着此时的小数为0.66,则所比较的值为100,若小数位中的值为三位数时,以此类推,所比较的值应为1000),若大于或等于则小数部分的值减去所比较的值,并置位C且同时左移尾数放于尾数的最低位中,指数位减1;若小于,则直接清零C且同时左移尾数放于尾数的最低位中,指数位减1。重复以上操作,直到尾数位左移产生的溢出位为1,则按照浮点型存储的格式,此时还应将整个四字节的浮点型存储数整体向右移一位。
图3.2.7.1 转换为浮点型存储格式流程图
(2)浮点型相加函数
其次介绍的是第二步,即把所输入的两个浮点型小数通过浮点型相加的函数将其相加。如图3.2.7.2所示,首先应将指数位与尾数位通过左移和"按位或"运算的方法分离开来,由于这个步骤不是重点,因此以下流程图将其省略,其次取两者中指数位较大的一方为结果的指数位,则指数位较小的一方,需通过右移尾数的方法使其指数位的值增大直至与另一方的指数位相等,则令两数的尾数相加,最后判断相加的尾数位是否存在进位现象,若存在的话,则尾数位右移一位,指数位加一,若不存在的话则完成浮点型的加法运算。
图3.2.7.2 浮点型相加函数流程图
(3)转换为十进制方式输出
最后介绍的是第三步,即把浮点型运算的结果转换为十进制的方式输出于数码管。如图3.2.7.3所示,首先通过不断左移尾数位取出整数部分,若指数部分原本便小于127,则右移尾数位为之后小数部分的输出做好准备。取出整数部分后则可调用显示结果函数将其显示了,其后再加上小数点并取出小数部分,在此规定小数部分最多只显示三位,即加数为取整,其中n为尾数位左移的次数,最后再将小数部分显示出来,即可完成浮点型加法运算。
图3.2.7.3 转换为十进制方式输出流程图
4. 仿真结果
4.1 加法运算仿真结果
图4.1.1 加数1
图4.1.2 加数2
图4.1.3 加法运算仿真结果
4.2 减法运算仿真结果
图4.2.1 被减数
图4.2.2 减数
图4.2.3 减法运算仿真结果
4.3 乘法运算仿真结果
图4.3.1 乘数1
图4.3.2 乘数2
图4.3.3 乘法运算仿真结果
4.4 除法运算仿真结果
图4.4.1 被除数
图4.4.2 除数
图4.4.3 除法运算仿真结果
4.5 负数乘法仿真结果
图4.5.1 乘数1
图4.5.2 乘数2
图4.5.3 负数乘法仿真结果
4.6 负数除法仿真结果
图4.6.1 被除数
图4.6.2 除数
图4.6.3 负数除法仿真结果
4.7 浮点加法仿真结果
图4.7.1 小数1
图4.7.2 小数2
图4.7.3 浮点加法仿真结果
附录
源程序代码
1 KEY EQU P1 2 LED EQU P3 3 LUMINANCE EQU 50 4 ON_OFF EQU 008H 5 NUM1ADD EQU 051H 6 NUM8ADD EQU 058H 7 8 NUM1_EXPONENT DATA 030H;浮点运算数1 9 NUM1_MANTISSA1 DATA 031H; 10 NUM1_MANTISSA2 DATA 032H; 11 NUM1_MANTISSA3 DATA 033H; 12 NUM2_EXPONENT DATA 034H;浮点运算数2 13 NUM2_MANTISSA1 DATA 035H; 14 NUM2_MANTISSA2 DATA 036H; 15 NUM2_MANTISSA3 DATA 037H; 16 SUM_EXPONENT DATA 038H;浮点和 17 SUM_MANTISSA1 DATA 039H; 18 SUM_MANTISSA2 DATA 03AH; 19 SUM_MANTISSA3 DATA 03BH; 20 NUM1_DECIMAL_L DATA 03CH;运算数1小数部分 21 NUM1_DECIMAL_H DATA 03DH; 22 NUM2_DECIMAL_L DATA 03EH;运算数2小数部分 23 NUM2_DECIMAL_H DATA 03FH; 24 25 DELAY1 DATA 041H; 26 DELAY2 DATA 042H; 27 DELAY3 DATA 043H;延时时间 28 T1_NUM DATA 044H;定时时间 29 LED_NUM DATA 045H;LED亮度 30 LED_CS DATA 046H;LED片选 31 TWINKLE DATA 047H;闪烁位置 32 KEY_X DATA 048H;键盘行信息 33 KEY_Y DATA 049H;键盘列信息 34 KEY_XY DATA 04AH;按键位置 35 36 DECIADD DATA 04EH;小数点地址 37 OPERADD DATA 04FH;运算符地址 38 KEYADD DATA 050H;当前键值地址 39 KEYNUM1 DATA 051H;第1次键值 40 KEYNUM2 DATA 052H;第2次键值 41 KEYNUM3 DATA 053H;第3次键值 42 KEYNUM4 DATA 054H;第4次键值 43 KEYNUM5 DATA 055H;第5次键值 44 KEYNUM6 DATA 056H;第6次键值 45 KEYNUM7 DATA 057H;第7次键值 46 KEYNUM8 DATA 058H;第8次键值 47 NUM1_LOW DATA 059H;运算数1低八位 48 NUM1_HIGH DATA 05AH;运算数1高八位 49 NUM2_LOW DATA 05BH;运算数2低八位 50 NUM2_HIGH DATA 05CH;运算数2高八位 51 52 MULTI1_LOW DATA 060H;乘数1的低八位 53 MULTI1_HIGH DATA 061H;乘数1的高八位 54 MULTI2_LOW DATA 062H;乘数2的低八位 55 MULTI2_HIGH DATA 063H;乘数2的高八位 56 ADDEND_LOW DATA 064H;加数的低八位 57 ADDEND_HIGH DATA 065H;加数的高八位 58 PRODUCT_LOW DATA 066H;积的低八位 59 PRODUCT_HIGH DATA 067H;积的高八位 60 DIVIDEND_LOW DATA 068H;被除数的低八位 61 DIVIDEND_HIGH DATA 069H;被除数的高八位 62 DIVISOR_LOW DATA 06AH;除数的低八位 63 DIVISOR_HIGH DATA 06BH;除数的高八位 64 QUOTIENT_LOW DATA 06CH;商的低八位 65 QUOTIENT_HIGH DATA 06DH;商的高八位 66 REMAINDER_LOW DATA 06EH;余数的低八位 67 REMAINDER_HIGH DATA 06FH;余数的高八位 68 69 POSITION_DEC DATA 070H;位置(十进制) 70 POSITION_BIN DATA 071H;位置(二进制) 71 LEN_RESULT DATA 072H;结果长度 72 LEN_NUM DATA 073H;运算数长度 73 POPDATA DATA 074H;出栈数据 74 OPERATOR_MOMENT DATA 075H;临时运算符 75 OPERATOR DATA 076H;运算符 76 KEYNUM_LAST DATA 077H;上一次键值 77 FLAG_NEGATIVE DATA 078H;负数标志位 78 FLAG_FLOAT DATA 079H;浮点标志位 79 LEN1_DECIMAL DATA 07AH;NUM1小数位长度 80 LEN2_DECIMAL DATA 07BH;NUM2小数位长度 81 NUM1_DECI_COMP DATA 07CH;NUM1小数位的比较数 82 NUM2_DECI_COMP DATA 07DH;NUM2小数位的比较数 83 84 ORG 0000H 85 JMP MAIN 86 ORG 0003H 87 JMP INT_EX0 88 ORG 000BH 89 JMP INT_TIMER0 90 ORG 0013H 91 JMP INT_EX1 92 ORG 001BH 93 JMP INT_TIMER1 94 ORG 0023H 95 JMP INT_UART 96 97 ORG 0030H 98 MAIN: 99 MOV SP,#008H;堆栈指针 100 ACALL CLEAR;所有数据清零 101 MOV LED_NUM,#LUMINANCE;LED亮度 102 103 ;定时器初始化 104 MOV TMOD,#011H;16位工作方式1 105 MOV TH0,#0ECH;数码管动态显示用 106 MOV TL0,#078H;初值为60536 107 MOV TH1,#03CH;数码管闪烁用 108 MOV TL1,#0B0H;初值为15536 109 MOV T1_NUM,#10;定时50*10=500MS 110 SETB EA 111 SETB ET0 112 SETB ET1 113 SETB TR0 114 SETB TR1 115 116 JUDGE_PR: 117 MOV KEY,#0F0H;读高四位 118 MOV A,KEY 119 CJNE A,#0F0H,COMFIRM_PR 120 JMP JUDGE_PR 121 COMFIRM_PR: 122 ACALL DELAY;软件去抖 123 MOV KEY,#00FH;读低四位 124 MOV A,KEY 125 CJNE A,#00FH,OPERATE 126 JMP JUDGE_PR 127 OPERATE: 128 ACALL KEY_READ 129 MOV R0,KEYADD 130 MOV A,@R0 131 ;---左移---; 132 K0A: 133 CJNE A,#00AH,K0B 134 ;恢复历史值 135 MOV R0,KEYADD 136 MOV @R0,KEYNUM_LAST 137 ;调用左移函数 138 ACALL LEFT 139 JMP JUDGE_PR 140 ;---右移---; 141 K0B: 142 CJNE A,#00BH,K0C 143 ;恢复历史值 144 MOV R0,KEYADD 145 MOV @R0,KEYNUM_LAST 146 ;下划线则清零 147 CJNE @R0,#00AH,SKIP_ZERO 148 MOV @R0,#000H 149 SKIP_ZERO: 150 ;调用右移函数 151 ACALL RIGHT 152 JMP JUDGE_PR 153 ;---清零---; 154 K0C: 155 CJNE A,#00CH,K0D 156 ACALL CLEAR 157 MOV OPERATOR,#000H;无任何运算符 158 MOV OPERATOR_MOMENT,#000H;无任何运算符 159 JMP JUDGE_PR 160 ;---浮点---; 161 K0D: 162 CJNE A,#00DH,K0E 163 ACALL POINT 164 JMP JUDGE_PR 165 ;---等于---; 166 K0E: 167 CJNE A,#00EH,K0F 168 ACALL EQUAL 169 JMP JUDGE_PR 170 ;---运算符---; 171 K0F: 172 CJNE A,#00FH,K10 173 ACALL SAVENUM1 174 175 INC OPERATOR_MOMENT 176 MOV A,OPERATOR_MOMENT 177 CJNE A,#005H,K0F_NEXT;超过4则为1 178 MOV OPERATOR_MOMENT,#001H 179 ;改变显示内容 180 K0F_NEXT: 181 MOV A,OPERATOR_MOMENT 182 MOV R0,KEYADD 183 ADD A,@R0 184 MOV @R0,A 185 K0F_END: 186 JMP JUDGE_PR 187 ;---错误---; 188 K10: 189 CJNE A,#010H,OPERATE_END 190 ACALL FAULT 191 ;---结束---; 192 OPERATE_END: 193 MOV A,KEYADD;超过NUM8则将停在该位 194 CJNE A,#NUM8ADD,PREPARE_NEXT 195 JMP JMP_LOOP 196 PREPARE_NEXT: 197 ;片选右移 198 MOV A,LED_CS 199 CLR C 200 RRC A 201 MOV LED_CS,A 202 ;闪烁右移 203 MOV A,TWINKLE 204 CLR C 205 RRC A 206 MOV TWINKLE,A 207 ;地址加一 208 INC KEYADD 209 ;下一位显示下划线 210 MOV R0,KEYADD 211 MOV @R0,#00AH;显示下划线 212 JMP_LOOP: 213 JMP JUDGE_PR 214 215 ;--------左移功能--------; 216 LEFT: 217 MOV A,KEYADD;小于NUM1则无法左移 218 CJNE A,#NUM1ADD,STATR_LEFT 219 JMP LEFT_END 220 STATR_LEFT: 221 ;片选左移 222 MOV A,LED_CS 223 SETB C 224 RLC A 225 MOV LED_CS,A 226 ;闪烁左移 227 MOV A,TWINKLE 228 CLR C 229 RLC A 230 MOV TWINKLE,A 231 ;地址减一 232 DEC KEYADD 233 ;下一位显示下划线 234 MOV R0,KEYADD 235 MOV @R0,#00AH;显示下划线 236 LEFT_END: 237 RET 238 239 ;--------右移功能--------; 240 RIGHT: 241 MOV A,KEYADD;超过NUM8则为无法右移 242 CJNE A,#NUM8ADD,START_RIGHT 243 JMP RIGHT_CLEAR 244 START_RIGHT: 245 ;片选右移 246 MOV A,LED_CS 247 CLR C 248 RRC A 249 MOV LED_CS,A 250 ;闪烁右移 251 MOV A,TWINKLE 252 CLR C 253 RRC A 254 MOV TWINKLE,A 255 ;地址加一 256 INC KEYADD 257 ;下一位显示下划线 258 MOV R0,KEYADD 259 MOV @R0,#00AH;显示下划线 260 MOV A,OPERADD 261 CJNE A,#051H,RIGHT_CLEAR 262 JMP RIGHT_END 263 RIGHT_CLEAR: 264 MOV OPERATOR,OPERATOR_MOMENT 265 ACALL CLEAR;所有数据清零 266 RIGHT_END: 267 MOV OPERATOR_MOMENT,#000H 268 RET 269 270 ;--------所有数据清零--------; 271 CLEAR: 272 MOV KEYNUM1,#00AH;显示下划线 273 ;MOV KEYNUM2,#000H;数据清零 274 ;MOV KEYNUM3,#000H;数据清零 275 ;MOV KEYNUM4,#000H;数据清零 276 ;MOV KEYNUM5,#000H;数据清零 277 ;MOV KEYNUM6,#000H;数据清零 278 ;MOV KEYNUM7,#000H;数据清零 279 ;MOV KEYNUM8,#000H;数据清零 280 ;MOV NUM1_LOW,#000H;运算数1清零 281 ;MOV NUM2_LOW,#000H;运算数2清零 282 ;MOV OPERATOR,#000H;无任何运算符 283 MOV KEYADD,#NUM1ADD;当前键值地址为第1个 284 MOV LED_CS,#07FH;显示第一位 285 MOV TWINKLE,#080H;第一位闪烁 286 287 RET 288 289 ;--------浮点运算--------; 290 POINT: 291 DEC KEYADD 292 MOV R0,KEYADD 293 MOV A,@R0 294 ADD A,#020H 295 MOV @R0,A 296 ;地址加一 297 INC KEYADD 298 ;下一位显示下划线 299 MOV R0,KEYADD 300 MOV @R0,#00AH;显示下划线 301 RET 302 303 ;--------存储运算数1--------; 304 SAVENUM1: 305 ;求运算数1初始化 306 INIT_NUM1: 307 MOV R0,KEYADD;当前键值地址 308 MOV OPERADD,KEYADD;运算符地址 309 MOV POSITION_DEC,#000H;位置(个十百) 310 MOV NUM1_LOW,#000H;运算数1低八位 311 MOV NUM1_HIGH,#000H;运算数1高八位 312 MOV FLAG_FLOAT,#000H;清零浮点标志位 313 ;判断是否为第一个数 314 JUDGE_FIRST: 315 CJNE R0,#NUM1ADD,RESULT_NUM1 316 JMP SAVENUM1_END 317 ;求运算数1结果 318 RESULT_NUM1: 319 DEC R0 320 ;判断浮点 321 NUM1_FLOAT: 322 MOV A,@R0 323 CJNE A,#01FH,NUM1F_NEQ 324 NUM1F_EQ: 325 ;等于则直接跳过 326 JMP NUM1_NEGATIVE 327 NUM1F_NEQ: 328 ;小于则直接跳过 329 JC NUM1_NEGATIVE 330 ;储存小数点的位置 331 MOV DECIADD,R0 332 ;NUM1中储存了小数位 333 MOV NUM1_DECIMAL_L,NUM1_LOW 334 MOV NUM1_DECIMAL_H,NUM1_HIGH 335 MOV LEN1_DECIMAL,POSITION_DEC 336 ;让NUM1储存整数位 337 MOV POSITION_DEC,#000H;位置(个十百) 338 MOV NUM1_LOW,#000H;运算数1低八位 339 MOV NUM1_HIGH,#000H;运算数1高八位 340 ;个位数正常化 341 MOV A,@R0 342 CLR C 343 SUBB A,#020H 344 MOV @R0,A 345 ;浮点标志位置一 346 MOV FLAG_FLOAT,#001H 347 JMP NUM1_POSITIVE 348 ;判断负号 349 NUM1_NEGATIVE: 350 MOV A,@R0 351 CJNE A,#011H,NUM1_POSITIVE 352 JMP NUM1_TRANSFORM 353 ;正数操作 354 NUM1_POSITIVE: 355 INC POSITION_DEC 356 MOV MULTI1_LOW,@R0 357 MOV MULTI1_HIGH,#0 358 MOV MULTI2_LOW,#10 359 MOV MULTI2_HIGH,#0 360 MOV R3,POSITION_DEC 361 ;R2为1直接相加,不用相乘 362 DJNZ R3,ACTUAL_VALUE1 363 MOV PRODUCT_LOW,MULTI1_LOW 364 MOV PRODUCT_HIGH,MULTI1_HIGH 365 JMP WEIGHTED_SUM1 366 ;该位实际代表值 367 ACTUAL_VALUE1: 368 ACALL MULTIPLY 369 MOV MULTI1_LOW,PRODUCT_LOW 370 MOV MULTI1_HIGH,PRODUCT_HIGH 371 MOV MULTI2_LOW,#10 372 MOV MULTI2_HIGH,#0 373 DJNZ R3,ACTUAL_VALUE1 374 WEIGHTED_SUM1: 375 ;低位加权求和 376 MOV A,NUM1_LOW 377 ADD A,PRODUCT_LOW 378 MOV NUM1_LOW,A 379 ;高位加权求和 380 MOV A,NUM1_HIGH 381 ADDC A,PRODUCT_HIGH 382 MOV NUM1_HIGH,A 383 CJNE R0,#NUM1ADD,RESULT_NUM1 384 JMP SAVENUM1_END 385 NUM1_TRANSFORM: 386 ;NUM1取反 387 MOV A,NUM1_LOW 388 CPL A 389 MOV NUM1_LOW,A 390 MOV A,NUM1_HIGH 391 CPL A 392 MOV NUM1_HIGH,A 393 ;NUM1加一 394 MOV A,NUM1_LOW 395 ADD A,#1 396 MOV NUM1_LOW,A 397 MOV A,NUM1_HIGH 398 ADDC A,#0 399 MOV NUM1_HIGH,A 400 SAVENUM1_END: 401 ;恢复小数点 402 MOV R0,DECIADD 403 MOV A,@R0 404 ADD A,#020H 405 MOV @R0,A 406 RET 407 408 ;--------显示结果--------; 409 EQUAL: 410 ;调试用 411 ;MOV FLAG_FLOAT,#01H;小数标志位置一 412 ;MOV OPERATOR,#01H;运算符为加法 413 ;求运算数2初始化(只用改地址就好了) 414 INIT_NUM2: 415 MOV R0,KEYADD;当前键值地址 416 MOV POSITION_DEC,#000H;位置(个十百) 417 MOV NUM2_LOW,#000H;运算数2低八位 418 MOV NUM2_HIGH,#000H;运算数2高八位 419 INC OPERADD;运算数2最高位地址 420 ;求运算数2结果 421 RESULT_NUM2: 422 DEC R0 423 ;判断浮点 424 NUM2_FLOAT: 425 MOV A,@R0 426 CJNE A,#01FH,NUM2F_NEQ 427 NUM2F_EQ: 428 ;等于则直接跳过 429 JMP NUM2_POSITIVE 430 NUM2F_NEQ: 431 ;小于则直接跳过 432 JC NUM2_POSITIVE 433 ;NUM2中储存了小数位 434 MOV NUM2_DECIMAL_L,NUM2_LOW 435 MOV NUM2_DECIMAL_H,NUM2_HIGH 436 MOV LEN2_DECIMAL,POSITION_DEC 437 ;让NUM2储存整数位 438 MOV POSITION_DEC,#000H;位置(个十百) 439 MOV NUM2_LOW,#000H;运算数1低八位 440 MOV NUM2_HIGH,#000H;运算数1高八位 441 ;个位数正常化 442 MOV A,@R0 443 CLR C 444 SUBB A,#020H 445 MOV @R0,A 446 ;浮点标志位置一 447 MOV FLAG_FLOAT,#001H 448 JMP NUM2_POSITIVE 449 ;判断负号 450 NUM2_NEGATIVE: 451 MOV A,@R0 452 CJNE A,#011H,NUM2_POSITIVE 453 JMP NUM2_TRANSFORM 454 ;正常操作 455 NUM2_POSITIVE: 456 INC POSITION_DEC 457 MOV MULTI1_LOW,@R0 458 MOV MULTI1_HIGH,#0 459 MOV MULTI2_LOW,#10 460 MOV MULTI2_HIGH,#0 461 MOV R3,POSITION_DEC 462 ;R2为1直接相加,不用相乘 463 DJNZ R3,ACTUAL_VALUE2 464 MOV PRODUCT_LOW,MULTI1_LOW 465 MOV PRODUCT_HIGH,MULTI1_HIGH 466 JMP WEIGHTED_SUM2 467 ;该位实际代表值 468 ACTUAL_VALUE2: 469 ACALL MULTIPLY 470 MOV MULTI1_LOW,PRODUCT_LOW 471 MOV MULTI1_HIGH,PRODUCT_HIGH 472 MOV MULTI2_LOW,#10 473 MOV MULTI2_HIGH,#0 474 DJNZ R3,ACTUAL_VALUE2 475 WEIGHTED_SUM2: 476 ;低位加权求和 477 MOV A,NUM2_LOW 478 ADD A,PRODUCT_LOW 479 MOV NUM2_LOW,A 480 ;高位加权求和 481 MOV A,NUM2_HIGH 482 ADDC A,PRODUCT_HIGH 483 MOV NUM2_HIGH,A 484 MOV A,R0 485 CJNE A,#NUM1ADD,RESULT_NUM2 486 JMP OPERATOR_0 487 NUM2_TRANSFORM: 488 ;NUM1取反 489 MOV A,NUM2_LOW 490 CPL A 491 MOV NUM2_LOW,A 492 MOV A,NUM2_HIGH 493 CPL A 494 MOV NUM2_HIGH,A 495 ;NUM1加一 496 MOV A,NUM2_LOW 497 ADD A,#1 498 MOV NUM2_LOW,A 499 MOV A,NUM2_HIGH 500 ADDC A,#0 501 MOV NUM2_HIGH,A 502 503 ;运算操作 504 OPERATOR_0: 505 MOV A,OPERATOR 506 OPERATOR_1: 507 CJNE A,#001H,OPERATOR_2 508 ACALL PLUS 509 OPERATOR_2: 510 CJNE A,#002H,OPERATOR_3 511 ACALL SUBTRACT 512 OPERATOR_3: 513 CJNE A,#003H,OPERATOR_4 514 MOV MULTI1_LOW,NUM1_LOW 515 MOV MULTI1_HIGH,NUM1_HIGH 516 MOV MULTI2_LOW,NUM2_LOW 517 MOV MULTI2_HIGH,NUM2_HIGH 518 ACALL MULTIPLY 519 MOV NUM1_LOW,PRODUCT_LOW 520 MOV NUM1_HIGH,PRODUCT_HIGH 521 OPERATOR_4: 522 CJNE A,#004H,CLEAR_DIS 523 MOV DIVISOR_LOW,NUM2_LOW 524 MOV DIVISOR_HIGH,NUM2_HIGH 525 ACALL DIVIDE 526 527 ;清零显示屏 528 CLEAR_DIS: 529 ACALL CLEAR;所有数据清零 530 MOV OPERATOR,#000H;无任何运算符 531 MOV OPERATOR_MOMENT,#000H;无任何运算符 532 ;判断负数 533 CONSULT_NEGATIVE: 534 MOV FLAG_NEGATIVE,#0 535 MOV A,NUM1_HIGH 536 RLC A 537 JNC DEC_OUTPUT 538 MOV FLAG_NEGATIVE,#1 539 ;NUM1取反 540 MOV A,NUM1_LOW 541 CPL A 542 MOV NUM1_LOW,A 543 MOV A,NUM1_HIGH 544 CPL A 545 MOV NUM1_HIGH,A 546 ;NUM1加一 547 MOV A,NUM1_LOW 548 ADD A,#1 549 MOV NUM1_LOW,A 550 MOV A,NUM1_HIGH 551 ADDC A,#0 552 MOV NUM1_HIGH,A 553 554 555 DEC_OUTPUT: 556 MOV KEYADD,#NUM1ADD;当前键值地址为第1个 557 ;转换为十进制输出 558 CONVERSION_DEC: 559 ;MOV NUM1_LOW,#1 560 ;MOV NUM1_HIGH,#0 561 MOV LEN_RESULT,#000H 562 ;求余压栈 563 REMAINDER: 564 MOV DIVISOR_LOW,#10 565 MOV DIVISOR_HIGH,#0 566 ACALL DIVIDE 567 PUSH REMAINDER_LOW 568 INC LEN_RESULT 569 MOV A,NUM1_HIGH 570 JNZ REMAINDER 571 MOV A,NUM1_LOW 572 JNZ REMAINDER 573 574 ;出栈显示 575 OUT_RESULT: 576 MOV A,FLAG_NEGATIVE 577 JZ OUT_LOOP 578 INC LEN_RESULT;显示长度加1 579 MOV R0,KEYADD 580 MOV @R0,#17;显示负号 581 JMP OUT_NEXT 582 OUT_LOOP: 583 MOV R0,KEYADD 584 POP POPDATA 585 MOV @R0,POPDATA 586 OUT_NEXT: 587 INC KEYADD 588 ;增加片选位 589 MOV A,LED_CS 590 CLR C 591 RRC A 592 MOV LED_CS,A 593 ;右移闪烁位 594 MOV A,TWINKLE 595 CLR C 596 RR A 597 MOV TWINKLE,A 598 DJNZ LEN_RESULT,OUT_LOOP 599 600 ;判断小数标志位,是否需要显示小数 601 MOV A,FLAG_FLOAT 602 CJNE A,#001H,EQUAL_END1 603 JMP DIS_DECIMAL 604 EQUAL_END1: 605 LJMP EQUAL_END 606 DIS_DECIMAL: 607 ;添加小数点 608 DEC KEYADD 609 MOV R0,KEYADD 610 MOV A,@R0 611 ADD A,#020H 612 MOV @R0,A 613 INC KEYADD 614 ;求小数部分的显示值 615 MOV NUM1_LOW,#000H;运算数2低八位 616 MOV NUM1_HIGH,#000H;运算数2高八位 617 ;左移尾数 618 CLR C 619 MOV A,SUM_MANTISSA1 620 RLC A 621 MOV SUM_MANTISSA1,A 622 JNC DECI_DIS2 623 MOV NUM1_LOW,#244 624 MOV NUM1_HIGH,#1 625 DECI_DIS2: 626 ;左移尾数 627 CLR C 628 MOV A,SUM_MANTISSA1 629 RLC A 630 MOV SUM_MANTISSA1,A 631 JNC DECI_DIS3 632 MOV A,NUM1_LOW 633 ADD A,#250 634 MOV NUM1_LOW,A 635 MOV A,NUM1_HIGH 636 ADDC A,#0 637 MOV NUM1_HIGH,A 638 DECI_DIS3: 639 ;左移尾数 640 CLR C 641 MOV A,SUM_MANTISSA1 642 RLC A 643 MOV SUM_MANTISSA1,A 644 JNC DECI_DIS4 645 MOV A,NUM1_LOW 646 ADD A,#125 647 MOV NUM1_LOW,A 648 MOV A,NUM1_HIGH 649 ADDC A,#0 650 MOV NUM1_HIGH,A 651 DECI_DIS4: 652 ;左移尾数 653 CLR C 654 MOV A,SUM_MANTISSA1 655 RLC A 656 MOV SUM_MANTISSA1,A 657 JNC DECI_DIS5 658 MOV A,NUM1_LOW 659 ADD A,#63 660 MOV NUM1_LOW,A 661 MOV A,NUM1_HIGH 662 ADDC A,#0 663 MOV NUM1_HIGH,A 664 DECI_DIS5: 665 ;左移尾数 666 CLR C 667 MOV A,SUM_MANTISSA1 668 RLC A 669 MOV SUM_MANTISSA1,A 670 JNC DECI_DIS6 671 MOV A,NUM1_LOW 672 ADD A,#31 673 MOV NUM1_LOW,A 674 MOV A,NUM1_HIGH 675 ADDC A,#0 676 MOV NUM1_HIGH,A 677 DECI_DIS6: 678 ;左移尾数 679 CLR C 680 MOV A,SUM_MANTISSA1 681 RLC A 682 MOV SUM_MANTISSA1,A 683 JNC DECI_DIS7 684 MOV A,NUM1_LOW 685 ADD A,#16 686 MOV NUM1_LOW,A 687 MOV A,NUM1_HIGH 688 ADDC A,#0 689 MOV NUM1_HIGH,A 690 DECI_DIS7: 691 ;左移尾数 692 CLR C 693 MOV A,SUM_MANTISSA1 694 RLC A 695 MOV SUM_MANTISSA1,A 696 JNC DECI_DIS8 697 MOV A,NUM1_LOW 698 ADD A,#8 699 MOV NUM1_LOW,A 700 MOV A,NUM1_HIGH 701 ADDC A,#0 702 MOV NUM1_HIGH,A 703 DECI_DIS8: 704 ;左移尾数 705 CLR C 706 MOV A,SUM_MANTISSA1 707 RLC A 708 MOV SUM_MANTISSA1,A 709 JNC DECI_DIS9 710 MOV A,NUM1_LOW 711 ADD A,#4 712 MOV NUM1_LOW,A 713 MOV A,NUM1_HIGH 714 ADDC A,#0 715 MOV NUM1_HIGH,A 716 DECI_DIS9: 717 ;MOV NUM1_LOW,#50 718 MOV FLAG_FLOAT,#000H;清零小数标志位 719 LJMP CONVERSION_DEC 720 EQUAL_END: 721 MOV R0,KEYADD 722 MOV @R0,#00AH;显示下划线 723 RET 724 725 ;--------双字节加法运算--------; 726 PLUS: 727 ;调试用 728 ;MOV NUM1_LOW,#20 729 ;MOV NUM1_HIGH,#0 730 ;MOV NUM2_LOW,#30 731 ;MOV NUM2_HIGH,#0 732 ;MOV NUM1_DECIMAL_L,#5 733 ;MOV NUM1_DECIMAL_H,#2 734 ;MOV NUM2_DECIMAL_L,#20 735 ;MOV NUM2_DECIMAL_H,#3 736 ;MOV NUM1_LOW,NUM1_DECIMAL_L 737 ;MOV NUM1_HIGH,NUM1_DECIMAL_H 738 ;LJMP PLUS_END 739 740 MOV A,FLAG_FLOAT 741 JNZ PLUS_FLOAT 742 PLUS_NORMAL: 743 MOV A,NUM1_LOW 744 ADD A,NUM2_LOW 745 MOV NUM1_LOW,A 746 MOV A,NUM1_HIGH 747 ADDC A,NUM2_HIGH 748 MOV NUM1_HIGH,A 749 LJMP PLUS_END 750 PLUS_FLOAT: 751 MOV NUM1_EXPONENT,000H;清空浮点数1 752 MOV NUM1_MANTISSA1,000H; 753 MOV NUM1_MANTISSA2,000H; 754 MOV NUM1_MANTISSA3,000H; 755 MOV NUM2_EXPONENT,000H;清空浮点数2 756 MOV NUM2_MANTISSA1,000H; 757 MOV NUM2_MANTISSA2,000H; 758 MOV NUM2_MANTISSA3,000H; 759 MOV SUM_EXPONENT,000H;清空浮点加法结果 760 MOV SUM_MANTISSA1,000H; 761 MOV SUM_MANTISSA2,000H; 762 MOV SUM_MANTISSA3,000H; 763 MOV NUM1_DECI_COMP,001H; 764 MOV NUM2_DECI_COMP,001H; 765 ;NUM1转换为浮点型储存格式 766 NUM1_CONVERSION_FLOAT: 767 MOV NUM1_MANTISSA3,NUM1_LOW 768 MOV NUM1_MANTISSA2,NUM1_HIGH 769 MOV NUM1_EXPONENT,#151;127+24=151 770 771 DECI1_COMP_SOLVE: 772 MOV A,NUM1_DECI_COMP 773 MOV B,#10 774 MUL AB 775 MOV NUM1_DECI_COMP,A 776 DJNZ LEN1_DECIMAL,DECI1_COMP_SOLVE 777 778 ;十进制小数位转二进制 779 DECI1_COMP: 780 CLR C 781 MOV A,NUM1_DECIMAL_L 782 RLC A 783 MOV NUM1_DECIMAL_L,A 784 CJNE A,NUM1_DECI_COMP,DECI1_COMP_NEQ 785 DECI1_COMP_EQ: 786 MOV NUM1_DECIMAL_L,#000H 787 SETB C 788 JMP NUM1_MANTISSA_RLC 789 DECI1_COMP_NEQ: 790 JC DECI1_COMP_LESS 791 CLR C 792 MOV A,NUM1_DECIMAL_L 793 SUBB A,NUM1_DECI_COMP 794 MOV NUM1_DECIMAL_L,A 795 SETB C 796 JMP NUM1_MANTISSA_RLC 797 DECI1_COMP_LESS: 798 CLR C 799 ;尾数位集体左移 800 NUM1_MANTISSA_RLC: 801 MOV A,NUM1_MANTISSA3 802 RLC A 803 MOV NUM1_MANTISSA3,A 804 MOV A,NUM1_MANTISSA2 805 RLC A 806 MOV NUM1_MANTISSA2,A 807 MOV A,NUM1_MANTISSA1 808 RLC A 809 MOV NUM1_MANTISSA1,A 810 ;记录小数指数 811 DEC NUM1_EXPONENT 812 JNC DECI1_COMP 813 ;浮点数集体右移 814 CLR C 815 MOV A,NUM1_EXPONENT 816 RRC A 817 MOV NUM1_EXPONENT,A 818 MOV A,NUM1_MANTISSA1 819 RRC A 820 MOV NUM1_MANTISSA1,A 821 MOV A,NUM1_MANTISSA2 822 RRC A 823 MOV NUM1_MANTISSA2,A 824 MOV A,NUM1_MANTISSA3 825 RRC A 826 MOV NUM1_MANTISSA3,A 827 828 ;NUM2转换为浮点型储存格式 829 NUM2_CONVERSION_FLOAT: 830 MOV NUM2_MANTISSA3,NUM2_LOW 831 MOV NUM2_MANTISSA2,NUM2_HIGH 832 MOV NUM2_EXPONENT,#151;127+24=151 833 834 DECI2_COMP_SOLVE: 835 MOV A,NUM2_DECI_COMP 836 MOV B,#10 837 MUL AB 838 MOV NUM2_DECI_COMP,A 839 DJNZ LEN2_DECIMAL,DECI2_COMP_SOLVE 840 841 ;十进制小数位转二进制 842 DECI2_COMP: 843 CLR C 844 MOV A,NUM2_DECIMAL_L 845 RLC A 846 MOV NUM2_DECIMAL_L,A 847 CJNE A,NUM2_DECI_COMP,DECI2_COMP_NEQ 848 DECI2_COMP_EQ: 849 MOV NUM2_DECIMAL_L,#000H 850 SETB C 851 JMP NUM2_MANTISSA_RLC 852 DECI2_COMP_NEQ: 853 JC DECI2_COMP_LESS 854 CLR C 855 MOV A,NUM2_DECIMAL_L 856 SUBB A,NUM2_DECI_COMP 857 MOV NUM2_DECIMAL_L,A 858 SETB C 859 JMP NUM2_MANTISSA_RLC 860 DECI2_COMP_LESS: 861 CLR C 862 ;尾数位集体左移 863 NUM2_MANTISSA_RLC: 864 MOV A,NUM2_MANTISSA3 865 RLC A 866 MOV NUM2_MANTISSA3,A 867 MOV A,NUM2_MANTISSA2 868 RLC A 869 MOV NUM2_MANTISSA2,A 870 MOV A,NUM2_MANTISSA1 871 RLC A 872 MOV NUM2_MANTISSA1,A 873 ;记录小数指数 874 DEC NUM2_EXPONENT 875 JNC DECI2_COMP 876 ;浮点数集体右移 877 CLR C 878 MOV A,NUM2_EXPONENT 879 RRC A 880 MOV NUM2_EXPONENT,A 881 MOV A,NUM2_MANTISSA1 882 RRC A 883 MOV NUM2_MANTISSA1,A 884 MOV A,NUM2_MANTISSA2 885 RRC A 886 MOV NUM2_MANTISSA2,A 887 MOV A,NUM2_MANTISSA3 888 RRC A 889 MOV NUM2_MANTISSA3,A 890 891 ;至此完成所有转换,可以开始计算 892 PLUS_FLOAT_START: 893 ;恢复NUM1指数位 894 MOV A,NUM1_MANTISSA1 895 RLC A 896 MOV A,NUM1_EXPONENT 897 RLC A 898 MOV NUM1_EXPONENT,A 899 ;恢复NUM1有效数字位 900 MOV A,NUM1_MANTISSA1 901 ORL A,#080H 902 MOV NUM1_MANTISSA1,A 903 ;恢复NUM2指数位 904 MOV A,NUM2_MANTISSA1 905 RLC A 906 MOV A,NUM2_EXPONENT 907 RLC A 908 MOV NUM2_EXPONENT,A 909 ;恢复NUM2有效数字位 910 MOV A,NUM2_MANTISSA1 911 ORL A,#080H 912 MOV NUM2_MANTISSA1,A 913 ;以大的为标准移动小数点 914 FLOAT_COMPARE: 915 MOV A,NUM1_EXPONENT 916 CJNE A,NUM2_EXPONENT,FLOAT_NEQ 917 FLOAT_EQ: 918 JMP FLOAT_ADD 919 FLOAT_NEQ: 920 JC FLOAT_RRNUM1 921 ;NUM1较大 NUM2右移 922 FLOAT_RRNUM2: 923 INC NUM2_EXPONENT 924 CLR C 925 MOV A,NUM2_MANTISSA1 926 RRC A 927 MOV NUM2_MANTISSA1,A 928 MOV A,NUM2_MANTISSA2 929 RRC A 930 MOV NUM2_MANTISSA2,A 931 MOV A,NUM2_MANTISSA3 932 RRC A 933 MOV NUM2_MANTISSA3,A 934 MOV A,NUM1_EXPONENT 935 CJNE A,NUM2_EXPONENT,FLOAT_RRNUM2; 936 LJMP FLOAT_ADD; 937 ;NUM1较小 NUM1右移 938 FLOAT_RRNUM1: 939 INC NUM1_EXPONENT 940 CLR C 941 MOV A,NUM1_MANTISSA1 942 RRC A 943 MOV NUM1_MANTISSA1,A 944 MOV A,NUM1_MANTISSA2 945 RRC A 946 MOV NUM1_MANTISSA2,A 947 MOV A,NUM1_MANTISSA3 948 RRC A 949 MOV NUM1_MANTISSA3,A 950 MOV A,NUM1_EXPONENT 951 CJNE A,NUM2_EXPONENT,FLOAT_RRNUM1 952 LJMP FLOAT_ADD; 953 ;两数相加 954 FLOAT_ADD: 955 MOV A,NUM1_MANTISSA3 956 ADD A,NUM2_MANTISSA3 957 MOV SUM_MANTISSA3,A 958 959 MOV A,NUM1_MANTISSA2 960 ADDC A,NUM2_MANTISSA2 961 MOV SUM_MANTISSA2,A 962 963 MOV A,NUM1_MANTISSA1 964 ADDC A,NUM2_MANTISSA1 965 MOV SUM_MANTISSA1,A 966 967 MOV SUM_EXPONENT,NUM2_EXPONENT 968 JNC FLOAT_RECOVER 969 ;有进位现象 SUM右移 970 FLOAT_RRSUM: 971 INC SUM_EXPONENT 972 SETB C 973 MOV A,SUM_MANTISSA1 974 RRC A 975 MOV SUM_MANTISSA1,A 976 MOV A,SUM_MANTISSA2 977 RRC A 978 MOV SUM_MANTISSA2,A 979 MOV A,SUM_MANTISSA3 980 RRC A 981 MOV SUM_MANTISSA3,A 982 ;恢复原有格式 983 FLOAT_RECOVER: 984 ;;左移丢掉第一位 985 ;MOV A,SUM_MANTISSA1 986 ;RL A 987 ;MOV SUM_MANTISSA1,A 988 ;;指数位和第一个尾数位同时右移 989 ;CLR C 990 ;MOV A,SUM_EXPONENT 991 ;RRC A 992 ;MOV SUM_EXPONENT,A 993 ;MOV A,SUM_MANTISSA1 994 ;RRC A 995 ;MOV SUM_MANTISSA1, A 996 997 ;调试用 998 ;MOV SUM_EXPONENT,#82H;结果SUM高十六位 999 ;MOV SUM_MANTISSA1,#0AAH; 1000 ;MOV SUM_MANTISSA2,#000H;结果SUM低十六位 1001 ;MOV SUM_MANTISSA3,#000H; 1002 1003 ;;恢复SUM指数位 1004 ;MOV A,SUM_MANTISSA1 1005 ;RLC A 1006 ;MOV A,SUM_EXPONENT 1007 ;RLC A 1008 ;MOV SUM_EXPONENT,A 1009 ;;恢复SUM有效数字位 1010 ;MOV A,SUM_MANTISSA1 1011 ;ORL A,#080H 1012 ;MOV SUM_MANTISSA1,A 1013 1014 ;完成运算 1015 MOV NUM1_LOW,#000H; 1016 MOV NUM1_HIGH,#000H; 1017 SEND_NUM1: 1018 MOV A,SUM_EXPONENT 1019 CJNE A,#127,SUM_NEQ 1020 ;MANTISSA左移送入NUM1 完成运算 1021 SUM_EQ: 1022 CLR C 1023 MOV A,SUM_MANTISSA3 1024 RLC A 1025 MOV SUM_MANTISSA3,A 1026 MOV A,SUM_MANTISSA2 1027 RLC A 1028 MOV SUM_MANTISSA2,A 1029 MOV A,SUM_MANTISSA1 1030 RLC A 1031 MOV SUM_MANTISSA1,A 1032 MOV A,NUM1_LOW 1033 RLC A 1034 MOV NUM1_LOW,A 1035 MOV A,NUM1_HIGH 1036 RLC A 1037 MOV NUM1_HIGH,A 1038 JMP PLUS_END 1039 ;SUM_EXPONENT较大 MANTISSA左移送入NUM1 EXPONENT自减 1040 SUM_NEQ: 1041 JC SUM_LESS 1042 CLR C 1043 MOV A,SUM_MANTISSA3 1044 RLC A 1045 MOV SUM_MANTISSA3,A 1046 MOV A,SUM_MANTISSA2 1047 RLC A 1048 MOV SUM_MANTISSA2,A 1049 MOV A,SUM_MANTISSA1 1050 RLC A 1051 MOV SUM_MANTISSA1,A 1052 MOV A,NUM1_LOW 1053 RLC A 1054 MOV NUM1_LOW,A 1055 MOV A,NUM1_HIGH 1056 RLC A 1057 MOV NUM1_HIGH,A 1058 DEC SUM_EXPONENT 1059 JMP SEND_NUM1 1060 ;SUM_EXPONENT较小 MANTISSA右移 EXPONENT自增 1061 SUM_LESS: 1062 CLR C 1063 MOV A,SUM_MANTISSA1 1064 RLC A 1065 MOV SUM_MANTISSA1,A 1066 MOV A,SUM_MANTISSA2 1067 RLC A 1068 MOV SUM_MANTISSA2,A 1069 MOV A,SUM_MANTISSA3 1070 RLC A 1071 MOV SUM_MANTISSA3,A 1072 INC SUM_EXPONENT 1073 JMP SEND_NUM1 1074 PLUS_END: 1075 RET 1076 1077 ;--------双字节减法运算--------; 1078 SUBTRACT: 1079 CLR C 1080 MOV A,NUM1_LOW 1081 SUBB A,NUM2_LOW 1082 MOV NUM1_LOW,A 1083 MOV A,NUM1_HIGH 1084 SUBB A,NUM2_HIGH 1085 MOV NUM1_HIGH,A 1086 RET 1087 1088 ;--------双字节移位乘法运算--------; 1089 MULTIPLY: 1090 MOV ADDEND_LOW,#0 1091 MOV ADDEND_HIGH,#0 1092 MOV PRODUCT_LOW,#0 1093 MOV PRODUCT_HIGH,#0 1094 MOV POSITION_BIN,#0 1095 MULTIPLY_LOOP: 1096 ;右移MULTI2 1097 CLR C 1098 MOV A,MULTI2_HIGH 1099 RRC A 1100 MOV MULTI2_HIGH,A 1101 MOV A,MULTI2_LOW 1102 RRC A 1103 MOV MULTI2_LOW,A 1104 ;记录MULTI2的第几位 1105 INC POSITION_BIN 1106 ;判断是否需要移位相加 1107 JNC MULTIPLY_JUDGE 1108 1109 MOV ADDEND_LOW,MULTI1_LOW 1110 MOV ADDEND_HIGH,MULTI1_HIGH 1111 MOV R2,POSITION_BIN 1112 ;R2为1直接相加,不用移位 1113 DJNZ R2,MULTIPLY_LEFT 1114 JMP MULTIPLY_ADDITION 1115 1116 MULTIPLY_LEFT: 1117 ;左移ADDEND 1118 CLR C 1119 MOV A,ADDEND_LOW 1120 RLC A 1121 MOV ADDEND_LOW,A 1122 1123 MOV A,ADDEND_HIGH 1124 RLC A 1125 MOV ADDEND_HIGH,A 1126 1127 DJNZ R2,MULTIPLY_LEFT 1128 1129 MULTIPLY_ADDITION: 1130 MOV A,PRODUCT_LOW 1131 ADD A,ADDEND_LOW 1132 MOV PRODUCT_LOW,A 1133 1134 MOV A,PRODUCT_HIGH 1135 ADDC A,ADDEND_HIGH 1136 MOV PRODUCT_HIGH,A 1137 ;判断是否移满16位 1138 MULTIPLY_JUDGE: 1139 MOV A,POSITION_BIN 1140 CJNE A,#010H,MULTIPLY_LOOP 1141 1142 RET 1143 1144 ;--------双字节移位除法运算--------; 1145 DIVIDE: 1146 MOV LEN_NUM,#16;双字节长度16 1147 MOV DIVIDEND_LOW,#0 1148 MOV DIVIDEND_HIGH,#0 1149 MOV QUOTIENT_LOW,#0 1150 MOV QUOTIENT_HIGH,#0 1151 DIVIDE_LOOP: 1152 ;左移NUM1 1153 CLR C 1154 MOV A,NUM1_LOW 1155 RLC A 1156 MOV NUM1_LOW,A 1157 1158 MOV A,NUM1_HIGH 1159 RLC A 1160 MOV NUM1_HIGH,A 1161 ;左移DIVIDEND 1162 MOV A,DIVIDEND_LOW 1163 RLC A 1164 MOV DIVIDEND_LOW,A 1165 1166 MOV A,DIVIDEND_HIGH 1167 RLC A 1168 MOV DIVIDEND_HIGH,A 1169 ;比较高八位 1170 MOV A,DIVIDEND_HIGH 1171 CJNE A,DIVISOR_HIGH,DIVIDE_NEQ2 1172 ;相等则判断低八位 1173 DIVIDE_EQ1: 1174 JMP DIVIDE_JUDGE 1175 DIVIDE_NEQ1: 1176 ;小于则直接跳过 1177 JC DIVIDE_LOW 1178 ;大于则直接相减 1179 CLR C 1180 MOV A,DIVIDEND_LOW 1181 SUBB A,DIVISOR_LOW 1182 MOV DIVIDEND_LOW,A 1183 1184 MOV A,DIVIDEND_HIGH 1185 SUBB A,DIVISOR_HIGH 1186 MOV DIVIDEND_HIGH,A 1187 ;左移QUOTIENT 1188 SETB C 1189 MOV A,QUOTIENT_LOW 1190 RLC A 1191 MOV QUOTIENT_LOW,A 1192 1193 MOV A,QUOTIENT_HIGH 1194 RLC A 1195 MOV QUOTIENT_HIGH,A 1196 DJNZ LEN_NUM,DIVIDE_LOOP 1197 JMP DIVIDE_END 1198 ;低八位判断 1199 DIVIDE_JUDGE: 1200 MOV A,DIVIDEND_LOW 1201 CJNE A,DIVISOR_LOW,DIVIDE_NEQ2 1202 DIVIDE_EQ2: 1203 MOV DIVIDEND_LOW,#0 1204 MOV DIVIDEND_HIGH,#0 1205 ;左移QUOTIENT 1206 SETB C 1207 MOV A,QUOTIENT_LOW 1208 RLC A 1209 MOV QUOTIENT_LOW,A 1210 1211 MOV A,QUOTIENT_HIGH 1212 RLC A 1213 MOV QUOTIENT_HIGH,A 1214 DJNZ LEN_NUM,DIVIDE_LOOP 1215 JMP DIVIDE_END 1216 DIVIDE_NEQ2: 1217 ;小于则跳过 1218 JC DIVIDE_LOW 1219 ;大于则相减 1220 MOV DIVIDEND_HIGH,#0 1221 CLR C 1222 SUBB A,DIVISOR_LOW 1223 MOV DIVIDEND_LOW,A 1224 ;左移QUOTIENT 1225 SETB C 1226 MOV A,QUOTIENT_LOW 1227 RLC A 1228 MOV QUOTIENT_LOW,A 1229 1230 MOV A,QUOTIENT_HIGH 1231 RLC A 1232 MOV QUOTIENT_HIGH,A 1233 DJNZ LEN_NUM,DIVIDE_LOOP 1234 JMP DIVIDE_END 1235 ;小于则只需左移QUOTIENT 1236 DIVIDE_LOW: 1237 ;左移QUOTIENT 1238 CLR C 1239 MOV A,QUOTIENT_LOW 1240 RLC A 1241 MOV QUOTIENT_LOW,A 1242 1243 MOV A,QUOTIENT_HIGH 1244 RLC A 1245 MOV QUOTIENT_HIGH,A 1246 DJNZ LEN_NUM,DIVIDE_LOOP 1247 JMP DIVIDE_END 1248 DIVIDE_END: 1249 MOV NUM1_LOW,QUOTIENT_LOW 1250 MOV NUM1_HIGH,QUOTIENT_HIGH 1251 MOV REMAINDER_LOW,DIVIDEND_LOW 1252 MOV REMAINDER_HIGH,DIVIDEND_HIGH 1253 1254 RET 1255 1256 ;--------错误处理--------; 1257 FAULT: 1258 RET 1259 1260 ;--------读取矩阵键盘键值--------; 1261 KEY_READ: 1262 MOV KEY,#0F0H;读高四位 1263 MOV A,KEY 1264 ORL A,#00FH;低四位置1 1265 MOV KEY_Y,A;高四位列信息 1266 MOV KEY,#00FH;读低四位 1267 MOV A,KEY 1268 ORL A,#0F0H;高四位置1 1269 MOV KEY_X,A;低四位行信息 1270 ANL A,KEY_Y 1271 MOV KEY_XY,A 1272 ;松手执行 1273 JUDGE_RELAX: 1274 MOV KEY,#0F0H;读高四位 1275 MOV A,KEY 1276 CJNE A,#0F0H,JUDGE_RELAX 1277 COMFIRM_RELAX: 1278 ACALL DELAY;软件去抖 1279 MOV KEY,#00FH;读低四位 1280 MOV A,KEY 1281 CJNE A,#00FH,JUDGE_RELAX 1282 ;确定KEYNUM 1283 CONFIRM_KEYNUM: 1284 MOV R0,KEYADD 1285 MOV KEYNUM_LAST,@R0 1286 INIT_KEY: 1287 MOV @R0,#0FFH 1288 MOV DPTR,#KEY_TABLE 1289 MOV R2,#21;自增21次,KEYNUM最大20 1290 JUDGE_EXCESS: 1291 INC @R0 1292 DJNZ R2,JUDGE_EQUAL 1293 JMP KEY_END 1294 JUDGE_EQUAL: 1295 MOV A,@R0 1296 MOVC A,@A+DPTR 1297 CJNE A,KEY_XY,JUDGE_EXCESS 1298 KEY_END: 1299 RET 1300 1301 KEY_TABLE: 1302 DB 0D7H;1101 0111B;K14(0) 1303 DB 0EBH;1110 1011B;K9 (1) 1304 DB 0DBH;1101 1011B;K10(2) 1305 DB 0BBH;1011 1011B;K11(3) 1306 DB 0EDH;1110 1101B;K5 (4) 1307 DB 0DDH;1101 1101B;K6 (5) 1308 DB 0BDH;1011 1101B;K7 (6) 1309 DB 0EEH;1110 1110B;K1 (7) 1310 DB 0DEH;1101 1110B;K2 (8) 1311 DB 0BEH;1011 1110B;K3 (9) 1312 DB 0E7H;1110 0111B;K13(<)10 1313 DB 0B7H;1011 0111B;K15(>)11 1314 DB 07EH;0111 1110B;K4 (c)12 1315 DB 07DH;0111 1101B;K8 (.)13 1316 DB 077H;0111 0111B;K16(=)14 1317 DB 07BH;0111 1011B;K12(O)+ - * / 1318 1319 ;--------数码管显示--------; 1320 DISPLAY: 1321 MOV R0,#NUM1ADD 1322 MOV R2,LED_CS 1323 MOV R3,#07FH 1324 DIS_LOOP: 1325 MOV A,R2 1326 RLC A 1327 MOV R2,A 1328 ;段选查表 1329 MOV DPTR,#DIS_TABLE 1330 MOV A,@R0 1331 MOVC A,@A+DPTR 1332 MOV P0,A 1333 INC R0 1334 JC SKIP 1335 ;片选延时 1336 MOV P2,R3 1337 DJNZ LED_NUM,$ 1338 MOV LED_NUM,#LUMINANCE 1339 MOV P2,#0FFH 1340 SKIP: 1341 SETB C 1342 MOV A,R3 1343 RRC A 1344 MOV R3,A 1345 JC DIS_LOOP 1346 RET 1347 1348 DIS_TABLE: 1349 DB 03FH,006H,05BH,04FH;0 1 2 3 1350 DB 066H,06DH,07DH,007H;4 5 6 7 1351 DB 07FH,06FH,008H,008H;8 9 _ _ 1352 DB 000H,000H,000H,000H; 1353 DB 03EH,040H,037H,049H;+ - * / 1354 DB 071H,071H,071H,071H;F F F F 1355 DB 071H,071H,071H,071H;F F F F 1356 DB 071H,071H,071H,071H;F F F F 1357 DB 0BFH,086H,0DBH,0CFH;0. 1. 2. 3. 1358 DB 0E6H,0EDH,0FDH,087H;4. 5. 6. 7. 1359 DB 0FFH,0EFH,000H,000H;8. 9. 1360 1361 ;--------延时函数--------; 1362 DELAY: 1363 MOV DELAY1,#100 1364 MOV DELAY2,#100 1365 MOV DELAY3,#2;延时约2*10=20MS 1366 DELAY_LOOP: 1367 DJNZ DELAY1,DELAY_LOOP 1368 MOV DELAY1,#100 1369 DJNZ DELAY2,DELAY_LOOP 1370 MOV DELAY2,#100 1371 DJNZ DELAY3,DELAY_LOOP 1372 RET 1373 1374 INT_EX0: 1375 1376 ;--------数码管动态显示--------; 1377 INT_TIMER0: 1378 PUSH 00H;R0压栈 1379 PUSH 01H;R1压栈 1380 MOV A,R1;A借用R1的地址 1381 PUSH 01H;A压栈 1382 PUSH 02H;R2压栈 1383 PUSH 03H;R3压栈 1384 MOV TH0,#0ECH; 1385 MOV TL0,#078H;初值为60536 1386 ACALL DISPLAY 1387 POP 03H;R3出栈 1388 POP 02H;R2出栈 1389 POP 01H;A出栈 1390 MOV A,R1;A借用R1的地址 1391 POP 01H;R1出栈 1392 POP 00H;R0出栈 1393 RETI 1394 1395 INT_EX1: 1396 1397 ;--------最后一位闪烁--------; 1398 INT_TIMER1: 1399 PUSH 01H;R1压栈 1400 MOV A,R1;A借用R1的地址 1401 PUSH 01H;A压栈 1402 MOV TH1,#03CH; 1403 MOV TL1,#0B0H;初值为15536 1404 DJNZ T1_NUM,TIMER1_END 1405 MOV T1_NUM,#10;定时50*10=500MS 1406 MOV A,TWINKLE 1407 CPL ON_OFF 1408 JB ON_OFF,LED_ON 1409 LED_OFF: 1410 ORL LED_CS,A;灭灯 1411 JMP TIMER1_END 1412 LED_ON: 1413 CPL A 1414 ANL LED_CS,A;亮灯 1415 TIMER1_END: 1416 POP 01H;A出栈 1417 MOV A,R1;A借用R1的地址 1418 POP 01H;R1出栈 1419 RETI 1420 1421 INT_UART: 1422 1423 END