2·ESP32-C3入门教程——按键基本法

这篇具有很好参考价值的文章主要介绍了2·ESP32-C3入门教程——按键基本法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【写在前面】经过了点灯→定时器点灯→PWM点灯的学习之后,逐渐开始对ESP32 C3整体的框架有了一定认识【 点灯模块链接指路:http://t.csdn.cn/xOBmI】也掌握了一些理解和学习代码的思路,这一章咱们聊一聊按键的控制。

目录

GPIO输出与按键控制

level 1:从一个朴实无华的点按开始

level 2:引入队列、中断——实现按键控制2.0

优化代码、引入队列,实现多按键控制

通过线程的方式完成中断

小结


GPIO输出与按键控制

level 1:从一个朴实无华的点按开始

        首先咱们了解下按键的硬件板块(以我手上的板子为例),可以发现按键按下电路导通对应低电平。2·ESP32-C3入门教程——按键基本法

        于是咱们可以使用最好理解的方法,从点按开始,光速上手按键模块:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"

#define KEY1_IO      9
#define KEY2_IO      8

#define LED_RED_IO 		10  //咱们借用红灯作为按键指示灯

#define LED_ON          0   //这个板子是共阳极,低电平亮
#define LED_OFF         1


void initKey()  //按键初始化(选择和设置为IO输入)
{
    gpio_pad_select_gpio(KEY1_IO);
    gpio_pad_select_gpio(KEY2_IO);
    gpio_set_direction(KEY1_IO, GPIO_MODE_INPUT);
    gpio_set_direction(KEY2_IO, GPIO_MODE_INPUT);
}

void initLed()   //因为灯咱们也用到了,所以也要初始化
{
    gpio_pad_select_gpio(LED_RED_IO);
    gpio_set_direction(LED_RED_IO, GPIO_MODE_OUTPUT);  
}


int key_read_key1(void)     //一个很笨的方法,直到松开才触发下一步,否则一直等待松开
{
    if(gpio_get_level(KEY1_IO)==0)
    {
        while (gpio_get_level(KEY1_IO)==0)
        {
            vTaskDelay(1);
        }
        return 1;
    }
    return 0;
}

int key_read_key2(void)     //同上
{
    if(gpio_get_level(KEY2_IO)==0)
    {
        while (gpio_get_level(KEY2_IO)==0)
        {
            vTaskDelay(1);
        }
        return 1;
    }
    return 0;
}

void main()
{
    initKey();
    initLed();      
    while(1)        //主函数一定要while(1),不然刚通电程序就结束了        
    {
        if(key_read_key1())      gpio_set_level(LED_RED_IO, LED_ON);
        if(key_read_key2())      gpio_set_level(LED_RED_IO, LED_OFF);
    }
}

        编译,烧录,监视一气呵成~ level 1轻松秒杀,那要不要试下长按呢?

        想实现长按其实也挺简单的,基于level1的代码简单魔改就能实现,只需要引入"esp_system.h"中的函数esp_timer_get_time(),可以获取内置定时器当时的时间,我们可以用这个作为flag,判断低电平状态和高电平的时间差。代码如下:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_system.h"

#define KEY1_IO      9
#define KEY2_IO      8

#define LED_RED_IO 		10  

#define LED_ON          0    
#define LED_OFF         1


void initKey()  //和短按无变化,具体注释看短按
{
    gpio_pad_select_gpio(KEY1_IO);
    gpio_pad_select_gpio(KEY2_IO);
    gpio_set_direction(KEY1_IO, GPIO_MODE_INPUT);
    gpio_set_direction(KEY2_IO, GPIO_MODE_INPUT);
}

void initLed()   //相比短按无变化,具体注释看短按
{
    gpio_pad_select_gpio(LED_RED_IO);
    gpio_set_direction(LED_RED_IO, GPIO_MODE_OUTPUT);  
}

