ESP32_S3

本文介绍了如何在基于FreeRTOS的嵌入式系统中使用ESPTimer进行按键中断处理,并通过定时器回调实现任务间的通信。作者详细展示了初始化定时器、安装中断服务函数以及创建任务的过程。
摘要由CSDN通过智能技术生成

 1.Task_key_timer

#include <stdio.h>

#include "freertos/FreeRTOS.h"

#include "freertos/task.h"

#include "driver/gpio.h"

#include "esp_timer.h"

#define E(name) static void name(void *params)

#define KEY1_GPIO GPIO_NUM_0

#define KEY2_GPIO GPIO_NUM_1

#define KEY3_GPIO GPIO_NUM_2

#define KEY4_GPIO GPIO_NUM_3

static TaskHandle_t t1;

static esp_timer_handle_t key_timer;

// 入口函数

E(task1_entry)

{

    while (1)

    {

        uint32_t notify_value = 0;

        // 等待通知到达(阻塞)

        BaseType_t res = xTaskNotifyWait(

            0x03,               // 接收通知之前要清空的位(0x00表示不清空) // 0xFFFFFFFF,         // 清空所有位

            0x00,               // 退出的时候清空哪些位

            &notify_value,      // 获取直达任务通知的值

            pdMS_TO_TICKS(1000) // 等待时长

        );

        if (res == pdTRUE)

        {

            printf("获得任务通知: %X\n", notify_value);

            // 清空标志位

            // ulTaskNotifyValueClear(

            //     t1,  // 操作哪个任务的标志位

            //     0x00 // 清空哪些位

            // );

        }

        else

        {

            printf("我没收到通知\n");

        }

        vTaskDelay(pdMS_TO_TICKS(2000));//延时两秒

    }

    vTaskDelete(NULL);

}

/** 定时器消抖

 *  1. 初始化定时器

 *  2. 安装中断服务函数

 *          在中断服务函数中打开定时器

 *  3. 定时器回调函数判断按键

 */

/**

 * @brief 定时器回调函数

 * 这是个任务回调函数,不是中断回调

 * 所以要使用 xTaskNotify 而不是 xTaskNotifyFromISR

 */

static void key_timer_cb(void *args)

{

    // 查看是否还是为低电平,如果持续为低电平,说明确实被按下了

    // 如果不为低电平,说明是没有被按下

    if (gpio_get_level(KEY1_GPIO) == 0)

    {

        // 被按下了

        xTaskNotify(

            t1,       // 接收通知的任务句柄

            1,        // 通知值

            eSetBits // 通知方式

        );

    }

}

/**

 * @brief 按键中断定时器初始化

 */

static void key_timer_init()

{

    // 1. 设置定时器参数表

    esp_timer_create_args_t timer_args = {

        .callback = key_timer_cb, // 回调函数

        .name = "key_timer",      // 定时器名称

    };

    // 创建定时器

    esp_timer_create(

        &timer_args, // 参数表

        &key_timer   // 句柄

    );

}

static void key_dd_isr_handler(void *arg)

{

    // 启动定时器,20ms 查询是否为低电平

    // 1s = 1000 ms

    // 1ms = 1000 us

    esp_timer_start_once(key_timer, 20000); // 20 ms 后启动,消除抖动

    // esp_timer_start_periodic(key_timer,20000);      // 每间隔 20ms 启动一次

}

/**

 * @brief 中断服务函数原型

 */

static void key_isr_handler(void *arg)

{

    uint32_t value = *((uint32_t *)arg);

    // 触发中断

    xTaskNotifyFromISR(

        t1,       // 接收通知的任务句柄

        value,    // 通知值

        eSetBits, // 通知方式

        NULL      // 是否优做切换

    );

}

uint32_t key1_value = 1;

uint32_t key2_value = 2;

uint32_t key3_value = 3;

void app_main(void)

{

   

    key_timer_init();

    // 创建任务

    xTaskCreate(

        task1_entry, // 任务入口函数

        "Task1",     // 任务名称

        4 * 1024,    // 栈空间大小 字数非字节数  在大多数系统中,一个字的大小是 4 字节,16384 字节或 16KB。

        NULL,        // 参数指针

        1,           // 优先级

        &t1          // 句柄

    );

    // 初始化按键中断

    // 1. 初始化 gpio

    gpio_config_t key_cfg = {

        .pin_bit_mask = (1ULL << KEY1_GPIO) |

                        (1ULL << KEY2_GPIO) |

                        (1ULL << KEY3_GPIO) , // 按键的 GPIO 掩码

        .mode = GPIO_MODE_INPUT,             // 设置为输入模式

        .pull_up_en = GPIO_PULLUP_ENABLE,    // 因为 GPIO 0 接地导通,下降沿触发,所以上拉使能

        .intr_type = GPIO_INTR_NEGEDGE       // 下降沿触发

    };

    gpio_config(&key_cfg);

    // 2. 设置中断类型

    // 写不写无所谓,在 gpio_config_t 中的 intr_type 已经设置了

    // gpio_set_intr_type(

    //     KEY1_GPIO,         // 要设置的 GPIO

    //     GPIO_INTR_NEGEDGE // 中断触发方式

    // );

    // 3. 启用中断服务

    gpio_install_isr_service(0); // 启用中断服务

    // 4. 安装中断服务函数

    gpio_isr_handler_add(

        KEY1_GPIO,       // 要安装的 gpio 编号

        key_dd_isr_handler, // 函数地址(名称)

        NULL      // 参数

    );

    gpio_isr_handler_add(KEY2_GPIO, key_isr_handler, &key2_value);

    gpio_isr_handler_add(KEY3_GPIO, key_isr_handler, &key3_value);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值