嵌入式作业二

一、打开04-Software\CH02\CH02-1-20220118工程目录,编译下载运行,理解并学习main.s汇编源文件

导入该工程,编译运行

连接GEC,串口更新

二、修改main.s文件,增加以下内容:

1.在第一行显示“广州大学”字样

2.编写一个求和程序“1+2+3+...+10”,将求和结果存入名为“sunset”的内存单元中,并将求和结果用printf显示出来

实现源代码:

//=====================================================================
//文件名称:main.s
//功能概要:汇编编程调用GPIO构件控制小灯闪烁(利用printf输出提示信息)
//版权所有:SD-ARM(sumcu.suda.edu.cn)
//版本更新:20180810-20191018
//=====================================================================
.include "include.inc"    //头文件中主要定义了程序中需要使用到的一些常量
//(0)数据段与代码段的定义
//(0.1)定义数据存储data段开始,实际数据存储在RAM中
.section .data
//(0.1.1)定义需要输出的字符串,标号即为字符串首地址,\0为字符串结束标志
hello_information:           //字符串标号
    .ascii "-------------------------------------------------------\n"
    .ascii "金葫芦提示:                                             \n"
    .ascii "1、本程序用来示范如何输出指令所在flash单元的地址以及指令  \n"
    .ascii "所对应的机器码。                                        \n"
    .ascii "2、Debug文件夹中的.lst文件可搜索汇编指令找到对应的机器码。\n"
    .ascii "3、printf函数可根据输出格式输出参数的值。                \n"
    .ascii "------------------------------------------------------\n\0"
 
my_printinfo:		//打印广州大学等信息
	.ascii "广州大学!\n"
	.ascII "32106100045\t黄彬斌\n"
	.ascii "sumresult= \0"
 
data_format2:
	.ascii "有符号数0x%x,0x%x,0x%x中,最大的是\0"
data_format3:
	.ascII "0x%x\n\0"
 
 
data_format:
    .ascii "%d\n\0"                 //printf使用的数据格式控制符
 
data_format1:
    .ascii "%08x:%02x\n\0"                 //printf使用的数据格式控制符,其中8表示输出位数,
                                         //0表示将输出的前面补上0,直到占满指定列宽为止
                  
 
light_show1:
	.ascii "LIGHT_BLUE:ON--\n\0"    //灯亮状态提示   
light_show2:
	.ascii "LIGHT_BLUE:OFF--\n\0"   //灯暗状态提示
light_show3:
	.ascii "闪烁次数mLightCount=\0"  //闪烁次数提示
//(0.1.2)定义变量
.align 4               //.word格式四字节对齐
mMainLoopCount:		   //定义主循环次数变量
	.word 0
mFlag:				   //定义灯的状态标志,1为亮,0为暗
	.byte 'A'	
.align 4
mLightCount:
    .word 0
sumresult:			   //定义内存单元sumresult初始值为0
	.word 0
 
//定义三个数字(进行有符号比较)
datax:
	.word 0x12211111
datay:
	.word 0x87654321
dataz:
	.word 0x65555555
 
//(0.2)定义代码存储text段开始,实际代码存储在Flash中
.section   .text
.syntax unified        //指示下方指令为ARM和thumb通用格式
.thumb                 //Thumb指令集
.type main function    //声明main为函数类型                     
.global main           //将main定义成全局函数,便于芯片初始化之后调用
.align 2               //指令和数据采用2字节对齐,兼容Thumb指令集
 
//--------------------------------------------------------------------                        
//main.c使用的内部函数声明处
 
//--------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
main:
//(1)======启动部分(开头)主循环前的初始化工作======================
//(1.1)声明main函数使用的局部变量
 
//(1.2)【不变】关总中断
	cpsid i   
//(1.3)给主函数使用的局部变量赋初值
	
//(1.4)给全局变量赋初值
	
//(1.5)用户外设模块初始化
//  初始化蓝灯, r0、r1、r2是gpio_init的入口参数
	ldr r0,=LIGHT_BLUE     //r0指明端口和引脚(用=,因常量>=256,需用ldr)
	mov r1,#GPIO_OUTPUT    //r1指明引脚方向为输出
	mov r2,#LIGHT_OFF       //r2指明引脚的初始状态为亮
	bl  gpio_init          //调用gpio初始化函数
//  初始化串口UART_User1
	mov r0,#UART_User       //串口号
	ldr r1,=UART_BAUD       //波特率
	bl uart_init            //调用uart初始化函数
//(1.6)使能模块中断
    mov r0,#UART_User       //串口号
    bl  uart_enable_re_int  //调用uart中断使能函数
 
//(1.7)【不变】开总中断
	cpsie  i  
//显示hello_information定义的字符串
	//ldr r0,=hello_information   //待显示字符串首地址
	//bl  printf		            //调用printf显示字符串
	
//编写一个1+2+...+10的程序,将求和结果存入名为“sumresult”的内存单元中,并将求和结果用printf显示出来
	//预先打印1+2+3……
	ldr r0, =my_printinfo
	bl printf
	
	//定义累加寄存器和循环计数器和初始值
	mov r1,#0
	mov r2,#10
	mov r3,#1
 
