走马灯实验报告67586Word下载.docx
《走马灯实验报告67586Word下载.docx》由会员分享,可在线阅读,更多相关《走马灯实验报告67586Word下载.docx(12页珍藏版)》请在冰豆网上搜索。
下面结合实际介绍几种ATPCS规则,如果读者想了解更多的规则,可以查看相关的书
籍。
1.基本ATPCS
基本ATPCS规定了在子程序调用时的一些基本规则,包括下面3方面的内容:
(1)各寄存器的使用规则及其相应的名称。
(2)数据栈的使用规则。
(3)参数传递的规则。
相对于其它类型的ATPCS,满足基本ATPCS的程序的执行速度更快,所占用的内存更少。
但是它不能提供以下的支持:
ARM程序和Thumb程序相互调用,数据以及代码的位置无关
的支持,子程序的可重入性,数据栈检查的支持。
而派生的其他几种特定的ATPCS就是在基本ATPCS的基础上再添加其他的规则而形成的。
其目的就是提供上述的功能。
2.寄存器的使用规则
寄存器的使用必须满足下面的规则:
(1)子程序间通过寄存器R0~R3来传递参数。
这时,寄存器R0~R3可以记作A0~A3。
被调用的子程序在返回前无需恢复寄存器R0~R3的内容。
(2)在子程序中,使用寄存器R4~Rll来保存局部变量。
这时,寄存器R4~R11可以记作V1~V8。
如果在子程序中使用到了寄存器V1~V8中的某些寄存器,子程序进入时必须保存这些寄存器的值,在返回前必须恢复这些寄存器的值;
对于子程序中没有用到的寄存器则不必进行这些操作。
在Thumb程序中,通常只能使用寄存器R4~R7来保存局部变量。
(3)寄存器R12用作子程序间scratch寄存器,记作IP。
在子程序间的连接代码段中常有这种使用规则。
(4)寄存器R13用作数据栈指针,记作SP。
在子程序中寄存器R13不能用作其他用途。
寄存器SP在进入子程序时的值和退出子程序时的值必须相等。
(5)寄存器R14称为连接寄存器,记作LR。
它用于保存子程序的返回地址。
如果在
子程序中保存了返回地址,寄存器R14则可以用作其他用途。
(6)寄存器R15是程序计数器,记作PC。
它不能用作其他用途。
3.参数传递规则根据参数个数是否固定可以将子程序分为参数个数固定的(nonvariadic)子程序和参数
个数可变的(variadic)子程序。
这两种子程序的参数传递规则是不同的。
(1)参数个数可变的子程序参数传递规则
对于参数个数可变的子程序,当参数不超过4个时,可以使用寄存器R0~R3来传递参数;
当参数超过4个时,还可以使用数据栈来传递参数。
在参数传递时,将所有参数看作是存放在连续的内存字单元中的字数据。
然后,依次将各字数据传送到寄存器R0、R1、R2、R3中,如果参数多于4个,将剩余的字数据传送到数据栈中,入栈的顺序与参数顺序相反,即最后一个字数据先入栈。
按照上面的规则,一个浮点数参数可以通过寄存器传递,也可以通过数据栈传递,也可能一半通过寄存器传递,另一半通过数据栈传递。
(2)参数个数固定的子程序参数传递规则对于参数个数固定的子程序,参数传递与参数个数可变的子程序参数传递规则不同。
如果系统包含浮点运算的硬件部件,浮点参数将按照下面的规则传递:
·
各个浮点参数按顺序处理。
为每个浮点参数分配FP寄存器。
分配的方法是,满足该浮点参数需要的且编号最小的一组连续的FP寄存器。
第一个整数参数,通过寄存器R0~R3来传递。
其他参数通过数据栈传递。
(3)子程序结果返回规则子程序中结果返回的规则如下:
结果为一个32位的整数时,可以通过寄存器R0返回。
结果为一个64位整数时,可以通过寄存器R0和Rl返回,依次类推。
结果为一个浮点数时,可以通过浮点运算部件的寄存器f0、d0或者s0来返回。
结果为复合型的浮点数(如复数)时,可以通过寄存器f0~fN或者d0~dN来返回。
对于位数更多的结果,需要通过内存来传递。
语言函数和ARM汇编语言函数间相互调用高级语言函数与汇编语言函数的混合调用也要遵循ATPCS规则,保证程序调用时参数的正确传递。
在汇编程序中使用EXPORT伪指令声明本子程序,使其它程序可以调用此子程序,而在C语言程序中使用extern关键字声明外部函数(声明要调用的汇编子程序),即可调用此汇编子程序。
下面给出两个例子来介绍函数相互调用。
6、实验步骤
1.编写一段程序,用P1口作为控制端口,使D1区的LED轮流点亮。
原理图如下图。
图3-1走马灯实验原理图
①仿照实验一的过程,编写程序、汇编、连接、软件仿真,基本达到功能要求。
ORG0000H
LJMPMAIN
ORG0100H
MAIN:
MOVA,#0FEH;
准备点亮第一只发光管
NEXT:
MOVP1,A
ACALLDELAY
RLA;
准备点亮下一只发光管
SJMPNEXT
;
延时子程序
DELAY:
MOVR2,#5
DELAY2:
MOVR3,#100
DELAY3:
MOVR4,#100
DJNZR4,$
DJNZR3,DELAY3
DJNZR2,DELAY2
RET
END
调试成功以后,将程序中的ORG部分的偏移地址再加上8000H,重新编译。
②按照原理图,将A1区P1口的引线分别连接到D1区J52上。
③下载监控程序到实验仪上。
短接A1区的JP15,连接实验仪串口和主机的串口,将MOD-SW1拨到LOAD一边,FLASH-E和SRAM-E断开,运行主机上DPFLASH,下载到实验仪上。
④在Keil系统上,完成程序的动态调试。
在主菜单DEBUG下的OptionsforTarget‘Target1’,点击Debug,选择UseKeilMonitor-51Driver,并且设置其他参数,将MOD-SW1拨到RUN一边,按复位键,再按DEBUG下的全速运行命令运行监控程序后,就可以进行动态调试了。
观察和记录各个寄存器内容的变化,端口P1的内容变化,以及对应的LED的变化。
全速运行时,观察LED的变化和闪烁速度。
7、实验相关寄存器
GPBCON――端口配置寄存器
GPBDAT――端口数据寄存器
GPBUP――端口上拉电阻使能寄存器
8、实验电路图
2.编写一段程序,用P1口作为控制端口,使D1区的LED轮流点亮。
用外部中断0控制走马灯的暂停/继续。
(此实验也可脱机运行)
ORG0000H
LJMPMAIN
ORG0003
LJMPZEX0
ORG0100H
MOVSP,#60H
SETBIT0
SETBEX0
SETBEA
MOVA,#0FEH;
MOVR5,#00H
CJNER5,#00H,NEXT;
00表示继续,FF表示暂停
ACALLDELAY
RLA;
准备点亮下一只发光管
SJMPNEXT
DJNZR4,$
DJNZR3,DELAY3
DJNZR2,DELAY2
RET
外部中断0服务子程序
ZEX0:
PUSHACC
MOVA,R5
XRLA,#0FFH
MOVR5,A
POPACC
RETI
END
将A1区P1口的引线分别连接到D1区J52上,将D1区的J53的KEY1连接到A1区的外部中断0上。
观察实验结果,解释如何实现走马灯的暂停和继续。
比较电平触发和边沿触发时走马灯控制的难易程度。
3.编写一段程序,用P1口作为控制端口,使D1区的LED轮流点亮。
用定时/计数器0控制走马灯的闪烁速度。
ORG000BH
LJMPZIT0
MOVSP,#60H
MOVTMOD,#01H
MOVTH0,#3CH
MOVTL0,#0B0H
MOVR6,#20/循环次数
MOVR7,#0FEH;
SETBET0
SETBEA
SETBTR0
SJMP$
定时中断0服务子程序
ZIT0:
DJNZR6,ZRET/为零时,跳转!
MOVA,R7
MOVP1,A
RLA
MOVR7,A
ZRET:
MOVTH0,#3CH
RETI
修改R6=0或1时,观察走马灯的速度快慢。
ZRET:
处没有重置初值时的走马灯的速度与ZRET处有重置初值时的走马灯的速度的比较。
R6=50时,改变T0的初值,设为最大、最小时,比较走马灯的速度。
去掉R6的软件辅助延时,是否可以,速度怎样
9、实验记录
第一个程序走马灯逐步地闪亮
第二个程序当按下D1区k1时,走马灯暂停,再按下时就又开始了!
第三个程序把R6值改大了,那间隔时间就增大!
走马灯越来越慢
!
10、实验结果分析
程序运行后,LED灯D3、D4不断闪烁,跑马灯程序运行。
11、实训分析与总结:
1、简述LED灯点亮的原理
2、观察并描述实验现象,尝试修改参数,使得LED灯变化的更快或者更慢。
3、实验的体会。
实验现象:
1号灯亮→2号灯亮→1、2号灯亮→3号灯亮→1、2、3号灯亮→4号灯亮→4个灯全亮→4个灯全灭→4号灯亮→3号灯亮→2号灯亮→1号灯亮→1、2号灯亮→1、2、3号灯亮→4个灯全亮→4个灯全灭→4号灯亮→3、4号灯亮→2、3、4号灯亮→4个灯全亮→全灭→1、2号灯亮→1、2、3号灯亮→全亮→全灭。
12、实验程序:
/*定义端口寄存器*/
#definerGPBCON(*(volatileunsigned*)0x)//PortBcontrol
#definerGPBDAT(*(volatileunsigned*)0x)//PortBdata
#definerGPBUP(*(volatileunsigned*)0x)//Pull-upcontrolB
/*延迟程序*/
externvoiddelay(inttimes);
/*主程序*/
voidxmain(void)
{
rGPBCON=(rGPBCON&
~(0xff<
<
10))|(0x55<
10);
//GPB5-8setoutput
rGPBUP=(rGPBUP&
~(0xf<
5))|(0xf<
5);
//disableGPBpullup
while
(1)
{rGPBDAT=(rGPBDAT|(0xf<
5))&
(~(0x1<
5));
//GPB7output0
delay(0x1000000);
//调用汇编语言编写的延时程序
rGPBDAT=(rGPBDAT|(0xf<
6));
rGPBDAT=rGPBDAT&
~(0x3<
//两个个灯亮
//调用汇编语言编写的延时程序
7));
~(0x7<
//1.2.3亮
delay(0x2000000);
8));
//GPB8output0
//调用汇编语言编写的延时程序0
//4灯全亮
rGPBDAT=rGPBDAT|(0xf<
//全灭
//4ok
7);
6);
//2.3.4三个灯亮
}