void key_read_key1(void)     // //相比短按,引入了flag和
{
    int flag = 0;
    if(gpio_get_level(KEY1_IO)==0)
    {
        flag = esp_timer_get_time();
        while(gpio_get_level(KEY1_IO)==0)
        {
            vTaskDelay(1);
        }
        flag = esp_timer_get_time() - flag;
        if(flag > 500*1000)  gpio_set_level(LED_RED_IO, LED_ON);
        else                 gpio_set_level(LED_RED_IO, LED_OFF);
    }
}


void app_main()
{
    initKey();
    initLed(); 
    while (1)
    {
        key_read_key1();
    }
}

        恭喜,如果上面的代码基本理解了,就已经可以做出一些小的模块了。但,这就满足了吗?

level 2:引入队列、中断——实现按键控制2.0

        上面的方法用于实现按键控制,虽然很好理解,但在功能上总是不大理想的,如果只是考试还好,在一个具体的项目工程中,这种代码比较冗余且不利于后续的拓展,此时就需要我们更进一步,引入队列、线程、中断、回调的概念,来实现框架化、模块化的按键控制2.0。

        对于入门来说,需要注意的地方其实还是不少,但是有了level1 的信心,level2 开始上点难度总不过分吧qwq,本文的所有代码我都统一了风格,可以通过比较的方式看看为了实现新功能新增了什么,改动了什么。

优化代码、引入队列,实现多按键控制

  • 怎么样实现按键不松手就能输出一个按键长按?
  • 拒绝重复if else ,如何简化多个按键之间的代码?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "freertos/queue.h"
#include "esp_system.h"     //多用了几个新的头文件
#include "sdkconfig.h"

#define KEY1_IO      9
#define KEY2_IO      8

#define LED_RED_IO 		10  //咱们借用红灯作为按键指示灯key1
#define LED_BLUE_IO     6   //再用一个蓝灯指示key2

#define LED_ON          0   //这个板子是共阳极,低电平亮
#define LED_OFF         1

static xQueueHandle gpio_evt_queue = NULL; //句柄地址先设置为0,点灯的文章中解释过

void IRAM_ATTR gpio_isr_handler(void *arg)  //创建了一个中断回调函数
{
    uint32_t gpio_num = (u_int32_t) arg;  
    xQueueSendFromISR(gpio_evt_queue,&gpio_num,NULL);   //插入一个中断到队列中
}

void initLed()   //因为灯咱们也用到了,所以也要初始化
{
    gpio_pad_select_gpio(LED_RED_IO);
    gpio_set_direction(LED_RED_IO, GPIO_MODE_OUTPUT);
    gpio_set_level(LED_RED_IO, LED_OFF);
    gpio_pad_select_gpio(LED_BLUE_IO);
    gpio_set_direction(LED_BLUE_IO, GPIO_MODE_OUTPUT);    
    gpio_set_level(LED_BLUE_IO, LED_OFF);
}

void initKey()  //这里和上面的代码变化很大,是另一种配置IO口的方法
{
    gpio_config_t io_conf;      //这边赋值的方式不够简洁,但是好理解
    io_conf.intr_type = GPIO_INTR_ANYEDGE;      //上升下降沿中断均可触发
    io_conf.pull_up_en = 1;     //上拉使能
    io_conf.mode = GPIO_MODE_INPUT;             //io口输入模式
    io_conf.pin_bit_mask = (1<<KEY1_IO) | (1<<KEY2_IO);  //通过操控寄存器的方式


    gpio_config(&io_conf); //上面是结构体赋值,赋好值了这里就要调用了

    gpio_evt_queue = xQueueCreate(2,sizeof(uint32_t));      //创建一个大小为2的队列

    gpio_install_isr_service(0);                                   //释放资源
    gpio_isr_handler_add(KEY1_IO,gpio_isr_handler,(void*)KEY1_IO); //初始化,返回esp_ok
    gpio_isr_handler_add(KEY2_IO,gpio_isr_handler,(void*)KEY2_IO);
}

