1. 程式人生 > 其它 >廣州大學 組合語言與介面技術實驗2 簡單介面應用實驗 2020.12

廣州大學 組合語言與介面技術實驗2 簡單介面應用實驗 2020.12

技術標籤:彙編嵌入式

文章提到的使用者手冊,下載地址:提取碼:9jsv

一、 實驗目的

1、熟練使用ubuntu Linux作業系統。
2、掌握常用的彙編命令,如mov、sub、add、ldr、str等。
3、掌握閱讀原理圖技巧,實現跑馬燈的效果。
4、熟練掌握arm-linux-gcc編譯程式的方法。
5、熟練掌握使用串列埠下載檔案到開發板的方法。

二、 實驗原理

一、分析原理圖,瞭解LED燈控制原理

S5P6818處理器有四個GPIO引腳控制四個LED燈。
GPIO引腳輸出高電平(3.3V),LED燈滅。
GPIO引腳輸出低電平(0V),LED燈亮。

二、分析S5P6818處理器中的GPIO

S5P6818處理器GPIO分成了5組,分別是:A、B、C、D、E,每個組32個引腳,共160個引腳。
GPIOE13 —— 控制D7燈
GPIOC17 —— 控制D8燈
GPIOC8 —— 控制D9燈
GPIOC7 —— 控制D10燈

三、LED的控制流程

1、將GPIO引腳配置成IO功能。
2、將這個GPIO再設定成Output
3、設定GPIO引腳輸出低電平,LED燈亮
4、設定GPIO引腳輸出高電平,LED燈滅

四、分析暫存器

1、GPIOxALTFN0/GPIOxALTFN1 —— 配置一個引腳為I/O

其中GPIOxALTFN0 —— 配置Pin0~Pin15
GPIOxALTFN1 —— 配置Pin0~Pin31

以:GPIOE13為例子
應該使用GPIOEALTFN0為暫存器配置GPIOE13作為GPIO功能。
GPIOEALTFNO暫存器地址為:0xC001000 + 0xE020
在這裡插入圖片描述GPIOEALTFN0暫存器有32個位,每個位為1組,每個組控制一個引腳的複用功能,我們先找到13號引腳。

在這裡插入圖片描述
需要配置的是第27和第26位。
一個引腳的複用功能有四個,要找到GPIOE13,需要到SEC_S5P6818使用者手冊查詢第二章

在這裡插入圖片描述
可以看到是Function0,則需要將GPIOEALTFN0的第26和27位置00即把引腳配置成GPIOE13功能。

2、GPIOxOUTENB —— 將一個GPIO配置成輸入或者輸出功能

每個位對應一個引腳,通過暫存器的位設定GPIO位輸入還是輸出。

首先可以在手冊中找到GPIOEOUTENB的位置

在這裡插入圖片描述地址為:0xC001000 + 0xE004

在這裡插入圖片描述
其中,0為輸入,1為輸出。
因此需要將第13位置為1。

3、GPIOxOUT —— 設定GPIO輸出的電平

找到GPIOEOUT的暫存器地址為:0xC001000 + 0xE000
在這裡插入圖片描述
在這裡插入圖片描述

其中,0為低電平,1為高電平。
因此,可以將13位置0或1來控制燈的點亮或者熄滅。

三、 實驗儀器、材料

三星S5P6818開發板(ARM Cortex-A53架構)
手提電腦

四、 實驗步驟

1、編寫流水燈控制的彙編程式碼

//GPIOE
#define GPIOEOUT	 0xC001E000
#define GPIOEOUTENB  0xC001E004
#define GPIOEALTFN0	 0xC001E020
#define GPIOEALTFN1	 0xC001E024


//GPIOC
#define GPIOCOUT	 0xC001C000
#define GPIOCOUTENB  0xC001C004
#define GPIOCALTFN0	 0xC001C020
#define GPIOCALTFN1	 0xC001C024

.text	//程式碼段的開始
.global _start

_start:
//配置GPIOE13為輸出模式
//GPIOEALTFN0 &= ~(3<<26);
	ldr r1,=GPIOEALTFN0
	ldr r0,[r1]
	ldr r2,=~(3<<26)
	and r0,r0,r2
	str r0,[r1]
//GPIOEOUTENB |= 1<<13;
    ldr r1,=GPIOEOUTENB
	ldr r0,[r1]
	ldr r2,=(1<<13)
	orr r0,r0,r2
	str r0,[r1]

//配置GPIOC17為輸出模式
//GPIOCALTFN1 &= ~(3<<2);
	ldr r1,=GPIOCALTFN1
	ldr r0,[r1]
	ldr r2,=~(3<<2)
	and r0,r0,r2
	str r0,[r1]
