主题 : 求用中断方式实现按键程序 复制链接 | 浏览器收藏 | 打印
级别: 侠客
UID: 39689
精华: 0
发帖: 69
金钱: 350 两
威望: 70 点
综合积分: 138 分
注册时间: 2011-03-11
最后登录: 2012-04-22
楼主  发表于: 2011-04-06 14:12

 求用中断方式实现按键程序

求mini6410按键程序
要求:
   用中断方式,按一次键蜂鸣器响一次。
级别: 侠客
UID: 39689
精华: 0
发帖: 69
金钱: 350 两
威望: 70 点
综合积分: 138 分
注册时间: 2011-03-11
最后登录: 2012-04-22
1楼  发表于: 2011-04-07 12:15
没人响应啊。,自己顶个
级别: 新手上路
UID: 43143
精华: 0
发帖: 8
金钱: 40 两
威望: 8 点
综合积分: 16 分
注册时间: 2011-04-14
最后登录: 2011-04-26
2楼  发表于: 2011-04-17 10:10
按下键,灯亮,蜂鸣器响,松开键,灯灭,蜂鸣器不响
级别: 新手上路
UID: 43143
精华: 0
发帖: 8
金钱: 40 两
威望: 8 点
综合积分: 16 分
注册时间: 2011-04-14
最后登录: 2011-04-26
3楼  发表于: 2011-04-17 10:11
驱动

#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/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <plat/regs-timer.h>
#include <asm/io.h>
#include <mach/regs-irq.h>
#include <asm/mach/time.h>
#include <linux/clk.h>
#include <linux/device.h>


#define DEVICE_NAME     "IRQ-Test"

static unsigned long gpio_table [] =
{
    S3C2410_GPB5,
    S3C2410_GPB6,
    S3C2410_GPB7,
    S3C2410_GPB8,
};

/* 用来指定GPIO引脚的功能:输出 */
static unsigned int gpio_cfg_table [] =
{
    S3C2410_GPB5_OUTP,
    S3C2410_GPB6_OUTP,
    S3C2410_GPB7_OUTP,
    S3C2410_GPB8_OUTP,
};

struct button_irq_desc {
    int irq;
    int pin;
    int pin_setting;
    int number;
    char *name;    
};

#if !defined (CONFIG_SKY2440_IRQ_TEST)
static struct button_irq_desc button_irqs [] = {
    {IRQ_EINT1,    S3C2410_GPF1,    S3C2410_GPF1_EINT1,    0, "KEY1"}, /* K1 */
    {IRQ_EINT4,    S3C2410_GPF4,    S3C2410_GPF4_EINT4,    1, "KEY2"}, /* K2 */
    {IRQ_EINT2,    S3C2410_GPF2,    S3C2410_GPF2_EINT2,    2, "KEY3"}, /* K3 */
    {IRQ_EINT0,    S3C2410_GPF0,    S3C2410_GPF0_EINT0,    3, "KEY4"}, /* K4 */
};
#else
static struct button_irq_desc button_irqs [] = {
    {IRQ_EINT9,    S3C2410_GPG1,    S3C2410_GPG1_EINT9,    0, "KEY1"}, /* K1 */
    {IRQ_EINT11,    S3C2410_GPG3,    S3C2410_GPG3_EINT11,    1, "KEY2"}, /* K2 */
    {IRQ_EINT2,    S3C2410_GPF2,    S3C2410_GPF2_EINT2,    2, "KEY3"}, /* K3 */
    {IRQ_EINT0,    S3C2410_GPF0,    S3C2410_GPF0_EINT0,    3, "KEY4"}, /* K4 */
};
#endif
static volatile char key_values [] = {'0', '0', '0', '0'};

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

static volatile int ev_press = 0,pp=0;


static irqreturn_t irq_interrupt(int irq, void *dev_id)
{
    struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;
    int down;

    down = !s3c2410_gpio_getpin(button_irqs->pin);

    if (down != (key_values[button_irqs->number] & 1))
    {
        key_values[button_irqs->number] = '0' + down;
        s3c2410_gpio_setpin(gpio_table[button_irqs->number], 0);
        ev_press = 1;
        pp=!pp;
        wake_up_interruptible(&button_waitq);
    }

    return IRQ_RETVAL(IRQ_HANDLED);
}


