一个引脚可以用于输入、输出或者其他的特殊功

关于驱动程序框架,请参考:嵌入式Linux驱动开发——字符设备驱动框架入门

之前的文章讨论了字符设备驱动的框架以及通过自负设备驱动程序来控制开发板上的LED嵌入式Linux驱动开发——字符设备驱动框架入门嵌入式Linux驱动开发——字符设备驱动之控制LED

  GPIO意思就是通用输入输出,一些引脚可以通过他们输出高低电平,或者通过它们读入引脚的状态。
对GPIO的操作是对所有硬件的操作最基本的技能。
一、通过寄存器来操作GPIO引脚,一个引脚可以用于输入、输出或者其他的特殊功能,那么一定有寄存器来配置这些功能,
对于输入,就是读取引脚的状态,一定可以从寄存器在中读取到引脚的状态;对于输出,也有相应的寄存器,向寄存器中
写入数据使引脚输出高低电平;其他特殊功能,有另外的寄存器来控制它。
对于S3C2440来说,同样的道理,也会有上面所说的寄存器,GPxCON用于配置引脚的功能的(输入、输出或其他功能),
GPxDAT用于读/写引脚数据;另外GPxUP用于是否使用内部上拉电阻。
1、GPxCON寄存器-配置寄存器
对于S3C2440,除了GPACON特殊外(寄存器每一位对应一个引脚),其它都是寄存器的没2位控制一根引脚:00表示输入,
01表示输出、10表示特殊、11保留不用。
2、GPxDAT寄存器
用于读/写引脚:当引脚被设为输入时,从GPxDAT寄存器读取引脚的状态;当引脚被设为输出时,将数据写入GPxDAT寄存器
相应的引脚会输出相应的该低电平。
3、GPxUP寄存器
某位为1时,相应引脚无内部上拉电阻;某位为0时,相应引脚使用上拉电阻。

同时,在这篇文章里面留下了两个问题,现在先来解决其中的第一个问题,就是如何用驱动程序来操作需要操作的硬件。

在这里我们可以简单的复习一下。首先,字符设备驱动程序的框架核心是file_operations结构体,其中注册上层应用和底层驱动程序的对应关系。正式通过这个结构体,应用层的write才能找到驱动程序中与之相对应的硬件操作的函数。如果这样理清了思路,就很容易看到,入口函数和出口函数的目的,就是告诉内核我们自己写的file_operations结构体的内容是啥,也就告诉内核上层和底层的映射关系是什么。

上拉电阻、下拉电阻的作用:GPIO为第三态时(相当于无外接芯片),引脚的电平状态有上拉电阻、下拉电阻确定。

关于开发板点亮LED的问题,在这里简单介绍一下,也可以参考之前我写的文章:嵌入式Linux开发——裸板程序点亮开发板上的LED灯首先为了操作硬件,看接线原理图是必不可少的一步,这几个LED的原理图相对来说比较简单,在这里说一下,如果需要看懂稍微复杂一点的原理图,可以参见:Linux嵌入式开发入门——看懂原理图

其次,对于控制LED来说,主要是对框架的实践,操作硬件的原理也很简单,主要是操作与之相对应的寄存器的值。而,驱动程序和单片机程序操作寄存器的区别在于,驱动程序操作的虚拟地址,而单片机程序操作的是物理地址,其核心的原理完全相同。

二、在开发板上实现LED亮灭及按键控制LED
目标:通过读写GPIO寄存器来驱动LED、获取按键状态。
第一个例子使用汇编编写一个简单的驱动LED的程序,点亮LED首先看原理图是怎么接的,拿到原理图手册

以下是LED的接线原理图:

那么我们通过了写入寄存器相应的数据,来完成了LED的控制,主要是建立了write的映射关系,那么在上层应用中,还有一个很常用的函数,就是read函数。我们应该如何做呢?

图片 1

图片 2LED的原理图

如果我们查看定义在fs.h文件中的file_operations结构体,可以看到其中有read属性,那么很自然的我们就能想到,用这个属性来映射他们之间的关系即可。

可以看到led被点亮开发板gpio需要低电平,找到对应的开发板gpio。一目了然GPF4为0时LED1亮,1时灭,但是一个GPIO管脚可以是输出也可以是输入,所以,要配置GPIO的功能。

看到上面的是开发板上面的三盏LED,在图上的左边,他们统一接到了3.3V的一个高电平上,那么如果在LED右侧为地,那么从左到右就可以形成电压差,因此,也就可以形成电流来点亮LED。

思路清晰明确!Let's go!

