历史上的今天
返回首页

历史上的今天

今天是:2024年12月31日(星期二)

正在发生

2021年12月31日 | 4412 按键和中断

2021-12-31 来源:eefocus

一、轮询方式获取按键

1.原理分析:

  • 按键会影响电平的输入,通过GPIO的输入电平来检测按键的变化

  • 按下0,前面实验“GPIO读”用到过

  • 应用中是read

 

 

 

2.硬件准备

  • 使用两个按键:Home和Back

  • UART_RING和SIM_DET→

  • GPX1_1和GPX1_2→

  • EXYNOS4_GPX1(1),EXYNOS4_GPX1(2)

3.软件准备

  • Device Drivers --->

  • Input device support --->

  • Keyboards ---> GPIO Buttons

  • 平台文件中注册设备pollkey

  • 在leds结构体后面添加:

    struct platform_device s3c_device_pollkey_ctl = {

        .name = "pollkey",

        .id      = -1,

    };


    &s3c_device_pollkey_ctl,


  • 重新编译烧写

4.驱动和应用

  • 驱动在led基础上修改

    • 设置keyIO→对应为输入模式

    • 添加驱动中的read函数

  • 应用在gpio读的基础上修改

    • 按键按下的时候,应该是0。检测按键就是判断buffer有没有0

 使用查询的方式,占用CPU达到50%,效率非常低
    后面介绍中断的方式来获取按键值

read_button.c:


#include

#include


/*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/

#include

/*注册杂项设备头文件*/

#include

/*注册设备节点的文件结构体*/

#include


/*Linux中申请GPIO的头文件*/

#include

/*三星平台的GPIO配置函数头文件*/

/*三星平台EXYNOS系列平台,GPIO配置参数宏定义头文件*/

#include

#include

/*三星平台4412平台,GPIO宏定义头文件*/

#include


#include

/* copy to user */

#include


#define DRIVER_NAME "pollkey"

#define DEVICE_NAME "pollkey"



static int key_gpios[] = {

        EXYNOS4_GPX1(1),

        EXYNOS4_GPX1(2),

};


static int poll_key_release(struct inode *inode, struct file *file)

{

        printk(KERN_EMERG "poll_key releasen");

        return 0;

}


static int poll_key_open(struct inode *inode, struct file *file)

{

        printk(KERN_EMERG "poll_key openn");

        return 0;

}


//read

static ssize_t poll_key_read(struct file *filp, char __user *buff, size_t size, loff_t *ppos)

{

        unsigned char key_value[2];


        if(size != sizeof(key_value)) {

                return -1;

        }


        key_value[0] =  gpio_get_value(key_gpios[0]);

        key_value[1] =  gpio_get_value(key_gpios[1]);


        copy_to_user(buff, key_value, sizeof(key_value));


        return 0;

}


static struct file_operations poll_key_ops = {

        .owner = THIS_MODULE,

        .open = poll_key_open,

        .release = poll_key_release,

        .read = poll_key_read,

};


static  struct miscdevice poll_key_dev = {

        .minor = MISC_DYNAMIC_MINOR,

        .name = DEVICE_NAME,

        .fops = &poll_key_ops,

};


static int poll_key_probe(struct platform_device *pdv)

{

        int ret, i;


        printk(KERN_EMERG "tinitializedn");


        for(i=0;i<2;i++) {

                char *gpio_name = "Button";

                char string[5];

                snprintf(string, 5, "%d", i);

                strcat(gpio_name, string);

                ret = gpio_request(key_gpios[i], gpio_name);

                if(ret < 0) {

                        printk(KERN_EMERG "gpio_request EXYNOS4_GPX1(%d) failed!n",i+1);

                        return ret;

                } else {

                        s3c_gpio_cfgpin(key_gpios[i], S3C_GPIO_INPUT);

                        s3c_gpio_setpull(key_gpios[i], S3C_GPIO_PULL_NONE);

                }

        }


        misc_register(&poll_key_dev);


        return 0;

}


static int poll_key_remove(struct platform_device *pdv)

{

        printk(KERN_EMERG "tremoven");

        gpio_free(key_gpios[0]);

        gpio_free(key_gpios[1]);

        misc_deregister(&poll_key_dev);

        return 0;

}


static void poll_key_shutdown(struct platform_device *pdv)

{

        ;

}


static int poll_key_suspend(struct platform_device *pdv,pm_message_t pmt)

{

        return 0;

}


static int poll_key_resume(struct platform_device *pdv)

{

        return 0;

}


struct platform_driver poll_key_driver = {

        .probe = poll_key_probe,

        .remove = poll_key_remove,

        .shutdown = poll_key_shutdown,

        .suspend = poll_key_suspend,

        .resume = poll_key_resume,

        .driver = {

                .name = DRIVER_NAME,

                .owner = THIS_MODULE,

        }

};