static int tq2440_irq_open(struct inode *inode, struct file *file)
{
    int i;
    int err = 0;

    for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
    {
        if (button_irqs.irq < 0)
            continue;
        err = request_irq(button_irqs.irq, irq_interrupt, IRQ_TYPE_EDGE_BOTH,
                          button_irqs.name, (void *)&button_irqs);
        if (err)
            break;
    }

    if (err)
    {
        i--;
        for (; i >= 0; i--)
        {
            if (button_irqs.irq < 0)
                continue;
            disable_irq(button_irqs.irq);
            free_irq(button_irqs.irq, (void *)&button_irqs);
        }
        return -EBUSY;
    }

    ev_press = 1;
    pp=1;

    return 0;
}


static int tq2440_irq_close(struct inode *inode, struct file *file)
{
    int i;

    for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
    {
        if (button_irqs.irq < 0)
            continue;
        free_irq(button_irqs.irq, (void *)&button_irqs);
    }

    return 0;
}



static int tq2440_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd)
{
    unsigned long tcfg0;
    unsigned long tcfg1;
    unsigned long tcntb;
    unsigned long tcmpb;
    unsigned long tcon;

    if(cmd <= 0)
    {
        s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
        s3c2410_gpio_setpin(S3C2410_GPB0, 0);
    }
    else
    {
        struct clk *clk_p;
        unsigned long pclk;

        //set GPB0 as tout0, pwm output
        s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0);

        tcon = __raw_readl(S3C2410_TCON);
        tcfg1 = __raw_readl(S3C2410_TCFG1);
        tcfg0 = __raw_readl(S3C2410_TCFG0);

        //prescaler = 50
        tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
        tcfg0 |= (50 - 1);

        //mux = 1/16
        tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
        tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;

        __raw_writel(tcfg1, S3C2410_TCFG1);
        __raw_writel(tcfg0, S3C2410_TCFG0);

        clk_p = clk_get(NULL, "pclk");
        pclk  = clk_get_rate(clk_p);
        tcntb  = (pclk/128)/500;
        tcmpb = tcntb>>1;

        __raw_writel(tcntb, S3C2410_TCNTB(0));
        __raw_writel(tcmpb, S3C2410_TCMPB(0));
            
        tcon &= ~0x1f;
        tcon |= 0xb;        //start timer
        __raw_writel(tcon, S3C2410_TCON);

        tcon &= ~2;
        __raw_writel(tcon, S3C2410_TCON);
    }

    return 0;
}





static int tq2440_irq_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
    unsigned long err;
    int i,down;

    if (!ev_press)
    {
        if (filp->f_flags & O_NONBLOCK)
            return -EAGAIN;
        else
            wait_event_interruptible(button_waitq, ev_press);
    }

    ev_press = 0;

    err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));
    

    if(pp)
    {
        for(i=0;i<4;i++)
        {
            s3c2410_gpio_setpin(gpio_table, 1);
        }
    }

    return err ? -EFAULT : min(sizeof(key_values), count);
}

static unsigned int tq2440_irq_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    =   tq2440_irq_open,
    .release    =   tq2440_irq_close,
    .read    =   tq2440_irq_read,
    .poll    =   tq2440_irq_poll,
    .ioctl        =   tq2440_pwm_ioctl,
};

static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};

static int __init dev_init(void)
{
    int ret;
    
    int i;
    
    for (i = 0; i < 4; i++)
    {
        s3c2410_gpio_cfgpin(gpio_table, gpio_cfg_table);
        s3c2410_gpio_setpin(gpio_table, 1);
    }

    ret = misc_register(&misc);

    printk (DEVICE_NAME" initialized\n");

    return ret;
}

static void __exit dev_exit(void)
{
    misc_deregister(&misc);
}

