ESP8266 RTOS开发之路(3)— 点亮第一个LED灯及按键输入

ESP8266 RTOS开发之路(3)— 点亮第一个LED灯及按键输入

一、前言

本次开发基于虚拟机下的Ubuntu18系统,ESP8266_RTOS_SDK版本为v3.4-rc,使用的模块是ESP8266-NodeMcu,其板载模组为ESP12E,flash大小为32Mbit,图片如下:
在这里插入图片描述

二、点亮第一个LED灯

在上一个hello_world工程的基础上复制文件并命名为01_led_key,修改hello_world_main.capp_main.c,
在这里插入图片描述
通过查询硬件原理图可得,ESP12E上自带的LED连在GPIO2上;所以首先宏定义LED的引脚编号:

#define GPIO_LED_NUM 2 

添加gpio头文件包含

#include "driver/gpio.h"

然后定义一个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_INTR_DISABLE;        /* 禁止中断 */ 

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

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

    /* 输出低电平,点亮LED*/
    gpio_set_level(GPIO_LED_NUM, 0);

app_mian.c修改为如下所示

/* Hello World Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.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 

void app_main()
{
    printf("Hello world!\n");
    
    /* 1.定义一个gpio配置结构体 */
	gpio_config_t gpio_config_structure;

    /* 2.初始化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_INTR_DISABLE;        /* 禁止中断 */ 

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

    /* 4.输出低电平,点亮LED*/
    gpio_set_level(GPIO_LED_NUM, 0);

    while (1) 
    {
        printf("Hello world!\n");
        printf("SDK version:%s\n", esp_get_idf_version());  
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

然后编译烧录运行,我们可以看到ESP12E模组上的蓝色LED已经亮起来了:
在这里插入图片描述

三、LED闪烁

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

    while(1)
    {
        gpio_set_level(GPIO_LED_NUM, 1);        /* 熄灭 */
        vTaskDelay(500 / portTICK_PERIOD_MS);   /* 延时500ms*/
        gpio_set_level(GPIO_LED_NUM, 0);        /* 点亮 */
        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_INTR_DISABLE;    /* 禁止中断 */ 

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

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

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

运行结果,检测成功
在这里插入图片描述

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

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

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

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

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

然后我们实现按键检测任务函数,注意,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!\n");
            }
        }
        else if(gpio_get_level(GPIO_KEY_NUM) == 1 )
        {
            key_up = 1;     /* 按键已松开 */
        }
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

烧录后的实现效果如下,同时LED正常闪烁
在这里插入图片描述

    /* 创建按键检测任务 */
    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 <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "driver/uart.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!\n");

    /* 定义一个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_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_INTR_DISABLE;    /* 禁止中断 */ 

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

    /* 输出低电平,点亮LED*/
    gpio_set_level(GPIO_LED_NUM, 0);

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

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

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

/* 按键检测任务函数 */
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!\n");
            }
        }
        else if(gpio_get_level(GPIO_KEY_NUM) == 1 )
        {
            key_up = 1;     /* 按键已松开 */
        }
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

六、附录

上一篇:ESP8266 RTOS开发之路(1)— 搭建在Ubuntu下的开发环境
下一篇:

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值