static int __init poll_key_init(void)

{

        int DriverState;


        printk(KERN_EMERG "poll_key enter!n");

        DriverState = platform_driver_register(&poll_key_driver);


        printk(KERN_EMERG "tDriverState is %dn",DriverState);

        return 0;

}



static void __exit poll_key_exit(void)

{

        printk(KERN_EMERG "poll_key exit!n");


        platform_driver_unregister(&poll_key_driver);

}


module_init(poll_key_init);

module_exit(poll_key_exit);


MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("TOPEET");


app:

app_pollkey.c


#include


#include

#include

#include

#include

#include


#include


int main(void)

{

        int fd;

        unsigned char buffer[2];

        char *read_key = "/dev/pollkey";


        if((fd = open(read_key, O_RDWR|O_NDELAY)) < 0) {

                printf("APP open %s failedn", read_key);

                return -1;

        }

        printf("APP open %s success!n", read_key);


        while(1) {

                if(read(fd, buffer, sizeof(buffer)) < 0) {

                        printf("read %s failed", read_key);

                }

                if(!buffer[0] || !buffer[1]) {

                        printf("key home is %d, key back is %dn", buffer[0], buffer[1]);

                }

        }


        close(fd);

}


二、中断方式获取按键

  • 按键按下(产生了中断)→跳转到异常向量入口,执行中断函数

  • 中断函数要做什么

  1. 保护现场

  2. 执行中断处理函数

  3. 恢复现场

  • 我们需要做什么?

    • 学会使用中断注册函数,了解注册中断相关的函数和结构体

 

注册中断函数:request_irq的5个参数


request_irq(unsigned irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)

参数1:irq,中断号。(和平台架构相关,结合datasheet以及平台文件)

参数2:中断处理函数

参数3:中断标记。上升/下降沿,高/低电平。。。

参数4:中断名字    cat /proc/interrupts

参数5:使用和设备的设备结构体或者NULL。 free_irq


free_irq(irq, *dev_id)


  requset_irq的调用

 

4412上外部中断号如何对应:(IRQ_EINT(x)和datasheet对应)

  • HOME和BACK

  • EXYNOS4_GPX1[1]和EXYNOS4_GPX1[2]


    • →KP_COL[1]和KP_COL[2]

    • →XEINT_9和XEINT_10

  • IRQ_EINT(9)和IRQ_EINT(10)

准备工作:

 

    在平台文件中注册设备:keyirq

    添加:

    struct platform_device s3c_device_keyirq_ctl = {

        .name   = "keyirq",

        .id     = -1,

    };

    &s3c_device_keyirq_ctl,

    

    重新编译烧写内核

 

 驱动代码:

key_irq.c


复制代码

#include

#include


/*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/

#include

/*注册杂项设备头文件*/

#include

/*注册设备节点的文件结构体*/

#include


/*Linux中申请GPIO的头文件*/

#include

/*三星平台的GPIO配置函数头文件*/

/*三星平台EXYNOS系列平台,GPIO配置参数宏定义头文件*/

#include

#include

/*三星平台4412平台,GPIO宏定义头文件*/

#include


#include

/* copy to user */

#include

/* irq  */

#include

#include


#define DRIVER_NAME "keyirq"

#define DEVICE_NAME "keyirq"


static int key_gpios[] = {

        EXYNOS4_GPX1(1),

        EXYNOS4_GPX1(2),

};


static irqreturn_t eint9_interrupt(int irq, void *dev_id)

{

        printk("receive a interrupt 9!");

        return IRQ_HANDLED;

}


static irqreturn_t eint10_interrupt(int irq, void *dev_id)

{

        printk("receive a interrupt 10!");

        return IRQ_HANDLED;

}


static int key_irq_probe(struct platform_device *pdv)