module_init(dev_init);
module_exit(dev_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("www.embedsky.net");
MODULE_DESCRIPTION("IRQ Test for EmbedSky SKY2440/TQ2440 Board");
级别: 新手上路
UID: 43143
精华: 0
发帖: 8
金钱: 40 两
威望: 8 点
综合积分: 16 分
注册时间: 2011-04-14
最后登录: 2011-04-26
4楼  发表于: 2011-04-17 10:14
驱动的Makefile
obj-m    += button.o
测试程序
#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>

int main(void)
{
    int i;
    int buttons_fd;
    char key_value[4];
    char first = 1;

    /*打开键盘设备文件*/
    buttons_fd = open("/dev/IRQ-Test", 0);
    if (buttons_fd < 0)
    {
        perror("open device buttons");
        exit(1);
    }

    for (;;)
    {
        char key_value_temp[4];
        int ret;

        /*开始读取键盘驱动发出的数据,注意key_value和键盘驱动中定义为一致的类型*/
        ret = read(buttons_fd, key_value_temp, sizeof(key_value_temp));
        if (ret != sizeof(key_value_temp))
        {
            perror("read buttons:");
            exit(1);
        }

        /*打印键值*/
        for (i = 0; i < sizeof(key_value); i ++)
        {
            if(key_value != key_value_temp)
            {
                key_value = key_value_temp;
                printf("K%d is %s%s", i+1, key_value == '0' ? "up" : "down", first ? ", " : "");
                if(key_value!='0')
                ioctl(buttons_fd, 1);
                else ioctl(buttons_fd, 0);
            }
        }
        first = 0;
        if(first == 0)
            printf("\n");
    }

    /*关闭设备文件句柄*/
    close(buttons_fd);
    return 0;
}
测试程序的Makefile
CROSS=arm-linux-

all: buttons

buttons:buttons.c
    $(CROSS)gcc -o buttons buttons.c
    $(CROSS)strip buttons
clean:
    @rm -vf buttons *.o *~
级别: 新手上路
UID: 43143
精华: 0
发帖: 8
金钱: 40 两
威望: 8 点
综合积分: 16 分
注册时间: 2011-04-14
最后登录: 2011-04-26
5楼  发表于: 2011-04-17 10:19
我用的是TQ2440开发板,有可能LED接的管脚不太一样,这是我在原来驱动基础上改的,我现在再看串口驱动,看不懂,大家交流一下啊,有什么书推荐一下吗,谢谢了
级别: 侠客
UID: 39689
精华: 0
发帖: 69
金钱: 350 两
威望: 70 点
综合积分: 138 分
注册时间: 2011-03-11
最后登录: 2012-04-22
6楼  发表于: 2011-04-17 11:17
3q,在看看
级别: 新手上路
UID: 38048
精华: 0
发帖: 6
金钱: 45 两
威望: 9 点
综合积分: 12 分
注册时间: 2011-02-20
最后登录: 2011-04-27
7楼  发表于: 2011-04-17 21:23

 回 3楼(shufangqian) 的帖子

驱动我就是按照你这样写的,编译也没有错~~~可是insmod的时候,就报错了,怎么回事啊?

# insmod pirs.ko
Unable to handle kernel NULL pointer dereference at virtual address 00000040
pgd = c3a7c000
[00000040] *pgd=33a5e031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1]
last sysfs file: /sys/devices/virtual/sound/timer/dev
Modules linked in: pirs(+)
CPU: 0    Not tainted  (2.6.32.2 #16)
PC is at sys_init_module+0x98/0x1e8
LR is at sys_init_module+0x9c/0x1e8
pc : [<c0230ad4>]    lr : [<c0230ad8>]    psr: 80000013
sp : c3a3bf88  ip : 00000000  fp : beae0ea4
r10: 00000000  r9 : c3a3a000  r8 : c01fd024
r7 : 001d8fb8  r6 : 00000000  r5 : bf000394  r4 : 00000000
r3 : 00000040  r2 : 00000001  r1 : 00000000  r0 : 00000000
Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: c000717f  Table: 33a7c000  DAC: 00000015
Process insmod (pid: 769, stack limit = 0xc3a3a270)
Stack: (0xc3a3bf88 to 0xc3a3c000)
bf80:                   001d8fb8 0000110e 001d8fa8 0000110e ffffffff beae0f88
bfa0: 00000080 c01fcea0 0000110e ffffffff 001d8fb8 0000110e 001d8fa8 beae0f88
bfc0: 0000110e ffffffff beae0f88 00000080 00000000 00000002 00000000 beae0ea4
bfe0: beae0cf8 beae0ce8 0002c024 00009310 20000010 001d8fb8 00000000 00000000
[<c0230ad4>] (sys_init_module+0x98/0x1e8) from [<c01fcea0>] (ret_fast_syscall+0x0/0x28)
Code: e1a04006 ea000003 e595313c e1a0e00f (e793f104)
---[ end trace 9ba1661a26102ee8 ]---
Segmentation fault