这里面我们需要完成用按键去控制一个灯。
我们需要的硬件包括:
按键
1. ENT0 : GPF0
2. EINT2: GPF2
3. EINT11: GPG3
led灯:
LED1:GPF4
LED2: GPF5
LED4: GPF6
思路就是 按下一个按键 则 对应的灯会亮。
那么在程序里面的思路是:
1、测试程序会一直读IO口的状态,当有按键被按下的时候则去判断是哪个按键按下 并且开启指定的灯。
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/irq.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #include <linux/poll.h> static struct class *forthdrv_class; static struct class_device *forthdrv_class_dev; volatile unsigned long *gpfcon = NULL; volatile unsigned long *gpfdat = NULL; volatile unsigned long *gpgcon = NULL; volatile unsigned long *gpgdat = NULL; //this is for key /* 1. ENT0 : GPF0 2. EINT2: GPF2 3. EINT11: GPG3 led??? LED1??GPF4 LED2?? GPF5 LED4?? GPF6 */ static int forth_drv_open(struct inode *inode, struct file *file) { // printk("this is the open function\r\n"); /* The task needs to do in open function 1. initialize lcd and key GPIO */ *gpfcon |= (1<<12) | (0x01<<10) | (0x01 << 8); //this is for led intialization *gpfcon &= ~((1<<0) | (1<<1) |(1<<5) | (1<<4) | (1<<7) | (1<<6)); //this is for the key GPIO initialization *gpgcon &= ~((1<<23) | (1<<22)); *gpgcon &= ~((1<<7) | (1<<6)); return 0; } ssize_t forth_drv_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos) {/* int val; copy_from_user(&val, buf, count); if(val == 1) { *gpfdat &= ~((1<<4) | (1<<5) | (1<<6)); } else { *gpfdat |= (1<<4) | (1<<5) | (1<<6); } */ return 0; } ssize_t forth_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { unsigned char key_val[4]; int regval; regval = *gpfdat; key_val[0] = (regval & (1<<0)) ? 1 : 0; key_val[1] = (regval & (1<<2)) ? 1 : 0; regval = *gpgdat; key_val[2] = (regval & (1<<3)) ? 1 : 0; key_val[3] = (regval & (1<<11)) ? 1 : 0; copy_to_user(buf, key_val, sizeof(key_val)); // printk("this is the read function\r\n"); return sizeof(key_val); } static struct file_operations sencod_drv_fops = { .owner = THIS_MODULE, /* ?????????????????????????????__this_module???? */ .open = forth_drv_open, .read = forth_drv_read, //???????? ????????????????? ??????????????д????????????????????? .write = forth_drv_write, //???????? ???????д???????????????? }; int major; static int forth_drv_init(void) { major = register_chrdev(0, "forth_drv", &sencod_drv_fops); //注册一个设备 forthdrv_class = class_create(THIS_MODULE, "forth_drv"); //生成一个class类型 forthdrv_class_dev = class_device_create(forthdrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */ /*把这个class类型创建出来 并且给一个主设备号*/ /*initialize the GPIO pin here */ gpfcon = ioremap(0x56000050, 16); //remap the IO address to virsual linux address gpfdat = gpfcon + 1; gpgcon = ioremap(0x56000060, 16); //this is for key gpgdat = gpgcon + 1; return 0; } static void forth_drv_exit(void) { unregister_chrdev(major, "forth_drv"); iounmap(gpfcon); iounmap(gpgcon); class_destroy(forthdrv_class); } module_init(forth_drv_init); module_exit(forth_drv_exit); MODULE_LICENSE("GPL");
首先我们来看这个程序,我们是从read函数中读取的所有的按键的状态,其中这个read函数就是对应到我们APP的read函数中的。
我们在read中进行了多按键的读取,其中函数
copy_to_user(buf, key_val, sizeof(key_val));是把数据从内核中读出 然后给到APP里面来。
我们的测试程序如下:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <signal.h> #include <unistd.h> #include <unistd.h> #include <fcntl.h> /* 1. ENT0 : GPF0 2. EINT2: GPF2 3. EINT11: GPG3 4. EINT19: GPG11 led??? LED1??GPF4 LED2?? GPF5 LED4?? GPF6 */ int fd; int val; unsigned char key_val[4] = {0}; int main(int argc, char **argv) { int flags; fd = open("/dev/buttons", O_RDWR); if (fd < 0) { printf("can‘t open!\n"); return -1; } while(1) { read(fd,key_val, sizeof(key_val)); if(!key_val[0] || !key_val[1] || !key_val[2] || !key_val[3]) { printf("GPF0 = %d, GPF1= %d, GPF3= %d\n GPG11= %d", key_val[0], key_val[1], key_val[2], key_val[3]); } } return 0; }
不过这种情况情况下 我们的程序占用CPU太多,因为是不断的查询
所以 我们需要用中断的方式来重新处理这个函数
原文:https://www.cnblogs.com/shwzh1990/p/14166608.html