MQ-2烟雾气敏传感器模块在X210v3开发板上的驱动。
现在需要一个MQ-2烟雾气敏传感器模块的驱动。其检测烟雾超过一定的标准后,会返回一个不同的电平,和按键驱动差不多。
但是在编写驱动的时候,需要用GPH2_3号引脚。但是在内核中先ioremap地址然后配置,发现无法控制gpio,也无法进入中断。
后来发现,如果需要使用gpio,需要先申请,然后才能使用。
具体程序如下:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <asm/irq.h>
#include <linux/random.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <mach/gpio.h>
#define GPH2CON 0xE0200c60
#define GPH2DAT 0xE0200c64
static struct class *fog_class; //创建类
static struct class_device *fog_class_devs; //创建类对应的设备
struct work_struct *work1;
struct timer_list fogs_timer;
unsigned int *gpio_data;
unsigned int fog_num = 0;
wait_queue_head_t fog_q;
void work1_func(struct work_struct *work)
{
mod_timer(&fogs_timer, jiffies + (HZ /10));
}
void fogs_timer_function(unsigned long data)
{
unsigned int fog_val;
fog_val = readw(gpio_data)&0x08;
if (fog_val == 0)
{
fog_num = 1;
printk("press down\n");
}
wake_up(&fog_q);
}
irqreturn_t fog_int(int irq, void *dev_id)
{
schedule_work(work1);
//return 0;
return IRQ_HANDLED;
}
void fog_hw_init()
{
unsigned int *gpio_config;
unsigned short data;
gpio_request(S5PV210_GPH2(3),"my_fog");
gpio_config = ioremap(GPH2CON,4);
data = readw(gpio_config);
data &= ~(0b1111<<12);
data |= 0b1111<<12;
writew(data,gpio_config);
gpio_data = ioremap(GPH2DAT,1);
}
int fog_open(struct inode *node,struct file *filp)
{
return 0;
}
ssize_t fog_read(struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
wait_event(fog_q,fog_num);
// printk("in kernel :fog num is %d\n",fog_num);
copy_to_user(buf, &fog_num, 4);
fog_num = 0;
return 4;
}
struct file_operations fog_fops =
{
.open = fog_open,
.read = fog_read,
};
struct miscdevice fog_miscdev = {
.minor = 200,
.name = "fog",
.fops = &fog_fops,
};
int major;
static int fog_init()
{
int ret;
major = register_chrdev( 0,"fog_drv", &fog_fops );
fog_class = class_create(THIS_MODULE,"fog_class");
fog_class_devs = device_create(fog_class,NULL,MKDEV(major,0),NULL,"my_fog");
if (ret !=0)
printk("register fail!\n");
//×¢²áÖжώŠÀí³ÌÐò
request_irq(IRQ_EINT(27),fog_int,IRQF_TRIGGER_FALLING,"fog",0);
//°ŽŒü³õÊŒ»¯
fog_hw_init();
//. ŽŽœš¹€×÷
work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);
INIT_WORK(work1, work1_func);
/* ³õÊŒ»¯¶šÊ±Æ÷ */
init_timer(&fogs_timer);
fogs_timer.function = fogs_timer_function;
/* ÏòÄÚºË×¢²áÒ»žö¶šÊ±Æ÷ */
add_timer(&fogs_timer);
/*³õÊŒ»¯µÈŽý¶ÓÁÐ*/
init_waitqueue_head(&fog_q);
return 0;
}
static void fog_exit()
{
del_timer(&fogs_timer);
unregister_chrdev( major, "fog_drv" );
device_unregister(fog_class_devs);
class_destroy(fog_class);
}
module_init(fog_init);
module_exit(fog_exit);
MODULE_LICENSE("GPL");