0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

i.MX6ULL 驱动开发7—按键输入捕获与GPIO输入配置与高低电平读取

码农爱学习 来源:码农爱学习 作者:码农爱学习 2022-05-24 09:11 次阅读

前面几篇文章,从最基础的寄存器点灯,到设备树点灯,再到GPIO子系统点灯,一步步了解嵌入式Linux开发的各种点灯原理。

点灯用到的都是GPIO的输出功能,这篇,通过按键的使用,来学习GPIO输入功能的使用。

1 硬件介绍

1.1 板子上按键原理图

先来看原理图,我板子上有4个按键sw1~sw4:

1.1.1 SW1

SW1是板子的系统复位按键,不可编程使用

poYBAGKLpYCAWgGbAABoFfKP0ZQ203.png

1.1.2 SW2、SW3

SW2:SNVS_TAMPER1,GPIO5_1

平时是低电平,按下去是高电平。

SW3:ONOFF

它也是系统级的按键,用于长按进行开关机。

poYBAGKLpYiAIG8MAAEcqcr0uho168.png

1.1.3 SW4

SW4是BOOT_MODE1脚,用来进行串行烧录模式切换,需要再与复位键配合使用。

本篇仅测试按键功能,因此可以该按键。

pYYBAGKLpZGAK9H6AAC3fSuYo7o389.png

1.1.4 使用其中2个按键

板子上这4个按键的功能特性如下表:

poYBAGKLpZiAd5wyAAGktTu1GEw782.png

本实验使用SW2和SW4这两个按键来进行实验。

pYYBAGKLpaCAGqlpAAYpy1niae8060.png

2 软件编写

2.1 修改设备树文件

2.1.1 修改iomuxc节点

修改imx6ull-myboard.dts,在iomuxc节点的imx6ull-evk字节点下创建一个名为pinctrl_key的子节点,节点内容如下:

pinctrl_key: keygrp { 
    fsl,pins = < 
        MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01    0x3080 /* SW2 */
        MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11      0xF080 /* SW4 */
    >; 
};

这部分是对引脚进行配置,这两个引脚的定义是在imx6ull-pinfunc-snvs.h文件中:

poYBAGKLpamAHMjzAAHyvI3nUkY061.png

引脚宏定义后面的值,是对引脚功能的配置:

SW2:0x3080,即0011 0000 1000 0000

SW4:0xF080,即1000 0000 1000 0000

对照之前讲解GPIO的PAD寄存器的配置,根据两个按键的实际电路配置上拉或下拉。

/*
*bit 16:0 HYS关闭
*bit [15:14]: [00]下拉 [01]47k上拉 [10]100k上拉 [11]22k上拉 <---
*bit [13]: [0]kepper功能 [1]pull功能
*bit [12]: [0]pull/keeper-disable [1]pull/keeper-enable
*bit [11]: 0 关闭开路输出
*bit [10:8]: 00 保留值
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 000 输出disable <---
*bit [2:1]: 00 保留值
*bit [0]: 0 低转换率
*/

注:SW4 (MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11)这个GPIO,在设备中实际已经被其它设备(spi4)使用了。

在imx6ull-myboard.dts的300多行处,有:

pinctrl_spi4: spi4grp {
 fsl,pins = <
     MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10        0x70a1
     MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11        0x70a1
     MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07      0x70a1
     MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08      0x80000000
     >;
};

理论上我们应该把这里的配置给注释掉,因为1个IO是不能同时进行2种功能的。由于本次实验不使用spi4,暂且也先不管它,看看会有什么影响,如果影响了本实验,再给把这里的配置给注掉。

2.1.2 添加key节点

在根节点下创建名为key的按键节点,内容如下:

key { 
    #address-cells = <1>; 
    #size-cells = <1>; 
    compatible = "myboard-key"; 
    pinctrl-names = "default"; 
    pinctrl-0 = <&pinctrl_key>; 
    key1-gpio = <&gpio5 1 GPIO_ACTIVE_HIGH>;   /* SW2 */
    key2-gpio = <&gpio5 11 GPIO_ACTIVE_LOW>;   /* SW4 */
    status = "okay"; 
}; 

2.2 编写按键驱动程序

按键驱动,也属于字符设备驱动,和之前的字符设备驱动的框架一样,主要的修改点在按键的硬件初始化配置已经按键的读取。

新建一个key-Bsp.c

2.2.1 按键的硬件初始化

初始化的流程,就是使用OF函数来从设备树中获取key节点,然后使用GPIO子系统的API函数,将GPIO配置为输入。

static int keyio_init(void)
{
    keydev.nd = of_find_node_by_path("/key");
    if (keydev.nd== NULL) 
    {
        return -EINVAL;
    }

    keydev.key1_gpio = of_get_named_gpio(keydev.nd ,"key1-gpio", 0);
    keydev.key2_gpio = of_get_named_gpio(keydev.nd ,"key2-gpio", 0);
    if ((keydev.key1_gpio < 0)||(keydev.key2_gpio < 0))
    {
        printk("can't get key\r\n");
        return -EINVAL;
    }
    printk("key1_gpio=%d, key2_gpio=%d\r\n", keydev.key1_gpio, keydev.key2_gpio);

    /* 初始化key所使用的IO */
    gpio_request(keydev.key1_gpio, "key1");    /* 请求IO */
    gpio_request(keydev.key2_gpio, "key2");    /* 请求IO */
    gpio_direction_input(keydev.key1_gpio);    /* 设置为输入 */
    gpio_direction_input(keydev.key2_gpio);    /* 设置为输入 */
    return 0;
}