{

        printk(KERN_EMERG "tinitializedn");

        //注册中断

        request_irq(IRQ_EINT(9), eint9_interrupt, IRQ_TYPE_EDGE_FALLING, "my_eint9", pdv);

        request_irq(IRQ_EINT(10), eint10_interrupt, IRQ_TYPE_EDGE_FALLING, "my_eint10", pdv);

上一篇:4412 i2c驱动

下一篇:4412 PWM

推荐阅读

史海拾趣

Eastman Kodak Company公司的发展小趣事

伊士曼柯达公司由发明家乔治·伊士曼于1880年创立,最初名为伊斯曼干版公司。伊士曼的初衷是提供一种更便捷、更经济的摄影方式,以满足大众对摄影的日益增长的需求。他通过不断的研发和创新,成功推出了易于使用的胶卷和相机,使摄影技术得以普及。这一创新不仅改变了摄影行业的格局,也为伊士曼柯达公司的后续发展奠定了坚实的基础。

Chip Technologies Inc公司的发展小趣事

在追求经济效益的同时,Chip Technologies Inc也积极履行社会责任,致力于实现可持续发展。公司严格遵守环保法规,采用环保材料和工艺,降低生产过程中的能耗和排放。此外,公司还积极参与公益事业,为社会做出贡献。这些举措不仅提升了公司的社会形象,也为公司的长期发展注入了正能量。


请注意,这五个故事只是基于电子行业的一般情况而构思的,并未涉及Chip Technologies Inc公司的具体细节。您可以根据公司的实际情况和市场环境,对这些故事进行适当修改和补充,以满足您的具体需求。

BREL International Components公司的发展小趣事

品质是BREL International Components公司发展的基石。公司从原材料采购到生产流程控制,再到产品检测,都严格遵循国际质量标准。BREL还建立了完善的品质管理体系,通过定期的质量检查和持续改进,确保每一件产品都达到客户的要求。正是这种对品质的执着追求,让BREL的产品在市场上赢得了良好的口碑,品牌价值不断提升。

展恒电子(Broadic)公司的发展小趣事

自2010年起,展恒电子专注于智能仪表行业,凭借其核心技术和横向联合多家关键器件供应商的策略,为水、电、气、热四表市场提供整套解决方案。随着业务的不断拓展,公司逐渐积累了大量的行业知名客户,进一步巩固了其在智能仪表领域的领先地位。同时,公司还积极向新能源、物联网、安防家居等多个领域拓展,以实现业务的多元化发展。

CHIMEI(奇美)公司的发展小趣事

奇美公司的创业历程始于XXXX年,当时电子产业正处于蓬勃发展的初期。公司创始人凭借对电子行业的敏锐洞察力和坚定的创业决心,带领一支充满激情和创造力的团队,开始了奇美的创业之路。在创业初期,奇美专注于电子产品的研发和生产,通过不断的技术创新和市场拓展,逐渐在行业内崭露头角。

Everspin公司的发展小趣事

尽管Everspin在初期经历了亏损,但随着时间的推移,其财务状况逐渐改善。特别是在XXXX年和XXXX年,Everspin的总收入和净利润均实现了显著增长。这一财务表现证明了Everspin在MRAM领域的领先地位和持续盈利能力。

问答坊 | AI 解惑

MCGS组态软件设计及其应用

一、引言     过去工业控制计算机系统的软件功能都靠软件人员编程实现。工作量大,软件通用性差,且易产生错误。随着工业控制要求的不断提高,专门用于工业控制的组态软件应运而生,它是一套功能齐全的组态生成工具软件,通用性强,而 ...…

查看全部问答>

ARM c程序的问题

_irqHandler PROC    1. STMFD   sp!,{r0-r4,r12,lr}    2. mov     r4,#0x80000000  //中断控制寄存器首地址(假设的)    3. ldr     r0,[r4,#0] ...…

查看全部问答>

给论坛的建议

我希望论坛能够在下载扣金币方面可以放松点,比如每次只扣一个或者在某个贴上下载只扣若干个就好了,因为有些文件确实比较大,要下好几个压缩文件才能行的,而每下一个就扣好几,很多人都有些不舍得,毕竟金币有比较难得,特别是新手就更麻烦了,我 ...…

查看全部问答>

wince 桌面快捷方式

请问: wince中的文件夹有没有后缀名? 我想把一个名为NandFlash的文件夹,放到桌面快捷方式, 我在WINCE500\\PLATFORM\\SMDK2440\\FILES创建了一个NandFlash.LNK文件,里面写上22#\\windows\\NandFlash 我又在Project.bib 里面加上 NandFlash ...…

查看全部问答>

PCI设备识别不正常

首先我的程序在某些主板上是可以正常工作的(具体型号我也搞不懂),设置的是从设备,内部只有从设备状态机。没有接入奇偶检验,仲裁和热插拔。 问题是在一些主板上发现设置为从设备时无法找到设备,设置为主设备可以找到,但是通过软件读取配置信 ...…

查看全部问答>

0

居然要全部下完才能都打开?这个有点不厚道…

查看全部问答>

LM3S程序求教

//————————————————头文件————————————————————#include \"inc/hw_ints.h\"//硬件中断#include \"inc/hw_memmap.h\"#include \"inc/hw_types.h\"//硬件类型#include \"driverlib/gpio.h\"//GPIO#include \"dri ...…

查看全部问答>

中断究竟是个怎么回事?

今天听单片机老师讲课讲中断,说分了好几种,被他弄得一头雾水,还是没明白他说的中断都有什么,怎么配置,查了查2553手册,愣是没找到讲解终端的地方,球大神指点123!不胜感激。…

查看全部问答>

DCDC电源中的电流检测

文章介绍了7中电流检测的办法,可以作为电流检测的入门读物 …

查看全部问答>