再开始一个单片机的学习之前,如果无从下手,可以先从他人视频或者官方文档找灵感。

官方文档编程指南:

GPIO & RTC GPIO - ESP32-S3 - — ESP-IDF 编程指南 v5.5.1 文档

一、外设初始化:

1.gpio_config()初始化对应IO口输入输出等模式

结构体参数赋值:

/**
 * @brief Configuration parameters of GPIO pad for gpio_config function
 */
typedef struct {
    uint64_t pin_bit_mask;          /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
    gpio_mode_t mode;               /*!< GPIO mode: set input/output mode                     */
    gpio_pullup_t pull_up_en;       /*!< GPIO pull-up                                         */
    gpio_pulldown_t pull_down_en;   /*!< GPIO pull-down                                       */
    gpio_int_type_t intr_type;      /*!< GPIO interrupt type                                  */
#if SOC_GPIO_SUPPORT_PIN_HYS_FILTER
    gpio_hys_ctrl_mode_t hys_ctrl_mode;       /*!< GPIO hysteresis: hysteresis filter on slope input    */
#endif
} gpio_config_t;

不同于32,我们需要在CMakeLists文件中进行配置

ESP-IDF 是 组件(component)系统,用 CMake 管理,需要显示声明依赖

如果用到了 driver/gpio.h  要加上REQUIRES driver ;意思是 我这个代码要用到 driver 这个库,请把它加进工程。

二、实现代码逻辑

//设置电平
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level)
{
    GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG);
    gpio_hal_set_level(gpio_context.gpio_hal, gpio_num, level);
    return ESP_OK;
}


//获取电平
int gpio_get_level(gpio_num_t gpio_num)
{
    return gpio_hal_get_level(gpio_context.gpio_hal, gpio_num);
}

需要注意的是:

main函数最后要加 vTaskDelay(10 / portTICK_PERIOD_MS) 进行延时操作 

freertos要求每个线程任务必须都要有阻塞 :

(1)方便各个任务切换 (2)延时是最简单的任务阻塞 

ESP-IDF框架内部默认打开了看门狗

添加多个文件的时候,必须要修改CmakeLists

三、通过线程创建来控制按键开关灯

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

#define LED_PIN         GPIO_NUM_1   // LED连接的GPIO引脚
#define KEY_PIN         GPIO_NUM_40  // 按键连接的GPIO引脚


// 任务函数:控制LED闪烁
void led_task(void *pvParameters)
{
    while(1)
    {
        gpio_set_level(LED_PIN, 1);
        vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时1秒
        gpio_set_level(LED_PIN, 0);
        vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时1秒
    }
}

void app_main(void)
{
    printf("\n*****************\nIO TEST Demo!\n*****************\n");
        // 配置LED引脚
    gpio_config_t led_conf = {
        .pin_bit_mask = (1ULL << LED_PIN),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_ENABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
    };
    gpio_config(&led_conf);
 
    // 配置按键引脚(启用内部上拉,未按下时为高电平)
    gpio_config_t key_conf = {
        .pin_bit_mask = (1ULL << KEY_PIN),
        .mode = GPIO_MODE_INPUT,
        .pull_up_en = GPIO_PULLUP_ENABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
    };
    gpio_config(&key_conf);

    xTaskCreate(
        led_task,   // 任务函数
        "led_task", // 任务名称
        2048,       // 任务栈大小(字节)
        NULL,       // 任务参数
        5,          // 任务优先级
        NULL        // 任务句柄
    );  
    
    while(1)
    {
        // 读取按键状态
        if(gpio_get_level(KEY_PIN) == 0) // 按键按下时为低电平
        {
            if (gpio_get_level(KEY_PIN) == 0) // 再次确认
            {
                // 等待释放
                while (gpio_get_level(KEY_PIN) == 0)
                {
                    vTaskDelay(10 / portTICK_PERIOD_MS); // 不要忙等
                }      
                vTaskDelay(20/ portTICK_PERIOD_MS); // 去抖释放
                printf("Key pressed\n");
            }
        }

        vTaskDelay(10 / portTICK_PERIOD_MS);    

    }

}

更多推荐