您现在的位置:首页 > >

ESP32开发之路(3)--

发布时间:

ESP32开发之路(3)? 点亮第一个LED灯及按键输入

本次开发是在Ubuntu下的,使用的模块是GOOUUU-ESP32,使用VSCode编辑项目。基于工程:ESP32开发之路(2)? HelloWorld工程分析和优化


一、点亮第一个LED灯

复制hello_world文件并命名为led_key,修改hello_world_main.c为app_main.c;

然后将工作区保存在led_key文件夹下:

通过硬件原理图查询可得,LED连在GPIO2上;所以首先宏定义LED的引脚编号:


#define GPIO_LED_NUM 2

然后定义一个gpio配置结构体


/* 定义一个gpio配置结构体 */
gpio_config_t gpio_config_structure;

对该结构体进行初始化,配置并使能


/* 初始化gpio配置结构体*/
gpio_config_structure.pin_bit_mask = (1ULL << GPIO_LED_NUM);/* 选择gpio2 */
gpio_config_structure.mode = GPIO_MODE_OUTPUT; /* 输出模式 */
gpio_config_structure.pull_up_en = 0; /* 不上拉 */
gpio_config_structure.pull_down_en = 0; /* 不下拉 */
gpio_config_structure.intr_type = GPIO_PIN_INTR_DISABLE; /* 禁止中断 */

/* 根据设定参数初始化并使能 */
gpio_config(&gpio_config_structure);

然后将其设为高电*,点亮该LED灯:


/* 输出高电*,点亮LED*/
gpio_set_level(GPIO_LED_NUM, 1);

然后我们可以看到开发板上的蓝色LED已经亮起来了:


二、LED闪烁

我们编写一个while循环,让LED一秒闪烁一次


while(1)
{
gpio_set_level(GPIO_LED_NUM, 0); /* 熄灭 */
vTaskDelay(500 / portTICK_PERIOD_MS); /* 延时500ms*/
gpio_set_level(GPIO_LED_NUM, 1); /* 点亮 */
vTaskDelay(500 / portTICK_PERIOD_MS); /* 延时500ms*/
}

烧录,运行结果:


三、按键电*检测

查看硬件原理图,BOOT按键连在GPIO0上,并且已经上拉;所以首先宏定义BOOT按键的引脚编号


#define GPIO_KEY_NUM 0

然后对gpio配置结构体进行初始化,配置并使能


/* 初始化gpio配置结构体*/
gpio_config_structure.pin_bit_mask = (1ULL << GPIO_KEY_NUM);/* 选择gpio0 */
gpio_config_structure.mode = GPIO_MODE_INPUT; /* 输入模式 */
gpio_config_structure.pull_up_en = 0; /* 不上拉 */
gpio_config_structure.pull_down_en = 0; /* 不下拉 */
gpio_config_structure.intr_type = GPIO_PIN_INTR_DISABLE; /* 禁止中断 */

/* 根据设定参数初始化并使能 */
gpio_config(&gpio_config_structure);

然后我们1s查询一次按键电*,并打印出来


