arm自作室内人群检测驱动,人流进出检测驱动+应用

人群检测,人流进出构思

想在门口只做一个检测人流量的多少,和监控室内进出人群
就用一个人体红外感应器来触发中断,用两个红外传感器来判断人是进入还是出去(不用光敏电阻,不够灵敏)
大概就是这样检测,因为人体红外的广域检测,红外传感是直线的,所以人体红外来触发中断

构思示意图

在这里插入图片描述

连线示意图

在这里插入图片描述
三个gpio口,两个负责红外的输入检测,一个负责人体的中断

代码上手

硬件连接

在这里插入图片描述
使用这三个gpio接口,图中红色的接口好像已经被占用,强行转换输出会报错

驱动编写poll中断
设置等待队列

在这里插入图片描述

设置定时器

poll中断的特色,没有中断发生,到时间也会自己查询
在这里插入图片描述

设置中断函数

在里面进行有中断发生的时候,对io口的检测,判断人的进出
在这里插入图片描述

按键初始化

初始化三个口为输出口,其中为一个口注册中断---->上升沿才触发(说明有人来了才会开始检测)
在这里插入图片描述

大概就是这些改动,其他的都是根据按键驱动进行的改写

app应用编写

在里面copy_form_user() 对人来人往进行检测,判断人的走向,统计人的数量
在这里插入图片描述

代码

写的不是很完整,很多冗余的,但是能用,改改还是很美观
buttondrv.c

 /*************************************************
 *头文件
 *************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
 
#include <asm/mach-types.h>
#include <asm/gpio.h>
#include <asm/delay.h>
#include <mach/gpio.h>
#include <mach/soc.h>
#include <mach/platform.h>
 
 
#define DEVICE_NAME		"gecBt"                //设备名字
static int get_number ;
 
 //按键结构体
 struct button_desc {
	 int gpio;
	 int number;
	 char *name; 
	 struct timer_list timer;
	 int  right_and_left;
 };
 
 //按键的管脚,编号,名字
 static struct button_desc buttons[] = {
	{ (PAD_GPIO_B + 9 ), 0, "KEY0" },//B9
	{ (PAD_GPIO_B + 29), 1, "KEY1" },//人体红外
	//{ (PAD_GPIO_B + 9), 2, "KEY2" },//左边 第四个
	//{ (PAD_GPIO_A + 28), 3, "KEY3" },//右边 第三个
 };
 
 //赋按键的初始值
 static volatile int key_values[] = {
	 2, 2, 2, 2
 };
 
 //等待队列申请
 static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
 
 static volatile int ev_press = 0; //判断中断的发生
 
 /*************************************************
 *定时器
 *************************************************/
 static void x6818_buttons_timer(unsigned long _data)
 {
	 struct button_desc *bdata = (struct button_desc *)_data;
 
	 mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(40));
 }
 
 /*************************************************
 *按键中断
 *************************************************/
 static irqreturn_t button_interrupt(int irq, void *dev_id)
 {
	 struct button_desc *bdata = (struct button_desc *)dev_id;
	 int down;
	 int number;
	 unsigned tmp;
 
	 tmp = gpio_get_value(bdata->gpio);
 
	 /* active low */
	 down = tmp;
	 printk("kernel KEY %d: %08x\n", bdata->number, down);
 
	 number = bdata->number;

	

	 int get_letf   =  gpio_get_value(PAD_GPIO_B + 9);//左边的光敏0没人,有人1遮光
	 int get_right =  gpio_get_value(PAD_GPIO_A + 28);//右边的红外0没人,1有人
	 //del_timer(&x6818_buttons_timer);

	 //开始在强光的照射下  为0,没光为1
	 while(get_letf | get_right) //开始为0
	 	{
	 		printk("kernel the right %d and left is %d",get_letf,get_right);
	 		if (get_letf == 1)
	 			{
	 				bdata->right_and_left = 2;
					key_values[1] =2;
					mdelay(5000);
	 			}
			if (get_right == 1)
				{
				 	bdata->right_and_left = 3;
					key_values[1] = 3;
					mdelay(5000);
				}
			break;
	 	}
	printk("end  is %d",bdata->right_and_left);
	//mdelay(5000);
	ev_press = 1;
	wake_up_interruptible(&button_waitq);
	 /********
	 if (down == (key_values[number])) {
		 key_values[number] = '0' + down;
		 ev_press = 1;
		 wake_up_interruptible(&button_waitq);
	 }
	 ******/
	 get_letf = 0;
	 get_right = 0;
 
	 return IRQ_HANDLED;
 }
 
 /*************************************************
 *按键初始化
 *************************************************/
 static int x6818_buttons_init(void)
 {
	 int irq;
	 int i;
	 int err = 0;

	 gpio_direction_input(PAD_GPIO_B + 9);
	 gpio_direction_input(PAD_GPIO_A + 28);
 
	 //每个按键 都设置 为上升向沿 触发模式
	 for (i = 0; i < ARRAY_SIZE(buttons); i++) {
		 if (!buttons[i].gpio)
			 continue;
		 gpio_free(buttons[i].gpio);
		 setup_timer(&buttons[i].timer, x6818_buttons_timer,
				 (unsigned long)&buttons[i]);
 
		 irq = gpio_to_irq(buttons[i].gpio);
		 
		 pr_err("irq = %.2d\n",irq);
		 err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_RISING, 
				 buttons[i].name, (void *)&buttons[i]);//上升触发
		 if (err)
		 {
			 pr_err("irq = %.2d is failed\n",i);
			 break;
		 }
 
	 }
	 //中断申请失败的时候,释放中断
	 if (err) {
		 i--;
		 for (; i >= 0; i--) {
			 if (!buttons[i].gpio)
				 continue;
 
			 irq = gpio_to_irq(buttons[i].gpio);
			 disable_irq(irq);
			 free_irq(irq, (void *)&buttons[i]);
 
			 del_timer_sync(&buttons[i].timer);
		 }
 
		 return -EBUSY;
	 }
 
	 ev_press = 1;
	 return 0;
 }
 
 static int x6818_buttons_open(struct inode *inode, struct file *file) 
 {
	 return 0;
 }
 
 
 
 /*************************************************
 *按键释放
 *************************************************/
 static int x6818_buttons_close(struct inode *inode, struct file *file)
 {
	 int irq, i;
 
	 for (i = 0; i < ARRAY_SIZE(buttons); i++) {
		 if (!buttons[i].gpio)
			 continue;
		 irq = gpio_to_irq(buttons[i].gpio);
		 free_irq(irq, (void *)&buttons[i]);
 
		 del_timer_sync(&buttons[i].timer);
	 }
 
	 return 0;
 }
 
 /*************************************************
 *按键读取值
 *************************************************/
 static int x6818_buttons_read(struct file *filp, char __user *buff,
		 size_t count, loff_t *offp)
 {
	 unsigned long err;
	 
	 if (!ev_press) {
		 if (filp->f_flags & O_NONBLOCK)
			 return -EAGAIN;
		 else{
			 pr_err("wai_enven*********************\n");
			 wait_event_interruptible(button_waitq, ev_press);
			 pr_err("OK*********************************\n");
		 }
	 }
 
	 ev_press = 0;
 
	 err = copy_to_user((void *)buff, (const void *)(&key_values),
			min(sizeof(key_values), count));
 
	 return err ? -EFAULT : min(sizeof(key_values), count);
 }
 
 /*************************************************
 *按键的头
 *************************************************/
 static unsigned int x6818_buttons_poll( struct file *file,
		 struct poll_table_struct *wait)
 {
	 unsigned int mask = 0;
 
	 poll_wait(file, &button_waitq, wait);
	 if (ev_press)
		 mask |= POLLIN | POLLRDNORM;
 
	 return mask;
 }
 
 /*************************************************
 *文件操作集
 *************************************************/
 static struct file_operations dev_fops = {
	 .owner 	 = THIS_MODULE,
	 .open			 = x6818_buttons_open,
	 .release	 = x6818_buttons_close, 
	 .read		 = x6818_buttons_read,
	 .poll		 = x6818_buttons_poll,
 };
 
 /*************************************************
 *杂项设备
 *************************************************/
 static struct miscdevice misc = {
	 .minor 	 = MISC_DYNAMIC_MINOR,
	 .name		 = DEVICE_NAME,
	 .fops		 = &dev_fops,
 };
 
 /********************************************************************
 *驱动的初始化函数--->从内核中申请资源(内核、中断、设备号、锁....)
 ********************************************************************/
 static int __init button_dev_init(void)
 {
	 int ret;
	 ret = misc_register(&misc);
	 x6818_buttons_init();
	 pr_err(DEVICE_NAME"\tinitialized\n");
 
	 return ret;
 }
 
 /*****************************************************************
 *驱动退出函数 --->将申请的资源还给内核
 *****************************************************************/
 static void __exit button_dev_exit(void)
 {
	 misc_deregister(&misc);
 }
 
 module_init(button_dev_init);						 //驱动的入口函数会调用一个用户的初始化函数
 module_exit(button_dev_exit);						 //驱动的出口函数会调用一个用户的退出函数
 
 //驱动的描述信息: #modinfo  *.ko , 驱动的描述信息并不是必需的。
 MODULE_AUTHOR("ZOROE@GEC");						 //驱动的作者
 MODULE_DESCRIPTION("Butoons of driver");			 //驱动的描述
 MODULE_LICENSE("GPL"); 							 //遵循的协议
 
 