//GPIOCALTFN1 |= 1<<2;
    ldr r1,=GPIOCALTFN1
	ldr r0,[r1]
	ldr r2,=(1<<2)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUTENB |= 1<<17;
    ldr r1,=GPIOCOUTENB
	ldr r0,[r1]
	ldr r2,=(1<<17)
	orr r0,r0,r2
	str r0,[r1]

//配置GPIOC7、GPIOC8為輸出模式
//GPIOCALTFN0 &= ~((3<<16)|(3<<14));
	ldr r1,=GPIOCALTFN0
	ldr r0,[r1]
//取反
    ldr r3,=(3<<16)
    ldr r4,=(3<<14)
    orr r3,r3,r4
    ldr r4,=0xFFFFFFFF
    eor r2,r3,r4
//取反
	and r0,r0,r2
	str r0,[r1]
//GPIOCALTFN0 |= (1<<16)|(1<<14);
    ldr r1,=GPIOCALTFN0
	ldr r0,[r1]
//連續或
    ldr r3,=(1<<16)
	ldr r4,=(1<<14)
	orr r2,r3,r4
//連續或
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUTENB |= (1<<8)|(1<<7);
    ldr r1,=GPIOCOUTENB
	ldr r0,[r1]
//連續或
    ldr r3,=(1<<8)
	ldr r4,=(1<<7)
	orr r2,r3,r4
//連續或
	orr r0,r0,r2
	str r0,[r1]

//while迴圈
loop:
//點亮D7,其他燈熄滅
//GPIOEOUT &= ~(1<<13);
	ldr r1,=GPIOEOUT
	ldr r0,[r1]
	ldr r2,=~(1<<13)
	and r0,r0,r2
	str r0,[r1]
//GPIOCOUT |= 1<<17;
    ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=(1<<17)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUT |= 1<<8;
    ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=(1<<8)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUT |= 1<<7;
    ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=(1<<7)
	orr r0,r0,r2
	str r0,[r1]
//delay();
    bl delay
//點亮D8,其他燈熄滅
//GPIOEOUT |= 1<<13;
    ldr r1,=GPIOEOUT
	ldr r0,[r1]
	ldr r2,=(1<<13)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUT &= ~(1<<17);
	ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=~(1<<17)
	and r0,r0,r2
	str r0,[r1]
//GPIOCOUT |= 1<<8;
    ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=(1<<8)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUT |= 1<<7;
    ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=(1<<7)
	orr r0,r0,r2
	str r0,[r1]
//delay();
    bl delay
//點亮D9,其他燈熄滅
//GPIOEOUT |= 1<<13;
    ldr r1,=GPIOEOUT
	ldr r0,[r1]
	ldr r2,=(1<<13)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUT |= 1<<17;
    ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=(1<<17)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUT &= ~(1<<8);
	ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=~(1<<8)
	and r0,r0,r2
	str r0,[r1]
//GPIOCOUT |= 1<<7;
    ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=(1<<7)
	orr r0,r0,r2
	str r0,[r1]
//delay();
    bl delay
//點亮D10,其他燈熄滅
//GPIOEOUT |= 1<<13;
    ldr r1,=GPIOEOUT
	ldr r0,[r1]
	ldr r2,=(1<<13)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUT |= 1<<17;
    ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=(1<<17)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUT |= 1<<8;
    ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=(1<<8)
	orr r0,r0,r2
	str r0,[r1]
//GPIOCOUT &= ~(1<<7);
	ldr r1,=GPIOCOUT
	ldr r0,[r1]
	ldr r2,=~(1<<7)
	and r0,r0,r2
	str r0,[r1]
//delay();
    bl delay
    b loop

delay:
	push {r0,lr}

	ldr r0,=0x2FF0000
	
delay_loop:
	sub r0,r0,#1
	cmp r0,#0
	bne delay_loop
	bx lr
		

//程式碼段的結束
.end

2.儲存,並在ubuntu作業系統中使用編譯程式碼
arm-linux-gcc -c led.S -o led.o -nostdlib
arm-linux-ld -Ttext 0x40000000 -o led.elf led.o
arm-linux-objcopy -O binary led.elf led.bin
獲得.bin檔案。

3.將.bin檔案通過串列埠下載到開發板中。
將開發板執行在uboot狀態
在命令列輸入
loady 0x40000000

4.執行程式
go 0x40000000

五、實驗結果及分析

1、D7、D8、D9、D10四盞燈輪流點亮。

2、當其中一盞燈燈亮的時候,其餘燈熄滅。

3、其中一盞燈到下一盞燈的時長是可以由delay函式來控制的,在本次實驗中,將delay中設定了一個數0x2FF0000,當此數歸0時,下一盞燈燈亮。如果想要流水燈變慢,可以擴大這個16進位制數。

4、原理是通過GPIOxOUT的輪換變化來控制燈的燈亮和熄滅。