while(1)
{
printf("Boot_key Level is : %d
",gpio_get_level(GPIO_KEY_NUM)); /* 获取BOOT按键电*并打印 */
vTaskDelay(1000 / portTICK_PERIOD_MS); /* 延时1000ms*/
}

运行结果,检测成功


四、循环检测按键是否按下

我们创建一个按键检测任务检测是否有按键按下,在主任务里执行LED的闪烁
首先我们查看一下这个freeRTOS的优先级可选范围,查询得知configMAX_PRIORITIES=25,所以任务优先级可选范围为0~24,且数字越大,优先级越高!


/* 定义按键检测任务的任务句柄*/
TaskHandle_t Key_Task_Handler;
/* 声明按键检测任务函数 */
void key_task(void *pvParameters);

然后在主任务里创建按键检测任务,


/* 创建按键检测任务 */
xTaskCreatePinnedToCore((TaskFunction_t )key_task, /* 任务函数 */
(const char* )"key task", /* 任务名称*/
(uint16_t )2048, /* 任务堆栈大小,单位为字节*/
(void* )NULL, /* 传递给任务函数的参数*/
(UBaseType_t )20, /* 任务优先级,最高优先级为24 */
(TaskHandle_t* )&Key_Task_Handler, /* 任务句柄*/
(const BaseType_t)tskNO_AFFINITY); /* 指定运行任务的CPU,使用这个宏表示不会固定到任何核上*/

然后我们实现按键检测任务函数,注意,portTICK_PERIOD_MS的值为10,即RTOS的一个时间片为10ms,则使用vTaskDelay()函数进行延时,不能小于10ms


/* 按键检测任务函数 */
void key_task(void *pvParameters)
{
static int key_up = 1; /* 按键松开标志 */
while (1)
{
/* 检测按键是否按下 */
if (key_up && (gpio_get_level(GPIO_KEY_NUM) == 0) )
{
vTaskDelay(50 / portTICK_PERIOD_MS); /* 延时50ms消抖*/
key_up = 0;
if (gpio_get_level(GPIO_KEY_NUM) == 0)
{
/* 按键BOOT按下,按键按下处理*/
printf("BOOT Key pressed!
");
}
}
else if(gpio_get_level(GPIO_KEY_NUM) == 1 )
{
key_up = 1; /* 按键已松开 */
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}

烧录后的实现效果如下,同时LED正常闪烁


五、补充

说一下任务创建函数,因为我之前看的freeRTOS,任务创建函数是xTaskCreate,然后我特意找了一下idf里的xTaskCreate函数,发现是调用了xTaskCreatePinnedToCore()函数,

所以以后创建任务在不需要指定哪个内核运行的时候,可以使用xTaskCreate()函数


/* 创建按键检测任务 */
xTaskCreate((TaskFunction_t )key_task, /* 任务函数 */
(const char* )"key task", /* 任务名称*/
(uint16_t )2048, /* 任务堆栈大小,单位为字节*/
(void* )NULL, /* 传递给任务函数的参数*/
(UBaseType_t )20, /* 任务优先级,最高优先级为24 */
(TaskHandle_t* )NULL); /* 任务句柄,在不需要使用任务句柄时,可以填入NULL*/

六、代码

最后贴上整个app_main.c的代码


#include
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "driver/gpio.h"

#define GPIO_LED_NUM 2
#define GPIO_KEY_NUM 0

/* 定义按键检测任务的任务句柄*/
TaskHandle_t Key_Task_Handler;
/* 声明按键检测任务函数 */
void key_task(void *pvParameters);

void app_main(void)
{
/* 打印Hello world! */
printf("Hello world!
");

/* 定义一个gpio配置结构体 */
gpio_config_t gpio_config_structure;

/* 初始化gpio配置结构体*/
gpio_config_structure.pin_bit_mask = (1ULL << GPIO_LED_NUM);/* 选择gpio2 */
gpio_config_structure.mode = GPIO_MODE_OUTPUT; /* 输出模式 */
gpio_config_structure.pull_up_en = 0; /* 不上拉 */
gpio_config_structure.pull_down_en = 0; /* 不下拉 */
gpio_config_structure.intr_type = GPIO_PIN_INTR_DISABLE; /* 禁止中断 */

/* 根据设定参数初始化并使能 */
gpio_config(&gpio_config_structure);

/* 初始化gpio配置结构体*/
gpio_config_structure.pin_bit_mask = (1ULL << GPIO_KEY_NUM);/* 选择gpio0 */
gpio_config_structure.mode = GPIO_MODE_INPUT; /* 输入模式 */
gpio_config_structure.pull_up_en = 0; /* 不上拉 */
gpio_config_structure.pull_down_en = 0; /* 不下拉 */
gpio_config_structure.intr_type = GPIO_PIN_INTR_DISABLE; /* 禁止中断 */

/* 根据设定参数初始化并使能 */
gpio_config(&gpio_config_structure);

/* 输出高电*,点亮LED*/
gpio_set_level(GPIO_LED_NUM, 1);
#if 1
/* 创建按键检测任务 */
xTaskCreate((TaskFunction_t )key_task, /* 任务函数 */
(const char* )"key task", /* 任务名称*/
(uint16_t )2048, /* 任务堆栈大小,单位为字节*/
(void* )NULL, /* 传递给任务函数的参数*/
(UBaseType_t )20, /* 任务优先级,最高优先级为24 */
(TaskHandle_t* )NULL); /* 任务句柄,在不需要使用任务句柄时,可以填入NULL*/
#else
/* 创建按键检测任务 */
xTaskCreatePinnedToCore((TaskFunction_t )key_task, /* 任务函数 */
(const char* )"key task", /* 任务名称*/
(uint16_t )2048, /* 任务堆栈大小,单位为字节*/
(void* )NULL, /* 传递给任务函数的参数*/
(UBaseType_t )20, /* 任务优先级,最高优先级为24 */
(TaskHandle_t* )&Key_Task_Handler, /* 任务句柄*/
(const BaseType_t)tskNO_AFFINITY); /* 指定运行任务的CPU,使用这个宏表示不会固定到任何核上*/
#endif
while(1)
{
gpio_set_level(GPIO_LED_NUM, 0); /* 熄灭 */
vTaskDelay(500 / portTICK_PERIOD_MS); /* 延时500ms*/
gpio_set_level(GPIO_LED_NUM, 1); /* 点亮 */
vTaskDelay(500 / portTICK_PERIOD_MS); /* 延时500ms*/
}

while(1)
{
printf("Boot_key Level is : %d
",gpio_get_level(GPIO_KEY_NUM)); /* 获取BOOT按键电*并打印 */
vTaskDelay(1000 / portTICK_PERIOD_MS); /* 延时1000ms*/
gpio_set_level(GPIO_LED_NUM, 0); /* 熄灭 */
}


}

/* 按键检测任务函数 */
void key_task(void *pvParameters)
{
static int key_up = 1; /* 按键松开标志 */
while (1)
{
/* 检测按键是否按下 */
if (key_up && (gpio_get_level(GPIO_KEY_NUM) == 0) )
{
vTaskDelay(50 / portTICK_PERIOD_MS); /* 延时50ms消抖*/
key_up = 0;
if (gpio_get_level(GPIO_KEY_NUM) == 0)
{
/* 按键BOOT按下,按键按下处理*/
printf("BOOT Key pressed!
");
}
}
else if(gpio_get_level(GPIO_KEY_NUM) == 1 )
{
key_up = 1; /* 按键已松开 */
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}


热文推荐
猜你喜欢
友情链接: