HC-SR505人体感应模块(imx6ull)驱动与测试代码

1.HC-SR505原理

HC-SR505工作原理是根据人体发出的红外信号,发出高电平信号,持续时间在8s。工作电压4.5v-20v。详细原理参考HC-SR505 人体红外感应模块-优快云博客

2.设备树

smarthome-sr505 {
         compatible = “smarthome -sr505”;
         pinctrl-names = “default”;
         pinctrl-0 = <&pinctrl_sr505>;
         sr505-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>;
         status = “okay”;
};
pinctrl_sr505:sr505grp {
        fsl,pins = <
           MX6UL_PAD_UART2_CTS_B__GPIO1_IO22  0x10B0
        >;
};

采用的板子是正点原子的mini开发板,sr505信号输出线连接板子20号引脚

3.驱动代码

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/gpio/consumer.h>


/*设备结构体*/
struct sr505_dev{
	int major;                //主设备号
	struct class *class;      //类
	struct device *device;    //设备
	struct device_node *nd;   //设备节点
	int gpio;         //GPIO编号
	int irq;          //中断号
};

struct sr505_dev sr505_dev;

static struct gpio_desc *sr505_desc;
struct fasync_struct *sr_fasync;     // fasync_struct结构体指针

static irqreturn_t sr505_handler(int irq, void *dev_id)
{
	kill_fasync(&sr_fasync,SIGIO,POLL_IN);       //向应用程序发送通知,可以访问设备
	return IRQ_HANDLED; 
}

static int sr505_open (struct inode *node, struct file *filp)
{
	return 0;
}

static ssize_t sr505_read (struct file *filp, char __user *buf, size_t size, loff_t *offset)
{
	char val;
	int ret;
	val = gpiod_get_value(sr505_desc);
	ret = copy_to_user(buf, &val, 1);
	if(ret != 0){
		printk("sr505 read failed\n");
	}
	return 1;
}

static int sr505_fasync (int fd, struct file *filp, int on)
{
	int retval;
	retval = fasync_helper(fd, filp, on, &sr_fasync);     //初始化sr_fasync结构体
	if (retval < 0)
		return retval;

	return 0;
}

static int sr505_release (struct inode *node, struct file *filp)
{
	sr505_fasync(-1,filp,0);   //删除异步通知
	free_irq(sr505_dev.irq,NULL);
	return 0;
}


static struct file_operations sr505_ops = {
	.owner		=	THIS_MODULE,
	.open 		= 	sr505_open,
	.release 	=	sr505_release,
	.fasync     =   sr505_fasync,
	.read       =   sr505_read,
};

static int sr505_init(void)
{
	int err;
	int ret;
	sr505_dev.nd = of_find_node_by_path("/smarthome-sr505");
	sr505_dev.gpio = of_get_named_gpio(sr505_dev.nd,"sr505-gpio",0);    //获取GPIO标号
	printk("sr505-gpio number: %d\n",sr505_dev.gpio);

	err = gpio_request(sr505_dev.gpio,"sr505_gpio");
	if(err != 0){
        printk("gpio request failed\n");
		return 0;
	}
	
	sr505_desc = gpio_to_desc(sr505_dev.gpio);
	ret = gpiod_direction_input(sr505_desc);
	if(ret < 0){
		printk("can not set direction\n");
	}

    /*申请中断号 申请中断*/
    sr505_dev.irq = gpio_to_irq(sr505_dev.gpio);
	ret = request_irq(sr505_dev.irq,sr505_handler,IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,"sr505_irq",NULL);
    if(ret){
        printk("request_irq failed\n");
		return -1;
	}

	sr505_dev.major = register_chrdev(0 , "sr505", &sr505_ops);
	sr505_dev.class = class_create(THIS_MODULE, "sr505_class");
    sr505_dev.device = device_create(sr505_dev.class, NULL, MKDEV(sr505_dev.major, 0), NULL, "sr505");
	
	return 0;
}

static void sr505_exit(void)
{
	device_destroy(sr505_dev.class, MKDEV(sr505_dev.major, 0));
	class_destroy(sr505_dev.class);
	unregister_chrdev(sr505_dev.major, "sr505");
	gpio_free(sr505_dev.gpio);
}

module_init(sr505_init);
module_exit(sr505_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("keane");
MODULE_VERSION("v1.0");

4.测试代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <poll.h>


int fd;

void handler(int signum)
{
	close(fd);		
	exit(0);
	return 0;
}

void sr505_sigio(int signum)
{
	char val;
	read(fd, &val, 1);
	printf("val is %d, %s\n", val, val==1?"have people":"no people");
}

int main(int argc, char *argv[])
{
	char buf[10];
	
	int val;
	char status = 1;
	int flags;
	int tim;

	signal(SIGINT, handler);  /* ctrl+c */
	signal(SIGIO, sr505_sigio);
	
	fd = open("/dev/sr505", O_RDWR);
	if(fd < 0){
		printf("/dev/sr505 open failed\n");
		return 1;
	}

	fcntl(fd, F_SETOWN, getpid());    //当前进程号告诉内核
	flags = fcntl(fd, F_GETFL);       //获取当前进程状态
	fcntl(fd, F_SETFL, flags | O_ASYNC);  //设置进程启用异步通知功能

	while(1){
		sleep(1);
	}

	
	return 0;
}

5.效果展示 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值