LINUX 操作GPIO口

两种方法

1、写驱动的方式

2、通过linux提供的用户空间

终端控制

通过在用户空间上来操作GPIO,控制入口在:/sys/class/gpio/。

首先确认内核里是否已选择上gpiolib的sysfs接口功能(默认是已选择上的)

make kernel_menuconfig      
	->Device Drivers->GPIO Support
		->/sys/class/gpio/... (sysfs nterface)。

在linux内核源码里gpio口对应的序号,这个是由芯片厂家自定义的,通常在”arch/arm/mach-xxx/include/mach/gpio.h”里.
h3的gpio口定义在”arch/arm/mach-sunxi/include/mach/gpio.h”

#define SUNXI_BANK_SIZE 32
#define SUNXI_PA_BASE   0
#define SUNXI_PB_BASE   32
#define SUNXI_PC_BASE   64
#define SUNXI_PD_BASE   96
#define SUNXI_PE_BASE   128
#define SUNXI_PF_BASE   160
#define SUNXI_PG_BASE   192
#define SUNXI_PH_BASE   224
#define SUNXI_PI_BASE   256
#define SUNXI_PJ_BASE   288
#define SUNXI_PK_BASE   320
#define SUNXI_PL_BASE   352
#define SUNXI_PM_BASE   384
#define SUNXI_PN_BASE   416
#define SUNXI_PO_BASE   448
#define AXP_PIN_BASE    1024

#define SUNXI_PIN_NAME_MAX_LEN  8

/* pin group base number name space,
 * the max pin number : 26*32=832.
 */
#define SUNXI_PINCTRL 	"sunxi-pinctrl"
#define SUNXI_BANK_SIZE 32
#define SUNXI_PA_BASE	0
#define SUNXI_PB_BASE	32
#define SUNXI_PC_BASE	64
#define SUNXI_PD_BASE	96
#define SUNXI_PE_BASE	128
#define SUNXI_PF_BASE	160
#define SUNXI_PG_BASE	192
#define SUNXI_PH_BASE	224
#define SUNXI_PI_BASE	256
#define SUNXI_PJ_BASE	288
#define SUNXI_PK_BASE	320
#define SUNXI_PL_BASE	352
#define SUNXI_PM_BASE	384
#define SUNXI_PN_BASE	416
#define SUNXI_PO_BASE	448
#define AXP_PIN_BASE	1024

#define SUNXI_PIN_NAME_MAX_LEN	8

/* sunxi gpio name space */
#define GPIOA(n)	(SUNXI_PA_BASE + (n))
#define GPIOB(n)	(SUNXI_PB_BASE + (n))
#define GPIOC(n)	(SUNXI_PC_BASE + (n))
#define GPIOD(n)	(SUNXI_PD_BASE + (n))
#define GPIOE(n)	(SUNXI_PE_BASE + (n))
#define GPIOF(n)	(SUNXI_PF_BASE + (n))
#define GPIOG(n)	(SUNXI_PG_BASE + (n))
#define GPIOH(n)	(SUNXI_PH_BASE + (n))
#define GPIOI(n)	(SUNXI_PI_BASE + (n))
#define GPIOJ(n)	(SUNXI_PJ_BASE + (n))
#define GPIOK(n)	(SUNXI_PK_BASE + (n))
#define GPIOL(n)	(SUNXI_PL_BASE + (n))
#define GPIOM(n)	(SUNXI_PM_BASE + (n))
#define GPION(n)	(SUNXI_PN_BASE + (n))
#define GPIOO(n)	(SUNXI_PO_BASE + (n))
#define GPIO_AXP(n)	(AXP_PIN_BASE  + (n))

gpio口的操作过程,如控制status-led(接在PA15)的亮灭.

1 让gpiolib导出PA15的控制文件. 可根据上面检出PA15引脚对应的gpio口序号为15

echo 15 > /sys/class/gpio/export

操作完成后,应会在/sys/class/gpio/目录下生成一个gpio15的子目录.

2 在/sys/class/gpio/gpio15目录有文件:

 /mnt/kernel_coding # ls /sys/class/gpio/gpio15/
    active_low  direction  edge   value
    
   //通过direction文件可控制gpio口是作输入或输出功能
    // echo "high" > /sys/class/gpio/gpio15/direction   是让gpio口作输出,并输出高电平
    // echo "out"  > /sys/class/gpio/gpio15/direction   是作输出功能,并输出低电平
    // echo "in"   > /sys/class/gpio/gpio15/direction   是作输入功能
   //通过value文件可以获取和控制gpio口的电平(当gpio口作输出时,可以通过写操作改变电平。当作输入时,可以通过读操作获取电平) 
    // echo "1" > /sys/class/gpio/gpio15/value    让gpio口输出高电平
    // echo "0" > /sys/class/gpio/gpio15/value    让gpio口输出低电平
   //通过edge文件, 可以指定gpio作中断功能,并指定它的触发电平和获取. 触发电平方式有("none", "falling", "rising", "both")

   //通过active_low文件,可以指定往value文件写1时为有效电平.
    如: echo "1" > /sys/calss/gpio/gpio15/value时是输出高电平的
       当echo "1" > /sys/calss/gpio/gpio15/active_low后, 再往value写1是就是输出低电平了.

代码中控制


int init_gpio_export(int gpio)
{
	FILE *p = NULL;

	p = fopen(GPIO_EXPORT_PATH, "w");
	if(p == NULL)
	{
		GPIO_KEY_DEBUG("gpio%d init_gpio_key_export error!!\n", gpio);
	}
	else
	{
		fprintf(p, "%d", gpio);
		fclose(p);
	}

	return 0;
}

int set_gpio_direction(int gpio, int direction)
{
	FILE *p = NULL;
	char gpio_direction_path[50];

	sprintf(gpio_direction_path, GPIO_DIRECTION_PATH, gpio);
	p = fopen(gpio_direction_path, "w");
	if(p != NULL)
	{
		if(direction == DIRECTION_IN)
		{
			fprintf(p, "in");
		}
		else
		{
			fprintf(p, "out");
		}
		
		fclose(p);
	}
	else
	{
		GPIO_KEY_DEBUG("gpio%d set_gpio_direction error", gpio);
	}
	
	return 0;
}

int set_gpio_value(int gpio, int value)
{
	FILE *p = NULL;
	char gpio_value_path[50];

	sprintf(gpio_value_path, GPIO_VALUE_PATH, gpio);
	p = fopen(gpio_value_path, "w");

	if(p != NULL)
	{
		fprintf(p, "%d", value);
		fclose(p);
	}

	return 0;
}

int get_gpio_value(int gpio)
{
	FILE *p = NULL;
	char gpio_value_path[50];
	char i[100]={0,};
	int value = 1;

	sprintf(gpio_value_path, GPIO_VALUE_PATH, gpio);
	p = fopen(gpio_value_path, "r");

	if(p != NULL)
	{
		fseek(p , 0 , 0);
		fread(i , 1, 1 ,p);
		//GPIO_KEY_DEBUG("gpio state = %c \r\n",i[0]);

		if(i[0] == '0')
		{
			value = 0;
		}
		else
		{
			value = 1;
		}
		/*Note that you must close it here, then re-open it when you read it again, 
		so that only the content will be updated.*/
		fclose(p);
	}
	else
	{
		value = -1;
		GPIO_KEY_DEBUG("gpio%d get_gpio_value value failed\n", gpio);
	}
	
	return value;
}
发布了63 篇原创文章 · 获赞 32 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/hushiganghu/article/details/88722223