前言
本系列博客均是基于韦东山老师的《嵌入式Linux应用开发》书籍,因此对于一些内容有疑问的可以参考书籍也可以评论区讨论。
注意:因为原书籍是基于S3C2410芯片进行讲述,所以我们这里主要是理解其原理,对于不同的芯片应根据实际原理图进行改进。
一、GPIO硬件介绍
GPIO(Gerneral Purpose I/O Port)意思就是通用输入/输出端口。通俗的说,就是一些引脚,可以通过它输出高低电平或者通过它们读入引脚的状态——高/低电平。
S3C2410有117个I/O端口,共分为A~H组,对于不同的芯片端口的数量不同,划分组的方式也不同。因此实际情况要根据原理图进行归纳,切勿死记(有单片机基础的同学可以对比学习)。对于GPIO端口的操作,是通过访问寄存器的方式开控制某个引脚是输入还是输出,还是作为其他特殊功能(串口·)。
GPIO的操作是所有硬件操作的基础,由此扩展开来了解所有硬件的操作,这是底层人员必须掌握的。
二、通过寄存器操作GPIO引脚
既然一个引脚可以用于输入、输出、或其他功能,那么一定有一个寄存器用来选择这些功能(control);对于输入,一定可以通过读取某个寄存器来确定引脚是高电平还是低电平(Data);对于输出,一定可以通过写入某个寄存器让这个引脚输出高电平/低电平(Data);对于其他特俗功能,则有另外的寄存器来控制它
1.GPxCON寄存器
从这个寄存器的名字可以看出,GP表示是一个GPIO口,x表示是哪个组,CON表示contro,用于控制选择输出/输出/特殊功能(你也可以理解为Configure 配置) PORTA与PORTB~PORTH/J在功能选择方面有所不同,GPACON中每一位对应一根引脚(一共23根)。当某位被设为0时,相应引脚问输出引脚,此时我们可以在GPADAT中相应位写入0或1让此引脚输出低电平/高电平;当CPACON中某位被设为1时,相应引脚为地址线或用于地址控制,此时CPADAT就无效。因此一般而言GPACON通常被设为1,以便访问外部存储器件。(这仅限于PORTA)
对于PORTB~PORTH/J寄存器操作完全相同。每两位控制一个引脚: 00:表示输入 01:表示输出 10:表示特殊功能 11:保留不用
GPxDAT寄存器
从单词意思上看,DAT就是表示对引脚操作的数据了。 GPxDAT用于读/写引脚;当引脚被设为输入时,读此寄存器可知相应引脚的状态是高电平还是低电平;当引脚被设置为输出时,写此寄存器可控制引脚输出高电平/低电平
GPxUP寄存器
CPxUP:某位为1时,相应引脚无内部上拉电阻;为0时,相应引脚使用内部上拉电阻。如下图 所谓上拉电阻,下拉电阻。是在端口处外接电阻。其目的是为了控制端口处的初始值。就是说,当GPIO引脚处于第三态(既不是输出高电平,也不输出低电平,而是高阻态,相当于没有接芯片)时,它的电平状态由上拉电阻,或下拉电阻确定(具体的使用会在后面对按键的操作进行分析)
特别说明:其实对于寄存器的访问和操作除了我们前面介绍的通过地址直接访问外,还可以通过总线的方式进行访问,但是这里就不介绍了,有兴趣的同学可以翻阅书籍
2.GPIO操作实例:点亮一个LED
LED原理图
使用汇编代码点亮一个LED
汇编代码
.text @伪代码text表示下面的内容为代码段
.global_start @伪代码用于将标号为start的程序定义为全局
_start: @伪代码程序编号
LDR R0 , =0X56000010 @R0设为GPBCON寄存器,此寄存器用于选择端口B的功能
MOV R1 , #0X00000400
STR R1 , [R0] @设置GPB5为输出口,位[10:9]=0b01
LDR R0 ,=0X56000014 @R0设为GPBDAT寄存器,用于控制输出数据
MOV R1 ,#0X0000000000 @设置R1寄存器的值位0
STR R1,[R0] @将R1的写入寄存器中,使GPB5输出低电平,则LED灯亮
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 0x00000000 -g led_on.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
C语言程序
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
int main()
{
GPBCON =0x00000400;
GPBDAT =0x000000000;
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 0x00000000 -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
总结
希望上面的内容能让你对GPIO的操作有新的认识!
|