GPIO全称: General-Purpose Input/Output(通用输入输出),是一种软件运行期间能够动态配置和控制的通用引脚。在RK平台上,除了部分有专门用途的pin(比如DDR、MIPI等),其他的pin,如果不配置复用的话,默认复用状态都是GPIO。RK的GPIO驱动,对上提供的是Linux下标准的GPIO接口。Linux下有一组用户态操作GPIO的sysfs节点。应用层对GPIO编程主要就是通过操作这几个节点来实现。
下面以操作GPIO1_A4和GPIO1_A7为例进行介绍。这两个GPIO位置如下
测试时将这两个脚短接,如下图所示
“/sys/class/gpio” 下面的节点需要root权限才能操作,使用命令行或者C语言编译出来的程序操作gpio都需要root权限。如果是ssh或者使用LX终端的,先执行如下命令获取root权限。
sudo su
在通用的Linux框架下面,所有GPIO都是用数字编号的。对于RK平台的芯片,其编号计算方式为
(gpio控制器号-0)*32+(端口号-‘A’)*8+索引序号
GPIO1_A4的控制器号为1,端口号为A,索引序号4,故编号为
(1-0) * 32 + 0 * 8 + 4 = 36
同理GPIO1_A7的编号为39
将GPIO36 GPIO39设置为用户态操作
echo 36 > /sys/class/gpio/export
echo 39 > /sys/class/gpio/export
将GPIO36设置为输出 将GPIO39设置为输入
echo out > /sys/class/gpio/gpio36/direction
echo in > /sys/class/gpio/gpio39/direction
在GPIO36为输出的情形下,设置电平
在GPIO39为输入的情形下,读取其电平,1为高,0为低
GPIO36输出高电平,读取GPIO39电平
echo 1 > /sys/class/gpio/gpio36/value
cat /sys/class/gpio/gpio39/value
GPIO36输出低电平,读取GPIO39电平
echo 0 > /sys/class/gpio/gpio36/value
cat /sys/class/gpio/gpio39/value
取消GPIO36 GPIO39用户态操作
echo 36 > /sys/class/gpio/unexport
echo 39 > /sys/class/gpio/unexport
上述操作流程的结果如下图
通过连接 libperipheral_api.a 静态库,可以使用C语言调用以下接口来操作GPIO
typedef enum {
PIN_DIRECTION_IN = 0,
PIN_DIRECTION_OUT = 1
} Enum_PinDirection;
/**
* @name: user_gpio_init
* @description: 将某个pin配置为gpio
* @param pin_num: 引脚号
* @return 等于0 - 成功 小于0 - 失败
*/
int user_gpio_init(int pin_num);
/**
* @name: user_gpio_deinit
* @description: 将某个pin释放
* @param pin_num: 引脚号
* @return 等于0 - 成功 小于0 - 失败
*/
int user_gpio_deinit(int pin_num);
/**
* @name: user_gpio_set_level
* @description: 设置gpio电平
* @param pin_num: 引脚号
* @param level: 电平 0 - 低 1- 高
* @return 等于0 - 成功 小于0 - 失败
*/
int user_gpio_set_level(int pin_num, unsigned char level);
/**
* @name: user_gpio_get_level
* @description: 获取gpio电平
* @param pin_num: 引脚号
* @param level: 电平 0 - 低 1- 高
* @return 等于0 - 成功 小于0 - 失败
*/
int user_gpio_get_level(int pin_num, unsigned char *level);
/**
* @name: user_gpio_set_direction
* @description: 设置gpio方向
* @param pin_num: 引脚号
* @param direction: PIN_DIRECTION_IN - 输入 PIN_DIRECTION_OUT - 输出
* @return 等于0 - 成功 小于0 - 失败
*/
int user_gpio_set_direction(int pin_num, unsigned char direction);
/**
* @name: user_gpio_get_direction
* @description: 获取gpio方向
* @param pin_num: 引脚号
* @param direction: PIN_DIRECTION_IN - 输入 PIN_DIRECTION_OUT - 输出
* @return 等于0 - 成功 小于0 - 失败
*/
int user_gpio_get_direction(int pin_num, unsigned char *direction);
#include "peripheral_api.h"
void gpio_api_test(void)
{
unsigned char level = 0;
user_gpio_init(36);
user_gpio_init(39);
user_gpio_set_direction(36, PIN_DIRECTION_OUT);
user_gpio_set_direction(39, PIN_DIRECTION_IN);
user_gpio_set_level(36, 1);
user_gpio_get_level(39, &level);
printf("1.pin 39 level %d\n", level);
usleep(10);
user_gpio_set_level(36, 0);
user_gpio_get_level(39, &level);
printf("2.pin 39 level %d\n", level);
user_gpio_deinit(36);
user_gpio_deinit(39);
return;
}
int main()
{
gpio_api_test();
return 0;
}
将peripheral_api.a静态库、peripheral_api.h和测试demo源码test.c放到同一路径下,编译命令如下
aarch64-none-linux-gnu-gcc test.c peripheral_api.a -I. -o gpiotest
运行结果如下