基于全志芯片的GPIO及底层(C/Python)编程

来源:互联网 发布:微信js获取地理位置 编辑:程序博客网 时间:2024/06/18 03:55

目标环境:搭载A20芯片的核心板Cubieboard2,使用522扩展板,用TF卡搭载cb2-dvk-sdcard-ubuntu-desktop-lcd-ctp-lvds-1024x600-v1.1.img系统 
管脚图:http://docs.cubieboard.org/cubieboard1_and_cubieboard2_gpio_pin 

GPIO是General Purpose Input/Output的简写,通用输入输出接口。GPIO是一种泛指,几乎所有MCU芯片都有GPIO。包括UART/SPI等接口管脚,也是一种GPIO。在中文上,我觉得用“输入输出管脚”的说法比较合适。。既然GPIO与硬件相关,那么必然厂家需要提供支持。 

全志芯片的GPIO,由运行其上的Linux版本:linux-sunxi提供直接支持。可以用过两种方式操作GPIO。 
一、设置linux-sunxi启动脚本配置文件,开启系统对gpio的支持,然后通过echo指令进行操作。优点:不用编程;缺点:改系统配置文件,重启系统后生效; 
二、使用sunxi的相关驱动(C、python等)。优点:不论系统配置文件是否声明,均可操作;缺点:C语言需要编译对应系统的二进制文件。(Python可以绕开) 

方法一、通过脚本配置文件和Linux指令操作GPIO 
linux-sunxi有个配置文件script.bin,在系统启动时,通过该配置文件来设置全志芯片的各个管脚和操作参数。修改script.bin需要使用全志提供工具sunxi-tools。通过sunxi-tools将script.bin文件转换为script.fex文本文件,修改script.fex文件之后,再用sunxi-tools将其转换为script.bin文件,重启系统。系统将会开放对应设置的GPIO。我们常在各种文章看到“修改script.fex文件“,就是指这个。实际上,script.fex中,不仅仅只有对GPIO配置的声明。可参看全志资料: 
Fex Guide:http://linux-sunxi.org/Fex_Guide#.5Bgpio_para.5D 
GPIO:http://linux-sunxi.org/GPIO 

1、script.bin在什么位置? 
根据系统启动的方式不同,其位置不同: 
1)TF启动: 
/dev/目录下的mmcblk0p1包含uEnv.txt 、 script.bin和uImage;mmcblk0p2 是文件系统。挂载相应目录,可执行以下命令: 

$mkdir /mnt/mmp1   

$mkdir /mnt/mmp2   

$mount /dev/mmcblk0p1 /mnt/mmp1   

$mount /dev/mmcblk0p2 /mnt/mmp2   

2)Nand启动: 
/dev/目录下的nanda 包含boot.ini、sprite.axf、uEnv.txt、script.bin 和uImage 等;nandb 是文件系统。挂载相应目录,执行命令: 

$mkdir /mnt/nanda   

$mkdir /mnt/nandb   

$mount /dev/nanda /mnt/nanda   

$mount /dev/nandb /mnt/nandb 

2、对script.bin操作 
script.bin 为二进制文件,不可以直接更改,需要通过 bin2fex命令转换为 script.fex。 script.fex为文本格式,可以直接更改。更改后, 再通过fex2bin命令把script.fex转换成script.bin。 如果没有 bin2fex 和 fex2bin 命令,需要安装,在终端输入相应命令: 

apt-get install git   

git clone git://github.com/linux-sunxi/sunxi-tools.git

通过该命令,会在当前目录下得到安装文件 sunxi-tools。

cd sunxi-tools/   

apt-get install make  

apt-get install gcc   

apt-get install libusb-1.0   

make   

sunxi-tools 目录下会产生 fex2bin 与 bin2fex两个工具。 把它们拷贝到/usr/bin目录下。 

cp fex2bin bin2fex /usr/bin/  
相应的转换操作如下: 

fex2bin script.fex script.bin   bin2fex script.bin script.fex   
修改script.fex 需要使用 vim,执行以下命令安装: 

apt-get install vim  

3、修改script.fex中 

[gpio_para]  gpio_used = 1  gpio_num = 5  gpio_pin_1 = port:PH20<1><1>  gpio_pin_2 = port:PH21<1><1>  gpio_pin_3 = port:PH07<6>  gpio_pin_4 = port:PE10<1><0>  gpio_pin_5 = port:PE11<1><0>  

说明: 
1)script.fex中要按规定声明节段名,gpio是:[gpio_para] 
2)script.fex中采用key=value的形式进行配置; 
3)gpio_used:用于声明是否使用gpio,1标识使用,0标识不使用; 
4)gpio_num:使用gpio的数量 
5)gpio_pin_N=port: 
:端口编号 
:0标识输入;1标识输出;2-7根据不同芯片定义不同; 
:0标识无效disabled;1标识“上升沿”有效;2标识“下降沿”有效;(仅当作为输入管脚时有用);default标识该选项采用默认值,可忽略; 
:标识输出管脚的驱动能力(mA),0-3分别代表10mA、20mA、30mA和40mA;default标识该选项采用默认值,可忽略; 
:标识输出管脚的初始电平,1标识高电平,0标识低电平(仅当作为输出管脚时有用);default标识该选项采用默认值,可忽略; 
其中,PH20是核心板上的绿灯,PH21是核心板上的红灯,PE10和PE11是522扩展板上已经外接好的LED测试排灯。总共有8个,接核心板的PE4~PE11管脚。 

4、将script.fex转换为script.bin并重启系统 

fex2bin script.fex script.bin  

reboot  