点亮led:
1、配置gpio的功能为输出,2、设置gpio输出高低
配置输出功能,在数据手册上可以看到一个寄存器GPFCON,GPF4对应的位【9:8】做出相应的配置,管脚的复用
设置寄存器在数据手册上可以看到一个寄存器GPFDAT,【7:0】,当是输出功能时一位对应功能寄存器的一个引脚。这样4位就对应GPF4了。
GPFCON地址0x56000050  GPFDAT地址0x56000054
下面是汇编写的点亮一个LED程序:

那么在LED右侧,引出三条线,这三条线根据接线原理图可以看出来接入到了下图的芯片中。

首先,我们阅读一下原理图,大致知道该硬件上面的按键是什么样的情况。下面是按键的接线原理图:

led_on.S

图片 3LED引脚对应的2440芯片引脚我们根据上面的两幅接线的原理图可以看出来,三盏LED都接在了这个芯片上,那么接下来就是需要我们来阅读一下这个芯片的手册了,看看如何来操作这些引脚。而我们需要的该引脚的状态应该是:输出低电平点亮LED,输出高电平熄灭LED。查看芯片手册:1. 对应引脚配置为输出引脚 2. 对应引脚输出低电平图片 42440芯片手册对应的GPF引脚信息

图片 5按键的原理图

.global _start  
_start:  
            LDR R0,= 0x56000050  @R0为GPFCON寄存器,此寄存器用于选择引脚的功能  
            MOV R1,#0x00000100     
            STR R1,[R0] @将数值写进寄存器里也就是配置了引脚的相应的功能  
            LDR R0,= 0x56000054 @R0为GPFDAT寄存器,此寄存器用于设置相应管脚的值,高低电平  
            MOV R1,#0x00000000   @设置相应管脚输出0电平,可让LED1灯亮  
            STR R1,[R0] @将数值写进寄存器里也就是设置了引脚的相应的输出电平  
MAIN_LOOP:  
                    B    MAIN_LOOP     @循环

根据芯片手册,找到对应引脚的部分,发现操作该引脚实际需要操作三个寄存器:GPFCONGPFDATGPFUP。其中配置输出引脚需要配置的是GPFCON寄存器,让寄存器中的数据的对应位保存01,即可设置为输出引脚;而操作GPFDAT寄存器中的对应位的数据为1/0,既可让该引脚输出高/低电平。所以我们控制对应的LED,实际上就是来控制2440芯片中的GPFCON和GPFDAT两个寄存器中的值。根据手册可以看到,这个两个寄存器的地址分别是0x5600 00500x5600 0054。我们是不是像单片机程序一样,直接来操作这个两个地址呢?实际不是的,在驱动程序的开发过程中,并不直接操纵这两个地址,而是操作这两个地址的映射。具体操作稍后详见代码。

通过接线原理图,很容易看到,如果当按键按下后,电路和地线相连,此时EINTx 的线上应该是低电平。如果这时候与对应的按键连线的引脚设置为输入引脚,我们只要检测出低电平就说明按键被按下了。思路有更加清晰了一步。

下面是相应的Makefile

PS: 写一个关于点亮LED的驱动,需要遵循一下结果步骤:

  • 搭建驱动的框架
  • 完善硬件操作的部分
    • 看懂原理图,确定引脚
    • 看芯片手册来确定如何操作引脚
  • 写代码(和单片机程序的区别为,驱动程序操作的是ioremap映射的虚拟地址,而非物理地址)

图片 6EINT0和EINT2图片 7EINT11图片 8EINT19

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

我们现在已经知道了驱动框架如何编写,同时根据硬件的原理图和芯片手册知道了该如何操作我们希望操作的硬件。那么接下来就是编写代码了。

参照原理图我们找到了与这几个按键连接的引脚,都是来自于2440芯片,接下来的事应该说比较明确了,就是查看2440手册,看看如何配置这几个引脚为输入引脚即可。

将生成的bin文件烧到开发板即可点亮LED。

我们驱动等下来完成,先确定我们希望如何来操作硬件,先把测试程序写完,然后再来完善驱动程序。假设使用驱动程序时,是通过测试程序 第一个led的控制参数 第二个led的控制参数 第三个led的控制参数,也就是./led 1 0 1代表的是第一盏灯和第三盏灯开,第二盏灯关的状态。

图片 9GPF芯片手册图片 10GPG芯片手册

本文由美高梅游戏网站登录发布于美高梅棋牌游戏,转载请注明出处:一个引脚可以用于输入、输出或者其他的特殊功

您可能还会对下面的文章感兴趣: