控制IO端口 s3c2410_gpio_setpin()的使用

本文基于FL2440 ARM开发板

Linux内核版本 2.6.28.7

arm-linux-gcc 3.4.1

转载请标明出处http://blog.csdn.net/yming0221

#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/interrupt.h>/*设置中断方式*/ #include <linux/wait.h> #include <linux/irq.h> #include <asm/uaccess.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> //设备名 #define IO_DEVICE_NAME "my_io" //主设备号 #define IO_DEVICE_MAJOR 240 //次设备号 #define IO_DEVICE_SECONDARY 32 //返回一个数x的第y位 #define MYBIT(x,y) ((x>>y)%2) #ifndef _LINUX_IRQRETURN_H #define _LINUX_IRQRETURN_H typedef int irqreturn_t; #define IRQ_EINT0 0 #define IRQ_EINT2 2 #define IRQ_EINT3 3 #define IRQ_EINT4 32 #define IRQ_NONE (0) #define IRQ_HANDLED (1) #define IRQ_RETVAL(x) ((x) != 0) #endif /* * S3C2410 GPIO edge detection for IRQs: * IRQs are generated on Falling-Edge, Rising-Edge, both, low level or higg level. * This must be called *before* the corresponding IRQ is registered. */ #define EXT_LOWLEVEL 0 #define EXT_HIGHLEVEL 1 #define EXT_FALLING_EDGE 2 #define EXT_RISING_EDGE 4 #define EXT_BOTH_EDGES 6 static int flag_0,flag_2;//中断转换标志 static int cnt; DECLARE_WAIT_QUEUE_HEAD(io_wait);//声明等待队列 void io_con_set(); static irqreturn_t io_interrupt_0(int irq,void * dev_id,struct pt_regs *regs) { printk("**********the interrupt 0 works**********/n"); if(flag_0==0) { cnt=(cnt+1)%2; flag_0=1; if(cnt==0) { printk("IN/n"); s3c2410_gpio_setpin(S3C2410_GPB5,0); s3c2410_gpio_setpin(S3C2410_GPB6,1); } wake_up_interruptible(&io_wait); } return IRQ_HANDLED; } static irqreturn_t io_interrupt_2(int irq,void * dev_id,struct pt_regs *regs) { printk("**********the interrupt 2 works**********/n"); if(flag_2==0) { cnt=(cnt+1)%2; flag_2=1; if(cnt==0) { printk("OUT/n"); s3c2410_gpio_setpin(S3C2410_GPB5,1); s3c2410_gpio_setpin(S3C2410_GPB6,0); } wake_up_interruptible(&io_wait); } return IRQ_HANDLED; } static int io_open(struct inode * inode,struct file * file)//打开设备函数 { int ret; set_irq_type(IRQ_EINT0,EXT_FALLING_EDGE);//设置中断0 触发方式 set_irq_type(IRQ_EINT2,EXT_FALLING_EDGE);//设置中断2 触发方式 // EXT_LOWLEVEL // EXT_HIGHLEVEL // EXT_FALLING_EDGE // EXT_RISING_EDGE // EXT_BOTH_EDGES disable_irq(IRQ_EINT0); disable_irq(IRQ_EINT2); enable_irq(IRQ_EINT0); enable_irq(IRQ_EINT2); ret=request_irq(IRQ_EINT0,io_interrupt_0,IRQF_SHARED,IO_DEVICE_NAME,1);//注册中断0 if(ret<0) { printk("IRQ %d can not request/n",IRQ_EINT0); return ret; } ret=request_irq(IRQ_EINT2,io_interrupt_2,IRQF_SHARED,IO_DEVICE_NAME,1);//注册中断2 if(ret<0) { printk("IRQ %d can not request/n",IRQ_EINT2); return ret; } printk("the device is opened/n"); io_con_set(); cnt=0; return 0; } void io_con_set()//IO端口控制寄存器初始化 { s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0); s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2); s3c2410_gpio_cfgpin(S3C2410_GPB5,S3C2410_GPB5_OUTP); s3c2410_gpio_cfgpin(S3C2410_GPB6,S3C2410_GPB6_OUTP); } static int io_close(struct inode * inode,struct file * file)//设备关闭函数 { free_irq(IRQ_EINT0,1);//释放中断 free_irq(IRQ_EINT2,1);//释放中断 printk("the device is closed/n"); return 0; } static ssize_t io_read(struct file * filp,char * buff,size_t count,loff_t * f_ops)//读取IO端口 { wait_event_interruptible(io_wait,flag_0); wait_event_interruptible(io_wait,flag_0); flag_0=0; flag_2=0; //printk("the value is %d/n",io_data); copy_to_user(buff,(char *)&cnt,sizeof(cnt)); } static struct file_operations io_device_fops = { .owner=THIS_MODULE, .read=io_read, .open=io_open, .release=io_close, }; static int __init io_init(void)//insmod加载驱动时执行 { int ret; ret=register_chrdev(IO_DEVICE_MAJOR,IO_DEVICE_NAME,&io_device_fops); if(ret<0) { printk("Fail to regist the device/n"); return ret; } return 0; } static int __exit io_exit(void)//rmmod卸载驱动时执行 { unregister_chrdev(IO_DEVICE_MAJOR,IO_DEVICE_NAME); printk("the device has been unregisted/n"); } module_init(io_init); module_exit(io_exit); MODULE_LICENSE("GPL");

Makefile同上一篇的Makefile

obj-m := my_io.o

KERNELDIR ?= /arm/linux-2.6.28.7-2440

PWD := $(shell pwd)

default:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:

rm -f *.o *.ko *.order *.symvers

这次本人修改了下内核头文件的目录,将目录./arch/arm/include下asm文件夹复制到./include

将目录./arch/arm/mach-s3c2410/include下mach文件夹复制到./include下

驱动修改版

#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/interrupt.h>/*设置中断方式*/ #include <linux/wait.h> #include <linux/irq.h> #include <asm/uaccess.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> //设备名 #define IO_DEVICE_NAME "my_io" //主设备号 #define IO_DEVICE_MAJOR 240 //次设备号 #define IO_DEVICE_SECONDARY 32 //返回一个数x的第y位 #define MYBIT(x,y) ((x>>y)%2) #ifndef _LINUX_IRQRETURN_H #define _LINUX_IRQRETURN_H typedef int irqreturn_t; #define IRQ_EINT0 0 #define IRQ_EINT2 2 #define IRQ_EINT3 3 #define IRQ_EINT4 32 #define IRQ_NONE (0) #define IRQ_HANDLED (1) #define IRQ_RETVAL(x) ((x) != 0) #endif /* * S3C2410 GPIO edge detection for IRQs: * IRQs are generated on Falling-Edge, Rising-Edge, both, low level or higg level. * This must be called *before* the corresponding IRQ is registered. */ #define EXT_LOWLEVEL 0 #define EXT_HIGHLEVEL 1 #define EXT_FALLING_EDGE 2 #define EXT_RISING_EDGE 4 #define EXT_BOTH_EDGES 6 static int flag_0,flag_2;//中断转换标志 static int cnt; DECLARE_WAIT_QUEUE_HEAD(io_wait);//声明等待队列 void io_con_set(); static irqreturn_t io_interrupt_0(int irq,void * dev_id,struct pt_regs *regs) { if(flag_0==0) { printk("**********the interrupt 0 works**********/n"); cnt=(cnt+1)%2; flag_0=1; if(cnt==0) { printk("IN/n"); s3c2410_gpio_setpin(S3C2410_GPB5,0); s3c2410_gpio_setpin(S3C2410_GPB6,1); } wake_up_interruptible(&io_wait); } return IRQ_HANDLED; } static irqreturn_t io_interrupt_2(int irq,void * dev_id,struct pt_regs *regs) { if(flag_2==0) { printk("**********the interrupt 2 works**********/n"); cnt=(cnt+1)%2; flag_2=1; if(cnt==0) { printk("OUT/n"); s3c2410_gpio_setpin(S3C2410_GPB5,1); s3c2410_gpio_setpin(S3C2410_GPB6,0); } wake_up_interruptible(&io_wait); } return IRQ_HANDLED; } static int io_open(struct inode * inode,struct file * file)//打开设备函数 { int ret; set_irq_type(IRQ_EINT0,EXT_FALLING_EDGE);//设置中断0 触发方式 set_irq_type(IRQ_EINT2,EXT_FALLING_EDGE);//设置中断2 触发方式 // EXT_LOWLEVEL // EXT_HIGHLEVEL // EXT_FALLING_EDGE // EXT_RISING_EDGE // EXT_BOTH_EDGES disable_irq(IRQ_EINT0); disable_irq(IRQ_EINT2); enable_irq(IRQ_EINT0); enable_irq(IRQ_EINT2); ret=request_irq(IRQ_EINT0,io_interrupt_0,IRQF_SHARED,IO_DEVICE_NAME,1);//注册中断0 if(ret<0) { printk("IRQ %d can not request/n",IRQ_EINT0); return ret; } ret=request_irq(IRQ_EINT2,io_interrupt_2,IRQF_SHARED,IO_DEVICE_NAME,1);//注册中断2 if(ret<0) { printk("IRQ %d can not request/n",IRQ_EINT2); return ret; } printk("the device is opened/n"); io_con_set(); cnt=0; return 0; } void io_con_set()//IO端口控制寄存器初始化 { s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0); s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2); s3c2410_gpio_cfgpin(S3C2410_GPB5,S3C2410_GPB5_OUTP); s3c2410_gpio_cfgpin(S3C2410_GPB6,S3C2410_GPB6_OUTP); } static int io_close(struct inode * inode,struct file * file)//设备关闭函数 { free_irq(IRQ_EINT0,1);//释放中断 free_irq(IRQ_EINT2,1);//释放中断 printk("the device is closed/n"); return 0; } static ssize_t io_read(struct file * filp,char * buff,size_t count,loff_t * f_ops)//读取IO端口 { wait_event_interruptible(io_wait,flag_0&flag_2); flag_0=0; flag_2=0; //printk("the value is %d/n",io_data); copy_to_user(buff,(char *)&cnt,sizeof(cnt)); } static struct file_operations io_device_fops = { .owner=THIS_MODULE, .read=io_read, .open=io_open, .release=io_close, }; static int __init io_init(void)//insmod加载驱动时执行 { int ret; ret=register_chrdev(IO_DEVICE_MAJOR,IO_DEVICE_NAME,&io_device_fops); if(ret<0) { printk("Fail to regist the device/n"); return ret; } return 0; } static int __exit io_exit(void)//rmmod卸载驱动时执行 { unregister_chrdev(IO_DEVICE_MAJOR,IO_DEVICE_NAME); printk("the device has been unregisted/n"); } module_init(io_init); module_exit(io_exit); MODULE_LICENSE("GPL");

这个驱动实际上是通过红外传感器检测电平变化,来实现人数的统计,改进后能够实现正确的通过中断先后来识别方向,还排除了单一中断的

抖动干扰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值