您好,登錄后才能下訂單哦!
?GPIO(General Purpose I/O Ports)意思為通用輸入/輸出端口,通俗地說,就是一些引腳,可以通過它們輸出高低電平、或者通過它們讀入引腳的狀態──是高電平還是低電平。
?三星 S3C2440,有130個I/O端口,分為A-J九組,可以通過設置寄存器來確定某個引腳用于輸入、輸出還是特殊功能。在這里通過四個實驗介紹GPIO的簡單使用。
1、通過匯編語言點亮LED燈
?首先需要看原理圖,知道LED與芯片引腳的關系。
????
?由原理圖可知,2440引腳作為輸出引腳與LED燈連接,要使LED燈點亮,配置相關寄存器為輸出引腳,且將該引腳輸出低電平即可點亮LED燈。查看2440芯片手冊,GPB組引腳控制寄存器地址為:0x56000010,數據寄存器地址為:0x56000014。點亮LED1的匯編代碼為:
.text
.global _start
_start:
LDR R0,=0x56000010 @ R0設為GPBCON寄存器。此寄存器用于選擇端口B各引腳的功能: 是輸出、是輸入、還是其他
MOV R1,#0x00000400
STR R1,[R0] @ 設置GPB5為輸出口, 位[11:10]=0b01
LDR R0,=0x56000014 @ R0設為GPBDAT寄存器。此寄存器用于讀/寫端口B各引腳的數據
MOV R1,#0x00000000 @ 此值改為0x00000020,可讓LED1熄滅
STR R1,[R0] @ GPB5輸出0,LED1點亮
MAIN_LOOP:
B MAIN_LOOP
其Makefile為:
led_on.bin : led_on.S
arm-linux-gcc -g -c -o led_on.o led_on.S
arm-linux-ld -Ttext 0x0000000 -g led_on.o -o led_on_elf
arm-linux-objcopy -O binary -S led_on_elf led_on.bin
clean:
rm -f led_on.bin led_on_elf *.o
編譯后下載到TQ2440開發板后效果:led_1點亮
2、通過C語言點亮LED燈
?在使用C語言點亮LED燈時,首先需要進行硬件相關初始化與軟件相關初始化。硬件相關有:關看門狗、初始化時鐘、初始化SDRAM等,而對于點亮LED燈實驗,只需要關閉看門狗即可;軟件方面,需要設置返回地址,即設置棧、調用main函數等。首先,匯編代碼部分:
.text
.global _start
_start:
ldr r0, =0x53000000 @ WATCHDOG寄存器地址
mov r1, #0x0
str r1, [r0] @ 寫入0,禁止WATCHDOG,否則CPU會不斷重啟
ldr sp, =1024*4 @ 設置堆棧,注意:不能大于4k, 因為現在可用的內存只有4K,nand flash中的代碼在復位后會移到內部ram中,此ram只有4K
bl main @ 調用C程序中的main函數
halt_loop:
b halt_loop
C語言部分:
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
int main()
{
GPBCON = 0x00000400; // 設置GPB5為輸出口, 位[11:10]=0b01
GPBDAT = 0x00000000; // GPB5輸出0,LED1點亮
return 0;
}
Makefile代碼為:
led_on_c.bin : crt0.S led_on_c.c
arm-linux-gcc -g -c -o crt0.o crt0.S
arm-linux-gcc -g -c -o led_on_c.o led_on_c.c
arm-linux-ld -Ttext 0x0000000 -g crt0.o led_on_c.o -o led_on_c_elf
arm-linux-objcopy -O binary -S led_on_c_elf led_on_c.bin
arm-linux-objdump -D -m arm led_on_c_elf > led_on_c.dis
clean:
rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o
編譯后下載到TQ2440開發板后效果:led_1點亮
3、通過按鍵控制LED燈點亮
?通過按鍵控制LED燈時,首先看原理圖,了解按鍵與2440芯片連接的引腳關系。
?使用匯編完成相關初始化,跳轉到main函數中,C程序部分通過按鍵實現LED燈的亮與滅。
匯編代碼:
.text
.global _start
_start:
ldr r0, =0x53000000 @ WATCHDOG寄存器地址
mov r1, #0x0
str r1, [r0] @ 寫入0,禁止WATCHDOG,否則CPU會不斷重啟
ldr sp, =1024*4 @ 設置堆棧,注意:不能大于4k, 因為現在可用的內存只有4K,nand flash中的代碼在復位后會移到內部ram中,此ram只有4K
bl main @ 調用C程序中的main函數
halt_loop:
b halt_loop
C語言代碼:
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054)
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
/*
* LED1,LED2,LED3、LED4對應GPB5、GPB6、GPB7、GPB8
*/
#define GPB5_out (1<<(5*2))
#define GPB6_out (1<<(6*2))
#define GPB7_out (1<<(7*2))
#define GPB8_out (1<<(8*2))
#define GPB5_msk (3<<(5*2))
#define GPB6_msk (3<<(6*2))
#define GPB7_msk (3<<(7*2))
#define GPB8_msk (3<<(8*2))
/*
* K1,K2,K3,K4對應GPF1、GPF4、GPF2、GPF0
*/
#define GPF0_in (0<<(0*2))
#define GPF1_in (0<<(1*2))
#define GPF2_in (0<<(2*2))
#define GPF4_in (0<<(4*2))
#define GPF0_msk (3<<(0*2))
#define GPF1_msk (3<<(1*2))
#define GPF2_msk (3<<(2*2))
#define GPF4_msk (3<<(4*2))
int main()
{
unsigned long dwDat;
// LED1,LED2,LED3,LED4對應的4根引腳設為輸出
GPBCON &= ~(GPB5_msk | GPB6_msk | GPB7_msk | GPB8_msk);
GPBCON |= GPB5_out | GPB6_out | GPB7_out | GPB8_out;
// K1,K2,K3,K4對應的4根引腳設為輸入
GPFCON &= ~(GPF0_msk | GPF1_msk | GPF2_msk | GPF4_msk);
GPFCON |= GPF0_in | GPF1_in | GPF2_in | GPF4_in;
while(1){
//若Kn為0(表示按下),則令LEDn為0(表示點亮)
dwDat = GPFDAT; // 讀取GPF管腳電平狀態
if (dwDat & (1<<1)) // K1沒有按下
GPBDAT |= (1<<5); // LED1熄滅
else
GPBDAT &= ~(1<<5); // LED1點亮
if (dwDat & (1<<4)) // K2沒有按下
GPBDAT |= (1<<6); // LED2熄滅
else
GPBDAT &= ~(1<<6); // LED2點亮
if (dwDat & (1<<2)) // K3沒有按下
GPBDAT |= (1<<7); // LED3熄滅
else
GPBDAT &= ~(1<<7); // LED3點亮
if (dwDat & (1<<0)) // K4沒有按下
GPBDAT |= (1<<8); // LED4熄滅
else
GPBDAT &= ~(1<<8); // LED4點亮
}
return 0;
}
Makefile:
key_led.bin : crt0.S key_led.c
arm-linux-gcc -g -c -o crt0.o crt0.S
arm-linux-gcc -g -c -o key_led.o key_led.c
arm-linux-ld -Ttext 0x0000000 -g crt0.o key_led.o -o key_led_elf
arm-linux-objcopy -O binary -S key_led_elf key_led.bin
arm-linux-objdump -D -m arm key_led_elf > key_led.dis
clean:
rm -f key_led.dis key_led.bin key_led_elf *.o
編譯后下載到TQ2440開發板后效果:
? ? ?
4、通過延時循環點亮LED燈
?與使用點亮一盞LED燈類似,通過循環與延時函數即可完成另LED循環閃爍的效果。
實驗源碼
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。