11 裸板控制IO

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ForFuture_/article/details/79394027

裸板控制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

猜你喜欢

转载自blog.csdn.net/ForFuture_/article/details/79394027
11