人群检测,人流进出构思
想在门口只做一个检测人流量的多少,和监控室内进出人群
就用一个人体红外感应器来触发中断,用两个红外传感器来判断人是进入还是出去(不用光敏电阻,不够灵敏)
大概就是这样检测,因为人体红外的广域检测,红外传感是直线的,所以人体红外来触发中断
构思示意图
连线示意图
三个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
运行结果
伸手反着检测了,但是能有双向检测,说明运行正确