void key_scan()    //因为我们上面配置的是上升沿、下降沿均可触发,所以按键按下就会立刻进入中断
{
    uint32_t io_num;
    bool     ret=0;
    xQueueReceive(gpio_evt_queue,&io_num,portMAX_DELAY);
    if(gpio_get_level(io_num)==0)
    {
        int flag=esp_timer_get_time();
        while(gpio_get_level(io_num)==0)
        {
            vTaskDelay(1);
            if(flag < esp_timer_get_time()-1000*1000)
            {
                gpio_set_level(LED_RED_IO, LED_ON);
                printf("按键长按\n");
                flag = esp_timer_get_time();
                ret = 1;
            }
        }
        if(ret == 0 && flag > esp_timer_get_time()-1000*1000)
            {
                gpio_set_level(LED_RED_IO, LED_OFF);
                printf("按键短按\n");
                ret = 0;
            }
    }

}

void app_main()
{  
    initKey();
    initLed();
    while(1)
    {
        vTaskDelay(1);
        key_scan();
    }
}

通过线程的方式完成中断

        实际工程中,我们当然不可能把按键扫描放到主函数的循环中,因为按键的响应速度会受到前面任务的影响,当我们按下按键时,肯定希望的是立刻得到反馈,那么,怎样实现不论程序进行什么,只要按键按下就能立刻响应? 

        经过了前面的铺垫,只需要在最后加入一个gpio_task_example(void* arg),并通过xTaskCreate调用即可,需要增添和修改的两个部分如下图所示:2·ESP32-C3入门教程——按键基本法

         下载之后,我们在监控中可以发现,虽然while(1)中只做了日志打印,但是每当按下按键的时候,中断都会立刻响应。

2·ESP32-C3入门教程——按键基本法     

        这个框架下想要加入和调整新功能都非常方便了(0 0总算搞定了),可以做成key.h和key.c,在根目录下封装到component里面。

小结

        前期学习的时候,代码一定不能CTRL C +V,最好理解之后自己手敲一遍,这一章全部都是手敲的,然后就发现了一些平常没有注意到的问题,思路更加严谨,也熟悉了整体的框架。

        点灯和按键其实代表最基本的 input output 的概念,而在我想要这个基础上加入一点好玩的东西,通过层层递进的方式学到更多的概念,也许更加符合项目的需要和拓展。

        从着手写 "不止点亮一个灯" 到写 "按键基本法" ,刚好是7天,春节期间经常需要走亲访友,所以都是等到整块的时间做的思考,毕竟一个完整的程序思路打断了还是不好调整的。不过也挺好的,整段时间可以拿来研究一个完整的程序,零碎时间;可以学各种API的用法,还有补自己的漏洞(真的很多)有的时候不知不觉时间就过去了,也算是心流状态;这让我保持了一个很好的心态,碰到问题就记录下自己的思路,学一段时间再回看,有时候忽然就理解了,再隔一段时间,甚至会觉得“怎么这么简单的东西当时都不会?”这是一个神奇的变化过程。

        下一篇就要聊聊WIFI模块了,毕竟还是要做物联网板块的,没有wifi怎么行(●ˇ∀ˇ●)文章来源地址https://www.toymoban.com/news/detail-418910.html

