ARM开发之用linux通用GPIO接口宏函数操作IO口-----LED字符驱动为例

ARM开发板:S5PV210


驱动步骤:

1.定义一个cdev设备结构体变量

2.给cdev申请设备号

3.定义一个文件操作集

4.设备初始化

5.注册设备进内核

6.申请GPIO口


GPIO相关函数接口:

1.gpio_request(引脚,给引脚的名字)   ----申请GPIO口

第一个参数

在内核代码 \arch\arm\mach-s5pv210\include\mach\gpio.h 中有定义,如下图(部分)

ARM开发之用linux通用GPIO接口宏函数操作IO口-----LED字符驱动为例_第1张图片

如GPJ2寄存器的第一个引脚,就是 S5PV210_GPJ2(0)


第二个参数

为管脚起一个名字而已。

例如:

申请GPJ2CON的第一个管脚,并取名为GPJ2_0:

gpio_request(S5PV210_GPJ2(0),"GPJ2_0");;



2.gpio_free(引脚)  ----释放引脚

既然有 gpio_request来申请引脚,那用完了就要释放掉。释放引脚用函数 gpio_free

例如:

释放GPJ2_0引脚:gpio_free(S5PV210_GPJ2(0));


3.gpio_direction_output(引脚,0/1)   ----给引脚置0或1,并把引脚设置为输出模式

例如:

给引脚GPJ2_0设置为输出模式,并置1:gpio_direction_output(S5PV210_GPJ2(0),1);

返回值:失败返回负值



4.gpio_direction_intput(引脚)   ----给引脚设置成输入模式

例如:

给GPJ2_0 设置成输入模式:gpio_direction_input(SPPV210_GPJ2(0));



5.gpio_set_value(引脚,0/1)   ----给引脚置0或1

例如:

给引脚GPJ2_0设置为1(高电平):gpio_set_value(S5PV210_GPJ2(0),1);

返回值:失败返回负值




6.gpio_get_value(引脚)   ----获取引脚的电平。看是0还是1

例如:

获取GPJ2_0 的电平: int  ret;ret = gpio_get_value(S5PV210_GPJ2(0));



下面给出驱动代码和应用程序代码:(实现Led灯轮流闪烁)

#include 
#include 	//for printk
#include 		//for cdev_init, cdev_add..
#include 		//alloc_chrdev_region..
#include 	//copy_to_user..
#include 	//request_mem_region
#include 
#include 	//for class, device
#include 		//for gpio

/*1.定义设备结构体*/
static struct cdev led_cdev;
static dev_t dev_num;
static char *gpio_name[]={"GPJ20","GPJ21","GPJ22","GPJ23"};
static struct class *led_class = NULL;
static struct device *led_device = NULL;
static char wbuf[1]={0};


static int led_open(struct inode *inode, struct file *f)
{
	int i;
	printk("led open\n");
	for(i=0;i<4;i++)
	{
		gpio_direction_output(S5PV210_GPJ2(i),1);
	}
	return 0;
}

void led_up(char i)
{
	char j;
	int k = i-'0';
	printk("GET[%c]\n",i);
	printk("GET[%d]\n",k);
	for(j=0;j<4;j++)
	{
		gpio_set_value(S5PV210_GPJ2(j),1);
	}
	gpio_set_value(S5PV210_GPJ2(k),0);
}

static ssize_t led_write(struct file *f, const char __user*buf,
	 size_t len, loff_t *t)
{
	copy_from_user(wbuf,buf,len);
	if(wbuf[0]=='0')
	{
		led_up(wbuf[0]);
	}

	if(wbuf[0]=='1')
	{
		led_up(wbuf[0]);
	}

	if(wbuf[0]=='2')
	{
		led_up(wbuf[0]);
	}

	if(wbuf[0]=='3')
	{
		led_up(wbuf[0]);
	}
	return 0;
}

/*3.定义文件操作集*/
static const struct file_operations fops={
	.owner = THIS_MODULE,
	.open = led_open,
	.write = led_write,
};


static int __init led_init(void)
{
	int ret;
	int i;
/*2.申请设备号*/
	ret = alloc_chrdev_region(&dev_num,0,1,"led");
	if(ret<0)
	{
		printk("failed to register dev num\n");
		goto failed_register;
	}

/*4.字符设备的初始化*/
	cdev_init(&led_cdev,&fops);
/*5.注册设备*/
	ret = cdev_add(&led_cdev,dev_num,1);
	if(ret<0)
	{
		printk("failed to add cdev\n");
		goto failed_add;
	}

/*6.申请IO口*/
	for(i=0;i<4;i++)
	{
		ret = gpio_request(S5PV210_GPJ2(i),gpio_name[i]);
		if(ret<0)
		{
			printk("failed to request GPIO\n");
			goto failed_request_IO;
		}
	}
/*7.创建设备类*/
	led_class = class_create(THIS_MODULE,"led_class");
	if(led_class == NULL)
	{
		printk("failed to create class\n");
		goto failed_create_class;
	}
/*创建设备文件结点*/
	led_device = device_create(led_class,NULL,dev_num,NULL,"led_dev");
	if(led_device == NULL)
	{
		printk("failed to create device\n");
		goto failed_create_device;
	}
	printk("init completed\n");
	return 0;

failed_create_device:
	class_destroy(led_class);
failed_create_class:
failed_request_IO:
	while(i--)
		{gpio_free(S5PV210_GPJ2(i));}
	cdev_del(&led_cdev);
failed_add:
	unregister_chrdev_region(dev_num,1);
failed_register:
	return -1;
}

static void __exit led_exit(void)
{
	device_destroy(led_class,dev_num);	
	class_destroy(led_class);
		
	gpio_free(S5PV210_GPJ2(3));	
	gpio_free(S5PV210_GPJ2(2));
	gpio_free(S5PV210_GPJ2(1));
	gpio_free(S5PV210_GPJ2(0));

	cdev_del(&led_cdev);					
	unregister_chrdev_region(dev_num,1);	
	printk("led uninstall!\n");
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

应用程序:

#include 
#include 

int main()
{
	char buf[1];
	char i;

	int fd = open("/dev/led_dev",O_WRONLY);
	if(fd<0)
	{
		perror("failed to open");
		return -1;
	}
	while(1)
	{
		for(i='0';i<'4';i++)
		{
			buf[0]=i;
			write(fd,buf,1);
			sleep(1);
		}
	}
	return 0;
}


1.gpio_direction_output(引脚,0/1)   ----给引脚置0或1,并把引脚设置为输出模式

你可能感兴趣的:(#,ARM开发)