廣州大學 組合語言與介面技術實驗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位輸入還是輸出。
地址為: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的輪換變化來控制燈的燈亮和熄滅。