单片机
返回首页

s3c2440之按键中断驱动

2022-10-25 来源:csdn

前言

本文记录的是S3C2440按键中断驱动程序,在查询方式按键驱动程序基础下修改。


一、代码

1.按键中断驱动程序

key_drv.c代码如下(示例):


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include



static struct class *keydrv_class;

static struct class_device *keydrv_class_dev;


volatile unsigned long *GPFCON;

volatile unsigned long *GPFDAT;


volatile unsigned long *GPGCON;

volatile unsigned long *GPGDAT;


static DECLARE_WAIT_QUEUE_HEAD(button_waitq);


/* 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0 */

static volatile int ev_press = 0;


struct pin_desc {

unsigned int pin;

unsigned int key_val;

};



static unsigned char key_val;

/* 键值: 按下时:0x01, 0x02, 0x03, 0x04 */

/* 键值: 松开时:0x81, 0x82, 0x83, 0x84 */

struct pin_desc pins_desc[4] = {

{S3C2410_GPF0, 0x01},

{S3C2410_GPF2, 0x02},

{S3C2410_GPG3, 0x03},

{S3C2410_GPG11, 0x04},


};


static irqreturn_t buttons_irq(int irq, void *dev_id) {

struct pin_desc * pindesc = (struct pin_desc *)dev_id;

unsigned int pinval;


pinval = s3c2410_gpio_getpin(pindesc->pin);

if(pinval){

/* 松开 */

key_val = 0x80 | pindesc->key_val;

} else {

/* 按下 */

key_val = pindesc->key_val;

}


ev_press = 1;                  /* 表示中断发生了 */

    wake_up_interruptible(&button_waitq);   /* 唤醒休眠的进程 */

return IRQ_RETVAL(IRQ_HANDLED);


}


static int key_drv_open(struct inode* inode, struct file *file){

/* 配置 GPF0,GPF2为输入引脚(置0) */

/* 配置 GPG3,GPG11为输入引脚(置0) */

request_irq(IRQ_EINT0,  buttons_irq, IRQT_BOTHEDGE, 'S2', &pins_desc[0]);

request_irq(IRQ_EINT2,  buttons_irq, IRQT_BOTHEDGE, 'S3', &pins_desc[1]);

request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, 'S4', &pins_desc[2]);

request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, 'S5', &pins_desc[3]);

return 0;

}


static ssize_t key_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) {

if(size != 1) {

return -EINVAL;

}


/* 如果没有按键动作, 休眠 */

wait_event_interruptible(button_waitq, ev_press);


/* 如果有按键动作, 返回键值 */

copy_to_user(buf, &key_val, 1);

ev_press = 0;

return 1;



}


int key_drv_close (struct inode* inode, struct file *file) {


free_irq(IRQ_EINT0,  &pins_desc[0]);

free_irq(IRQ_EINT2,  &pins_desc[1]);

free_irq(IRQ_EINT11, &pins_desc[2]);

free_irq(IRQ_EINT19, &pins_desc[3]);


return 0;

}


static struct file_operations key_drv_fops = {

.owner   = THIS_MODULE,

.open    = key_drv_open,

.read    = key_drv_read,

.release = key_drv_close,

};


int major;

static int key_drv_init(void) {

major = register_chrdev(0, 'key_drv', &key_drv_fops); //注册驱动程序,告诉内核

keydrv_class = class_create(THIS_MODULE, 'key_drv');


keydrv_class_dev = class_device_create(keydrv_class, NULL, MKDEV(major, 0), NULL, 'buttons'); /* /dev/buttons */


GPFCON = (volatile unsigned long *)ioremap(0x56000050, 16); //物理地址映射成虚拟地址

GPFDAT = GPFCON + 1;


GPGCON = (volatile unsigned long *)ioremap(0x56000060, 16); //物理地址映射成虚拟地址

GPGDAT = GPGCON + 1;

return 0;

}


static void key_drv_exit(void) {

unregister_chrdev(major, 'key_drv'); //卸载驱动

class_device_unregister(keydrv_class_dev);

class_destroy(keydrv_class);


iounmap(GPFCON); //解除映射关系

iounmap(GPGCON); //解除映射关系

}


module_init(key_drv_init);

module_exit(key_drv_exit);


MODULE_LICENSE('GPL'); //让linux识别定义的类


2.测试程序

keydrvtest.c代码如下(示例):


#include

#include

#include

#include


/* keydrvtest 

  */

int main(int argc, char **argv)

{

int fd;

unsigned char key_val;

fd = open('/dev/buttons', O_RDWR);

if (fd < 0)

{

printf('can't open!n');

}


while (1)

{

read(fd, &key_val, 1);

printf('key_val = 0x%xn', key_val);

//sleep(5);

}

return 0;

}


3.Makefile

keydrvtest.c代码如下(示例):


KERN_DIR = /home/book/work/system/linux-2.6.22.6


all:

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


clean:

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

rm -rf modules.order


obj-m += key_drv.o


二、结果显示

在这里插入图片描述

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • 如何构建一个触摸传感器电路

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章