2.2.2 读取按键的值

读取按键的值,也是GPIO子系统的API函数来读取。读取到按键的值后,将该值传递出来给应用层使用,注意这里使用了原子操作的方式atomic_set和atomic_read实现数据的写入和读取。

/* 定义按键值 */
#define KEY1VALUE      0X01    /* 按键值       */
#define KEY2VALUE      0X02    /* 按键值       */
#define INVAKEY        0X00    /* 无效的按键值 */

static ssize_t key_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    int ret = 0;
    int value;
    struct key_dev *dev = filp->private_data;

    if (gpio_get_value(dev->key1_gpio) == 1)         /* key1按下 */
    {
        printk("get key1: high\r\n");
        while(gpio_get_value(dev->key1_gpio));       /* 等待按键释放 */
        atomic_set(&dev->keyvalue, KEY1VALUE);
    }
    else if (gpio_get_value(dev->key2_gpio) == 0)    /* key2按下 */
    {
        printk("get key2: low\r\n");
        while(!gpio_get_value(dev->key2_gpio));      /* 等待按键释放 */
        atomic_set(&dev->keyvalue, KEY2VALUE);
    }
    else
    {
        atomic_set(&dev->keyvalue, INVAKEY);        /* 无效的按键值 */
    }

    value = atomic_read(&dev->keyvalue);
    ret = copy_to_user(buf, &value, sizeof(value));
    return ret;
}

2.3 编写按键应用程序

新建一个key-App.c

按键的应用层程序,主要就通过驱动程序提供的按键读取接口,来循环读取按键的值,并在按键按下时,将按键的值打印出来。

/* 定义按键值 */
#define KEY1VALUE   0X01
#define KEY2VALUE   0X02
#define INVAKEY     0X00

int main(int argc, char *argv[])
{
    int fd, ret;
    char *filename;
    int keyvalue;

    if(argc != 2)
    {
        printf("Error Usage!\r\n");
        return -1;
    }

    filename = argv[1];

    /* 打开key驱动 */
    fd = open(filename, O_RDWR);
    if(fd < 0)
    {
        printf("file %s open failed!\r\n", argv[1]);
        return -1;
    }

    /* 循环读取按键值数据! */
    while(1)
    {
        read(fd, &keyvalue, sizeof(keyvalue));
        if (keyvalue == KEY1VALUE)
        {
            printf("KEY1 Press, value = %#X\r\n", keyvalue);
        }
        else if (keyvalue == KEY2VALUE)
        {
            printf("KEY2 Press, value = %#X\r\n", keyvalue);
        }
    }

    ret= close(fd); /* 关闭文件 */
    if(ret < 0)
    {
        printf("file %s close failed!\r\n", argv[1]);
        return -1;
    }
    return 0;
}

3 实验测试

3.1 编译程序

3.1.1 编译设备树

编译设备树文件,并将编译出的dtb文件复制到启动文件夹:

pYYBAGKLpbiAQbODAAE2bDoXQB8818.png

网络方式启动开发板,查看key节点:

poYBAGKLpb-ALdDQAAB4JCpPP_g827.png

3.1.2 编译按键驱动程序

pYYBAGKLpcWAA4N1AAGM4BH_H_4238.png

3.1.3 编译按键应用程序

poYBAGKLpcyAbDOhAADtMDDW8fo238.png

3.2 测试

pYYBAGKLpdKAcp5JAACb4X-uFHc021.png

3.3 查看CPU占用率

先Ctrl+C结束掉此按键进程,然后使用如下指令来后台运行按键程序:

./key-App /dev/key &

然后再使用指令:

top

来查看CPU是使用情况。从下图可以看出,此时CPU的使用率是99.8%,全被按键检查程序占用了,因为按键程序中有个while循环在一直读取按键的值。

poYBAGKLpdqAU5h5AAD4q6Bv6d0467.png

使用指令:

ps

查看按键的进程号,如下图为149,再使用:

kill -9 149

来杀掉按键进程,然后再使用top指令查看,可以看到CPU的使用率又变回了0。

pYYBAGKLpfSAPYlbAAC5aLytSzg805.png

实际的按键使用中,一般不会使用本篇的这种持续检测导致CPU占满的方式,本篇只是先来介绍GPIO的输入功能的使用,后续会使用更加高效的按键检测机制来实现按键检测功能。

4 总结

本篇主要介绍了i.MX6ULL的按键检测的使用,主要的知识点是设备树的修改,以及GPIO的输入配置与高低电平的读取。