到了这里,关于2·ESP32-C3入门教程——按键基本法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ESP32入门教程】ESP32开发板原理图,引脚图,引脚功能,ESP WROOM 32,介绍ESP32硬件

    记录本人学习历程,同时也分享给大家学习,仅供参考! 模组共有38个管脚,具体描述如下。 1. GPIO6至GPIO11 引脚 控制集成在模组内部的SPI Flash, 不建议用于其他功能 。 SCK/CLK GPIO6 SDO/SD0 GPIO7 SDI/SD1 GPIO8 SHD/SD2 GPIO9 SWP/SD3 GPIO10 SCS/CMD GPIO11 2.Strapping 管脚 ESP32共有5个Strapping管脚,。

    2024年02月08日
    浏览(65)
  • Arduino ESP32开发环境搭建入门教程,esp32的arduino开发环境搭建教程,arduino导入eps32开发插件

    从官网下载 Arduino IDE 软件并安装。下载链接:Software | Arduino 网盘链接:链接:https://pan.baidu.com/s/1ZuSbo1BPy8XyyXzfl4KNzg?pwd=f8yd 提取码:f8yd 1、找到Arduino IDE安装目录,打开hardware文件夹。 2、在hardware文件夹中创建一个espressif文件夹。 3、将解压出的文件夹移动到espressif文件夹中,

    2024年02月13日
    浏览(53)
  • ESP系列入门教程(一)——之用继电器简单驱动一个LED【附 ESP32 / ESP8266 通用代码】

    最近在跟着几个大佬的教学视频做项目。陆续会更新记录一些要点,便于后期总结笔记的时候进行引用。 也可以帮助有心跟着一起复刻的宝子们,更好地捋清思路。 【本系列教程 - 总目标】: 使用ESP系列板卡,通过MQTT进行数据通信,达到远程控制多个传感器的效果。 ◆配

    2024年01月19日
    浏览(46)
  • c3p0 数据池入门使用教程

    从零开始手写 mybatis (三)jdbc pool 如何从零手写实现数据库连接池 dbcp? 万字长文深入浅出数据库连接池 HikariCP/Commons DBCP/Tomcat/c3p0/druid 对比 Database Connection Pool 数据库连接池概览 c3p0 数据池入门使用教程 alibaba druid 入门介绍 数据库连接池 HikariCP 性能为什么这么快? Apache

    2024年03月15日
    浏览(54)
  • 【Arduino环境下驱动合宙esp32c3单片机基本外设】

    本教程是参加FastBond2活动主题4 - 测量仪器中的【Arduino环境下驱动合宙esp32c3单片机基本外设】。 围绕FastBond2阶段1——基于ESP32C3开发的简易IO调试设备项目需求开发。 设计目标: 多种数字和模拟信号的输入输出:用户可以选择不同的输入输出模式,并通过设备的操作界面进行

    2024年02月04日
    浏览(54)
  • 【esp32c3配置arduino IDE教程】

    本文主线FastBond2阶段1——基于ESP32C3开发的简易IO调试设备,esp32c3环境搭建,设计目标如下 设计用户操作界面,该设备具备简单易用的操作界面,外加显示屏SSD1306和旋转编码器进行显示和控制,用户后期可进行二次开发WiFi或蓝牙连接电脑或手机监控。 多种数字和模拟信号的

    2024年02月03日
    浏览(54)
  • 006.合宙ESP32-C3+蓝牙调试器通过BLE发送接收数据教程

    在平衡小车制作过程中,需要对KP/KD/KSP/KSI等PID系数进行调试,而平衡小车无法通过USB等进行有线调试,而ESP32-C3自带蓝牙+WIFI,使用WIFI比较吃算力,故选择通过蓝牙进行调参,同时能够将Angle/Encoder/PWM等数据回传至手机端进行查看。 前期通过查找资料,发现合宙ESP32-C3自带蓝

    2024年02月03日
    浏览(54)
  • 新上架的简约版合宙ESP32C3使用arduino开发的教程

    经过两个月的缺货下架后,9块9包邮的合宙ESP32C3又重新上架了,真香。这一批都是没有带串口芯片的简约版(9块9要啥自行车)。在下架前,简约版要使用2.0.0版本的ESP32开发板库才能下载,而2.0.0版本有一些丢失arduino自带库的诡异BUG,所以一直没法用于下载。现在由于发布了2

    2024年02月05日
    浏览(87)
  • ESP8266入门教程12:自动配网

    下载第三方库WiFiManager到lib文件夹  ​git clone https://github.com/tzapu/WiFiManager.git 第2行:包含WiFiManager库的头文件 第12行:创建WiFiManager对象 第14行:配置自动配网热点名称 1、编译并上传固件,然后使用手机连接名称叫做“ESP8266-Auto”的WIFI热点 2、点击【Configure WiFi】开始配网,

    2024年02月12日
    浏览(50)
  • ESP8266物联网开发入门教程

    B站本图文链接https://b23.tv/F7tPcAm 先消除一下零基础爱好者的担忧:这玩意有点C语言基础就能搞,学不会我就把键盘吃了 教程适用于刚入门得小白,根据教程自行拓展就可以用8266开发出属于自己的智能家电,希望能帮助到大家|・ω・`) 一:需要的硬件:电脑、8266开发板(笔

    2023年04月08日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包