//循环
loop:
	//将r3加到r1上,r3自增,r2自减,其中subs用于更新标志位用于判断是否跳出循环
	add r1,r1,r3
	add r3,#1
	subs r2,r2,#1
	bne loop
	
	//跳出循环,将r1存入sumresult
	ldr r3,=sumresult
	str r1,[r3]
	//显示求和结果,这里是用%d输出,源代码就有,直接使用即可
	ldr r0,=data_format
	ldr r1,[r3]
	bl printf
	//ldr r0,=data_format
	//bl printf
	
	ldr r0,=datax
	ldr r1,[r0]
	ldr r0,=datay
	ldr r2,[r0]
	ldr r0,=dataz
	ldr r3,[r0]
	
	cmp r1,r2	//比较r1和r2
	bgt compare_dataxz	//如果r1>r2,则r1跟r3比
	cmp r2,r3	//如果r1<r2,则r2跟r3比
	bgt compare_datayz
	
compare_datayz:
	cmp r2,r3	//r2跟r3比
	bgt compare_r2win
	mov r4,r3	//说明r3最大,
	bl end_compare
 
compare_dataxz:
	cmp r1,r3	//r1跟r3比
	bgt compare_r1win	//如果r1>r3,则r1最大
	mov r4,r3	//说明r3最大,
	bl end_compare
 
compare_r1win:
	mov r4,r1	//r1的值赋给r4
	bl end_compare	//跳出比较
 
compare_r2win:
	mov r4,r2	//r2的值赋给r4
	bl end_compare
 
end_compare:
	//输出比较的结果
	ldr r0,=data_format2
	ldr r0,=data_format3
	mov r1,r4
	
	bl .   //在此打桩(.表示当前地址),理解发光二极管为何亮起来了?
 
	
//(1)======启动部分(结尾)=======================================
 
//(2)======主循环部分(开头)=====================================
main_loop:                      //主循环标签(开头)
//(2.1)主循环次数变量mMainLoopCount+1
		ldr r2,=mMainLoopCount     //r2←mMainLoopCount的地址
		ldr r1, [r2]
		add r1,#1
		str r1,[r2]	
//(2.2)未达到主循环次数设定值,继续循环
        ldr r2,=MainLoopNUM
		cmp r1,r2
		blO  main_loop     //未达到,继续循环
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
 
//测试代码部分[理解机器码存储]
Label:	
	MOV  R0,#0xDE               //立即数范围为0x00~0xFF
	
	ldr r0,=data_format1        //输出格式送r0 
	ldr r1,=Label               //r1中是Label地址
	ldrb r2,[r1]                //r2中是Label地址中的数据
	bl  printf	
	
	ldr r0,=data_format1         //输出格式送r0 
	ldr r1,=Label+1              //r1中是Label+1地址
	ldrb r2,[r1]                 //r2中是Label+1地址中的数据
	bl  printf	
	
	ldr r0,=data_format1         //输出格式送r0 
	ldr r1,=Label+2              //r1中是Label+2地址
	ldrb r2,[r1]                 //r2中是Label+2地址中的数据

	
	ldr r0,=data_format1         //输出格式送r0 
	ldr r1,=Label+3              //r1中是Label+3地址
	ldrb r2,[r1]                 //r2中是Label+3地址中的数据
	bl  printf	
 
//(2.3.1)清除循环次数变量
		ldr r2,=mMainLoopCount     //r2←mMainLoopCount的地址
		mov r1,#0
		str r1,[r2]	
//(2.3.2)如灯状态标志mFlag为'L',灯的闪烁次数+1并显示,改变灯状态及标志	
		//判断灯的状态标志
		ldr r2,=mFlag		   
		ldr r6,[r2]
		cmp r6,#'L'			
		bne main_light_off	   //mFlag不等于'L'转
		//mFlag等于'L'情况
		ldr r3,=mLightCount	   //灯的闪烁次数mLightCount+1
		ldr r1,[r3]
		add r1,#1				
		str r1,[r3]
		ldr r0,=light_show3   //显示“灯的闪烁次数mLightCount=”
		bl  printf				
		ldr r0,=data_format    //显示灯的闪烁次数值
		ldr r2,=mLightCount
		ldr r1,[r2]
		bl  printf	
		ldr r2,=mFlag           //灯的状态标志改为'A'
		mov r7,#'A'
		str r7,[r2]             
		ldr r0,=LIGHT_BLUE      //亮灯
		ldr r1,=LIGHT_ON
		bl  gpio_set          
		ldr r0, =light_show1    //显示灯亮提示
		bl  printf	
		//mFlag等于'L'情况处理完毕,转
		b main_exit  
//(2.3.3)如灯状态标志mFlag为'A',改变灯状态及标志
main_light_off:
        ldr r2,=mFlag		   //灯的状态标志改为'L'        
		mov r7,#'L'
		str r7,[r2]   
        ldr r0,=LIGHT_BLUE      //暗灯
		ldr r1,=LIGHT_OFF
		bl  gpio_set  
        ldr r0, =light_show2    //显示灯暗提示
		bl  printf	
main_exit:
	b main_loop                 //继续循环
//(2)======主循环部分(结尾)=====================================
.end     //整个程序结束标志(结尾)

结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值