一、 实验目的
- 了解 ARM9 的启动过程,学会使用 MDK 编写简单的 C 语言程序和汇编启动代码并进行调试;
- 掌握如何指定代码入口地址与入口点;
- 掌握通过 memory、register、watch、Local 等窗口分析判断结果;
- 掌握在汇编程序中使用C程序的全局变量;
- 掌握C语言与汇编程序的混合编程方法;
- 掌握嵌入式内部可编程模块的开发方法。
二、 实验设备
- 硬件:PC 机。
- 软件:µVision IDE for ARM 集成开发环境。
三、 实验任务与要求
1. 用 c 语言编写延时函数,使用嵌入汇编。
(1) 单步执行EduKit2410_for_MDK修正\3.6_c2\CTest2.Uv2
工程,理解每条语句的意义;
IMPORT __main ;导入c函数_main
LDR R0, =__main ;用伪指令将_main函数入口地址加载到R0
BX R0 ;跳转执行R0
; # jump to __main()
;# *********************************************************
;# * Loop for ever *
;# * End of application. Normally, never occur. *
;# * Could jump on Software Reset ( B 0x0 ). *
;# *********************************************************
End
b End
end
/*********************************************************************************************
* File: c2.c
* Author: Wuhan R&D Center, embest
* Desc: c language example 2
* History:
*********************************************************************************************/
/*********************************************************************************************
* name: _nop_
* func: The following example embed assembel language
* para: none
* ret: none
* modify:
* comment:
*********************************************************************************************/
void _nop_(void)
{
int temp=0;
__asm
{
mov temp,temp //调用mov操作,实现一次“空操作”目的是为了实现一段延时(具体时间由指令周期决定)
}
}
/*********************************************************************************************
* name: delay
* func: delay time
* para: none
* ret: none
* modify:
* comment:
*********************************************************************************************/
void delay(void)
{
int i;
for(i=0;i<=10;i++)
{
_nop_(); // 调用_nop_()
}
}
/*********************************************************************************************
* name: delay10
* func: delay time
* para: none
* ret: none
* modify:
* comment:
*********************************************************************************************/
void delay10(void)
{
int i;
for(i = 0; i <= 10; i++)
{
delay(); // 调用延时函数
}
}
/*********************************************************************************************
* name: _main
* func: c code entry
* para: none
* ret: none
* modify:
* comment:
*********************************************************************************************/
__main() // __main 函数
{
for( ; ; )
{
delay10(); // 调用10次延时函数
}
}
(2) 打开 memory、register、watch、Local 窗口,单步执行,并通过 memory/register/
watch/variable 窗口分析判断结果。注意观察程序如何从跳转进主程序__main,在 call stack 窗口观察当前执行函数之间的调用。在 watch 框中输入要观察变量 I 的值,并记录下来。特别注意在 local 窗口观察变量 I 的变化并记录下;
一直循环…
(3) 结合实验内容和相关资料,观察程序运行;
(4) 改写CTest2.Uv2中的程序,实现在 C 语言文件中调用汇编子程序,实现在 C 语言文件中定义全局变量,在汇编代码中读取全局变量并修改在存入全局变量中;
extern void func();
int x;
__main(){
func();
for( ; ; ){
delay10();
}
}
将全局变量x导入汇编文件,导入编写函数func
将全局变量x的地址装入r0中
给r1赋值6
将r1中的数写入到以r0为地址的内存中
返回主程序
import __main
import x
export func
func
ldr r0,=x
mov r1,#6
str r1,[r0]
bx lr
- 编写程序,控制实验平台的发光二极管 LED1,LED2,LED3,LED4,使它们有规律的点亮和熄灭,具体LED灯亮灭顺序请根据给出的程序写出来,并把每个端口寄存器的值写出来。
如图 4-14 所示,LED1-4 分别与 GFP7-4 相连,通过 GFP7-4 引脚的高低电平来控制发光二极管的亮与灭。当这几个管脚输出高电平的时候发光二极管熄灭,反之,发光二极管点亮。
(1) 把EduKit2410_for_MDK修正\4.2_led_test\led_test.c
中的语句进行解释;
void led_on(void)
{
int i,nOut;
nOut = 0xF0;
//rGPFDAT=nOut & 0x10;
rGPFDAT=nOut & 0xd0; //1101 0000
for(i=0;i<100000;i++);
rGPFDAT = nOut & 0x50; //0101 0000
for(i=0;i<100000;i++);
rGPFDAT=nOut & 0x40; //0100 0000
for(i=0;i<100000;i++);
rGPFDAT=nOut & 0x00; //0000 0000
for(i=0;i<100000;i++);
rGPFDAT=nOut ; //熄灭
}
void led_off(void)
{
int i,nOut;
nOut=0;
rGPFDAT = 0; //0000 0000
for(i=0;i<100000;i++);
rGPFDAT = nOut | 0x20; //0010 0000
for(i=0;i<100000;i++);
rGPFDAT |= nOut | 0xa0; //1010 0000
for(i=0;i<100000;i++);
rGPFDAT |= nOut | 0xb0;//0x20;
for(i=0;i<100000;i++);
rGPFDAT |= nOut | 0xf0;//0x10;
for(i=0;i<100000;i++);
}
(2) 如果图4-14中四个LED灯LED1-4分别与GPB0-3相连,通过GPB0-3控制LED灯发光,亮灭顺序如下:LED1-4全亮->LED1-4全灭->LED4亮->LED3亮->LED2亮->LED1亮-> LED1-4全灭。请在EduKit2410_for_MDK修正\4.2_led_test\led_test.c
代码基础上进行修改。
void led_test(void)
{
rGPBCON=0x55;
rGPBUP=0x0f;
uart_printf("\n I/O (Diode Led) Test Example\n");
rGPBDAT &= 0; //全亮
for(i=0;i<100000;i++);
rGPBDAT |= 0x0f //全灭
for(i=0;i<100000;i++);
rGPBDAT &= 0x07 //led4亮
for(i=0;i<100000;i++);
rGPBDAT |=0x0f //熄灭led4
rGPBDAT &=0x0b //点亮led3
for(i=0;i<100000;i++);
rGPBDAT |=0x0f //熄灭led3
rGPBDAT &=0x0d //点亮led2
for(i=0;i<100000;i++);
rGPBDAT |=0x0f //熄灭led2
rGPBDAT &=0x0e //点亮led1
for(i=0;i<100000;i++);
rGPBDAT |=0x0f //全部熄灭
for(i=0;i<100000;i++);
uart_printf(" end.\n");
}