跳到主要内容位置

人体红外传感器SR501

6ull上使用GPIO4_19,具体模块说明可以查看《03_i.MX.6ULL裸机开发手册_V1.0》。

  • 感应到人体并输出高电平后,延时时间一结束,输出将自动从高电平变为低电平
  • 感应到人体后输出高电平后,在延时时间段内,如果有人体在其感应范围内活动,其输出将一直保持高电平,直到人离开后才延时将高电平变为低电平

编程

定义gpio:

/* gpio描述结构体 */
struct gpio_desc{
int gpio; //引脚编号
int irq; //中断号
char *name; //名字
int key; //按键值
struct timer_list key_timer; //定时器,用于消除抖动
} ;
static struct gpio_desc gpios[2] = {
{115, 0, "sr501", 1,}, //GPIO4_19
//{132, 0, "gpio_100ask_2", 2,},
};

入口函数:对每个gpio申请中断,注册字符设备的file_operations,创建设备节点

/* 在入口函数 */
static int __init gpio_drv_init(void)
{
int err;
int i;
int count = sizeof(gpios)/sizeof(gpios[0]);
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
for (i = 0; i < count; i++)
{
gpios[i].irq = gpio_to_irq(gpios[i].gpio); //把引脚号转换为中断号,
//注册中断,处理函数为gpio_key_isr(gpios[i].irq, &gpios[i])
err = request_irq(gpios[i].irq, gpio_key_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
gpios[i].name, &gpios[i]);
}
/* 注册file_operations */
major = register_chrdev(0, "100ask_gpio_key", &gpio_key_drv); /* /dev/gpio_desc */
gpio_class = class_create(THIS_MODULE, "100ask_gpio_key_class");
if (IS_ERR(gpio_class)) {
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
unregister_chrdev(major, "100ask_gpio_key");
return PTR_ERR(gpio_class);
}
device_create(gpio_class, NULL, MKDEV(major, 0), NULL, "sr105"); /* /dev/sr105 */
return err;
}

出口函数:

static void __exit gpio_drv_exit(void)
{
int i;
int count = sizeof(gpios)/sizeof(gpios[0]);
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
device_destroy(gpio_class, MKDEV(major, 0));
class_destroy(gpio_class);
unregister_chrdev(major, "100ask_gpio_key");
for (i = 0; i < count; i++)
{
free_irq(gpios[i].irq, &gpios[i]);
}
}

在gpio中断处理函数中,进行sr501电平值的读取

static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{
struct gpio_desc *gpio_desc = dev_id;
int val;
int key;
printk("gpio_key_isr key %d irq happened\n", gpio_desc->gpio);
val = gpio_get_value(gpio_desc->gpio);
//printk("key_timer_expire key %d %d\n", gpio_desc->gpio, val);
key = (gpio_desc->key) | (val<<8);
put_key(key);
wake_up_interruptible(&gpio_wait);
kill_fasync(&button_fasync, SIGIO, POLL_IN);
return IRQ_HANDLED;
}

修改file_operations结构体及其函数:gpio_drv_read函数中返回ringbuf中的值

static DECLARE_WAIT_QUEUE_HEAD(gpio_wait);
/* 实现对应的open/read/write等函数,填入file_operations结构体 */
static ssize_t gpio_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
int err;
int key;
if (is_key_buf_empty() && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
wait_event_interruptible(gpio_wait, !is_key_buf_empty());
key = get_key();
err = copy_to_user(buf, &key, 4);
return 4;
}
...
/* 定义自己的file_operations结构体 */
static struct file_operations gpio_key_drv = {
.owner = THIS_MODULE,
.read = gpio_drv_read,
.poll = gpio_drv_poll,
.fasync = gpio_drv_fasync,
};

请点击左侧菜单(移动端为右下角)选择要查看的所有笔记吧。

最近更新于