poYBAGKLpf2AEdaoAADLKUk862g915.png

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    4976

    文章

    18239

    浏览量

    287890
  • Linux
    +关注

    关注

    87

    文章

    10978

    浏览量

    206671
  • GPIO
    +关注

    关注

    16

    文章

    1129

    浏览量

    50481
  • i.MX6
    +关注

    关注

    1

    文章

    36

    浏览量

    16224
收藏 人收藏

    评论

    相关推荐

    i.MX6UL/i.MX6ULL开发常见问题】单独编译内核,uboot生成很多文件,具体用哪一个?

    i.MX6UL/i.MX6ULL开发常见问题》基于米尔电子 i.MX6UL/i.MX6ULL产品(V.10)2.3单独编译内核,uboot
    发表于 07-01 17:50

    用FPGA的GPIO作为输入,采集高低电平

    我想用FPGA的GPIO口作为输入,采集外来的高低电平读取管脚数据的verilog语句怎么写,小白一枚,刚刚开始学习
    发表于 05-17 18:24

    使用迅为IMX6ULL开发板第一个汇编实验(一)

    驱动,在我们的开发板上板载了一个 led 发光二极管,他的实现原理就是通过 gpio 来控制 led 的亮灭(控制 gpio 输出高低电平
    发表于 06-17 14:34

    移植5.4内核到迅为I.MX6ULL开发

    编译器的搭建,可以参考“i.mx6ull终结者开发板使用手册”的4.3章节“搭建交叉编译环境”和29.1章节 安装第三方库。编译内核为了编译方便,我们可以创建一个脚本,我们在命令行输入“vi
    发表于 06-29 10:13

    I.MX6ULL终结者开发板裸机仿真jlink调试

    I.MX6ULL‘终结者’开发板预留了JTAG仿真接口,并给出了开发文档,可以实现在JLINK仿真器条件下的单步跟踪、断点调试等功能,使得开发研究i
    发表于 07-07 10:56

    迅为i.MX6ULL开发板资料下载,让Linux学习更轻松

    引脚 i.MX6ULL开发板底板资源 I.MX6ULL 开发板板载资源非常丰富,几乎已经把 i.MX6ULL 的功能发挥到了极致。1. 电
    发表于 09-23 18:07

    i.MX6ULL开发板硬件资源

    迅为i.MX6ULL 终结者开发板硬件资源非常丰富,几乎将 i.MX6ULL 芯片的所有资源都扩展引出到底板上了,底板提供了丰富的外设接口,开发板的尺寸是 190mm*125mm,充分
    发表于 12-29 06:18

    i.MX6ULL核心板资源

    路多功能音频通道多路 SPI、IIC、定时器、PWM、DMA、RTC、看门狗等常用外设规格参数:核心板配置CPU 型号 NXP i.MX6ULL(MCIMX6Y2C),ARM Cortex A
    发表于 07-12 17:50

    初识 i.MX6ULL 寄存器

    裸机开发_L1_汇编LED实验0. 本节目标1. 硬件层电路2. 初识 i.MX6ULL 寄存器2.1 i.MX6ULL 时钟控制寄存器2.2 i.MX6ULL IO复用寄存器2.3
    发表于 12-20 07:13

    I.MUX6ULL的初始化方法

    拉、速度等);4.使用GPIO输出高低电平。二、I.MX6ULL初始化1.使能时钟CCGR0-CCGR6,这七个寄存器控制着6ull所有外设
    发表于 03-02 06:18

    ARM裸机篇之i.MX6ULL处理器资料分享

    1、i.MX6ULL处理器启动过程i.MX6ULL是NXP基于ARM Cortex-A7内核的单核处理器家族,主频可以高900MHz。i.MX6ULL应用处理器包含了电源管理模块,可以
    发表于 04-14 16:42

    关于i.MX6ULL配置GPIO

    处理器,它的GPIO外设应该如何配置呢?今天小编就将通过飞凌嵌入式的OKMX6ULL-S开发板来为大家详细介绍。一、i.MX6ULL处理器的
    发表于 08-05 10:37

    STM32F103输入捕获--按键

    初始化七、中断初始化八、中断函数8.1 进入中断的条件8.2 高电平捕获的流程8.3 时间的计算8.4 伪代码8.5 可执行代码九、结果展示十、存在的问题一、输入捕获
    发表于 11-30 13:51 27次下载
    STM32F103<b class='flag-5'>输入</b><b class='flag-5'>捕获</b>--<b class='flag-5'>按键</b>

    i.MX6ULL学习笔记:GPIO按键输入捕获

    掌握GPIO输入输出是必备技能,这篇推文继续来学习操作GPIO,这篇主要学习GPIO输入,通过使用
    的头像 发表于 04-06 10:37 670次阅读

    基于i.MX6ULL的掉电检测设计与软件测试

    基于i.MX6ULL的掉电检测设计与软件测试基于i.MX6ULL平台设计实现掉电检测功能,首先选择一路IO,利用IO电平变化触发中断,在编写驱动
    的头像 发表于 11-09 10:40 459次阅读
    基于<b class='flag-5'>i.MX6ULL</b>的掉电检测设计与软件测试