buttonrun.c

/*---------------------------------------
*功能描述:  按键测试程序 
*创建者:   粤嵌技术部
*创建时间: 2015,01,01
---------------------------------------
*修改日志:
*修改内容:
*修改人:
*修改时间:
----------------------------------------*/
/*************************************************
*头文件
*************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>

#define  ARRY_SIZE(x) (sizeof(x)/sizeof(x[0]))

/*************************************************
*主函数
*************************************************/
int main(int argc , char **argv)
{
		int button_fd ;
		int current_button_value[4]={}; 		 //板载八个按键 vol
		char prior_button_value[4]={'0'};			 //用于保存按键的前键值
		int person = 0 ;
		
		button_fd = open("/dev/gecBt", O_RDWR);   //打开设备,成功返回0
		if(button_fd <0){
			perror("open device :");
			exit(1);		
		}
	
		while(1){
		int i ;
			
		read(button_fd, current_button_value, sizeof(current_button_value)) ;
		if(current_button_value[1] ==2)
			{
			printf("left success \n");
			person++;
			}
		if(current_button_value[1] ==3)
			{
			printf("right success \n");
			person--;
			}
		
		printf("all person is \%d\n",person);
	

				}
			}




Makefile

#内核要提前编译好
KERN_DIR = /home/scholar/Desktop/6818GEC/kernel
#-C 是转到后面的目录'$(KERN_DIR)',使用这个目录下面的 Makefile 编译
#M是指当前目标是什么
#moudule 是指目标

all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

obj-m	+= dht11drv.o

运行结果

伸手反着检测了,但是能有双向检测,说明运行正确
在这里插入图片描述

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值