1. 程式人生 > >11 裸板控制IO

11 裸板控制IO

裸板控制IO


控制器就是相當於一個介面,這個介面用於與特定用途的硬體模組通訊及資料的互動。

GPIO表示通用的IO介面,這些介面上面可以接不同的硬體模組。

GPIO口共分成組: GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOL。
每組裡面有數個不等的IO口。

GPIO口都是多功能的,可以做輸入、輸出、外部中斷、控制器的引腳。
GPIO口使用前都需要配置具體做什麼用途。

GPIO口是硬體的引腳,SOC廠家一般都會由控制器來管理,並給我們提供記憶體介面(就是通改變一個地址上的值)來讓我們的程式碼來控制IO口。

統一編址:記憶體晶片的地址與控制器的配置記憶體介面是在同一地址範圍裡的。
arm基本上都是統一編址,也就意味著我們改變控制器的相關配置時,對控制的配置介面(配置暫存器)像記憶體一般訪問即可。

PA21表示GPIOA組的第21個IO口。


檢視配套的幫助文件(Allwinner_H3_Datasheet_V1.1.edit.pdf)P316頁:

1.GPIO控制器的配置暫存器的基地址為:0x01C20800

2.每組IO口的配置暫存器都有4個,因每個IO需要3位來配置,所以分成4個暫存器
    Pn_CFG0(IO: 0 ~ 7)     // PA基地址: 0x01C20800, PC: 0x01c20848
    Pn_CFG1(IO: 8 ~ 15)    // PA: 0x01c20804, PC: 0x01c2084c
    Pn_CFG2(IO: 16 ~ 21)       // PA: 0x01c20808, PC: 0x01c20850
Pn_CFG3(目前沒有) // PA: 0x01c2080c, PC: 0x01c20854 3.Pn_DAT //PA: 0x01c20810, PC: 0x01c20858 可以通這個配置暫存器檢視或都改變相應IO口的電平狀況, 在這個暫存器裡每個IO口只佔用一位,第幾個IO口就是第幾位。 4.Pn_DRV0 //0x01c20814, PC: 0x01c2085c 用於配置IO口的輸出電流。 Pn_DRV1 //0x01c20818, PC: 0x01c20860 5.Pn_PUL0 //0x01c2081c, PC: 0x01c20864 用於配置相應的IO口的預設電平是高還是低(上拉/下拉),也就是當外面不來改變電平時是處於什麼電平狀態。 如果外面有改變,則隨外面的改變而改變。 Pn_PUL1 //0x01c20820, PC: 0x01c20868

輸入是指IO口只可以用於獲取電平,不能改變電平。
輸出是指IO口既可以改變電平,也可以獲取電平。


檢視配套的電路圖說明檔案(orangepi-plus-h3-v1_1.pdf):

LED是接PA15,當PA15輸出高電平時亮。
所以可以改變PA15為輸出,控制它輸出高低電平就可以控制led燈的亮滅。

可以在uboot上使用”mw”,”md”來配置或獲取IO口的電平:

mw.l 0x01c20804 0x10000000 1  //PA15口作輸出,即改變配置暫存器PA_CFG1(0x01c20804)的第28~30位的值為1

mw.l 0x01c20810 0x8000 1 //第15位的值為1,即PA組的第15個IO口輸出高電平,LED亮

mw.l 0x01c20810 0 1  //LED滅

通過C程式碼來控制LED燈迴圈亮滅(test.c):

typedef volatile unsigned int   u32;

#define     PA_CFG1     (*(u32 *)0x01c20804) //PA_CFG1_REG
#define     PA_DATA     (*(u32 *)0x01c20810) //PA_DATA_REG

void delay(int val);//延時函式宣告

//arm板的開始函式(相當於main函式)
void _start() 
{
    int i;

    PA_CFG1 &= ~(7 << 28);//PA15清零
    PA_CFG1 |= 1 << 28;//設定PA15作為輸出

    for (i = 0; i < 10; i++)
    {
        PA_DATA |= 1 << 15;//PA15高電平,LED亮
        delay(1000);
        PA_DATA &= ~(1<<15);//低電平,LED滅
        delay(1000);
    }

}

//延時函式
void delay(int val)
{
    val *= 0xffff;  //沒什麼目標,就是把延時的數變大點

    while (val--)
        ;
}

編譯:

arm-linux-gnueabihf-gcc test.c -c -o test.o -march=armv5
arm-linux-gnueabihf-ld test.o -o test
arm-linux-gnueabihf-objcopy -O binary test test.bin

將生成的test.bin下載到板上記憶體裡:

loady 0x40008000 //uboot就會進入等待狀態,等著接收資料"ctrl+a",鬆手後再按"s",選擇"ymodem",在彈出的介面裡按空格鍵選中要傳的檔案(test.bin)

執行:

go 0x40008000