5、启动好之后,用linux的echo指令打开系统对gpio的映射,对应我们新配置的script.fex,就是第4号和5号两个管脚: 

root@cubieboard2:/# echo 4 > /sys/class/gpio/export  

root@cubieboard2:/# echo 5 > /sys/class/gpio/export 

然后我们就可以看到系统赋予的gpio名称: 

root@cubieboard2:/# ls sys/class/gpio  export  gpio4_pe10  gpio5_pe11  gpiochip1  unexport 

操作gpio的势能方向: 

root@cubieboard2:/# echo out > /sys/class/gpio/gpio4_pe10/direction  

root@cubieboard2:/# echo out > /sys/class/gpio/gpio4_pe11/direction

操作gpio控制led灯的亮灭: 

root@cubieboard2:/# echo 1 > /sys/class/gpio/gpio4_pe10/value  

root@cubieboard2:/# echo 0 > /sys/class/gpio/gpio4_pe10/value  

方法二、使用sunxi的相关驱动(C、python等) 
附件分别是C和py的库文件。 

1、C语言示例代码(只使用gpio_lib.c和gpio_lib.h): 

#include 

#include 

#include "gpio_lib.h"  

#define PE5    SUNXI_GPE(5)  

#define PE8    SUNXI_GPE(8)  

#define PE9    SUNXI_GPE(9)  

#define PE10   SUNXI_GPE(10)  

#define PE11   SUNXI_GPE(11)  

int main()  

{  

    if(SETUP_OK!=sunxi_gpio_init()){  

        printf("Failed to initialize GPIO\n");  

        return -1;  

    }  

    if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE5,OUTPUT)){  

        printf("Failed to config GPIO PE5 pin\n");  

        return -1;  

    }  

    if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE8,OUTPUT)){  

        printf("Failed to config GPIO PE8 pin\n");  

        return -1;  

    }  

    if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE9,OUTPUT)){  

        printf("Failed to config GPIO PE9 pin\n");  

        return -1;  

    }  

    if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE10,OUTPUT)){  

        printf("Failed to config GPIO PE10 pin\n");  

        return -1;  

    }  

    if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE11,OUTPUT)){  

        printf("Failed to config GPIO PE11 pin\n");  

        return -1;  

    }  

    while(1){  

        if(sunxi_gpio_output(PE5,HIGH)){  

            printf("Failed to set GPIO PE5 pin value\n");  

            return -1;  

        }  

        usleep(500000);  

        if(sunxi_gpio_output(PE5,LOW)){  

            printf("Failed to set GPIO PE5 pin value\n");  

            return -1;  

        }  

        usleep(500000);  

        if(sunxi_gpio_output(PE8,HIGH)){  

            printf("Failed to set GPIO PE8 pin value\n");  

            return -1;  

        }  

        usleep(500000);  

        if(sunxi_gpio_output(PE8,LOW)){  

            printf("Failed to set GPIO PE8 pin value\n");  

            return -1;  

        }  

        usleep(500000);  

        if(sunxi_gpio_output(PE9,HIGH)){  

            printf("Failed to set GPIO PE9 pin value\n");  

            return -1;  

        }  

        usleep(500000);  

        if(sunxi_gpio_output(PE9,LOW)){  

            printf("Failed to set GPIO PE9 pin value\n");  

            return -1;  

        }  

        usleep(500000);  

        if(sunxi_gpio_output(PE10,HIGH)){  

            printf("Failed to set GPIO PE10 pin value\n");  

            return -1;  

        }  

        usleep(500000);  

        if(sunxi_gpio_output(PE10,LOW)){  

            printf("Failed to set GPIO PE10 pin value\n");  

            return -1;  

        }  

        usleep(500000);    

        if(sunxi_gpio_output(PE11,HIGH)){  

            printf("Failed to set GPIO PE11 pin value\n");  

            return -1;  

        }  

        usleep(500000);  

        if(sunxi_gpio_output(PE11,LOW)){  

            printf("Failed to set GPIO PE11 pin value\n");  

            return -1;  

        }  

        usleep(500000);  

    }    

    sunxi_gpio_cleanup();  

    return 0;  


可以在目标操作系统上直接编译: 

$sudo apt-get install gcc build-essential  

$tar -xf gpio.tar  $cd gpio/  $gcc gpio_lib.c -c  

$gcc gpio.c -c  $gcc gpio.o gpio_lib.o -o gpio  

$./gpio  

也可以搭建交叉编译环境来编译: 

$arm-linux-gnueabi-gcc  gpio_lib.c  gpio.c -static -o gpio  

$./gpio  

2、python代码示例 
配置python 

sudo apt-get install python-dev  wget http://dl.linux-sunxi.org/users/tom/pySUNXI-0.1.12.tar.gz  tar zxf pySUNXI-0.1.12.tar.gz  sudo python setup.py install  

新建一个blink.py文件 

#!/usr/bin/env python  

import SUNXI_GPIO as GPIO  

import time    

RED_LED = GPIO.PE11    

GPIO.init()  

GPIO.setcfg(RED_LED, GPIO.OUT)        

while True:  

        GPIO.output(RED_LED, GPIO.HIGH)  

        time.sleep(1)  

        GPIO.output(RED_LED, GPIO.LOW)  

        time.sleep(1)  

运行代码: 

chmod +x blink.py  sudo ./blink.py  

顺便补充一下,经过测试,本例中A20搭载的是ubuntu的一个精简版linaro 12.09。示例中交叉编译好的C语言执行文件,同样可以在cb2-dvk-nand-android-4.2.2-lcd-ctp-lvds-1024x600-v1.1.img中执行。

0 0