1、如何在VSCode和ESP-IDF的环境下创建工程

说实话,这是我用ESP-IDF在VSCode环境下最不喜欢的事情,在一顿CSDN和百度之后,很多大佬博主都推荐使用VSCode,通过官方示例来进行工程创建,好处是所需要的头文件都已经准备好了,同时很有可能会以及写好你所需要的外设的驱动头文件,看似非常省力。
但是!坑又非常非常的多!当我在example示例文件夹中看到了关于矩阵键盘的示例,我满心欢喜的打开,想着不是从零敲矩阵键盘扫描了,结果在一次次编译失败中我逐渐抓狂,一个.c文件可以高达9个报错,而且还完全没法修复。后来在拜读大佬博主——夏虫不可与之言冰的文章后,询问到为何矩阵键盘的示例工程无法编译通过,大佬的回答为:“底层上好像依赖S2的硬件,如果你是esp32是编译不了的”。所以,如果我以该官方示例作为创建工程的参考,那有可能会一直出现问题,毕竟报错的不是main函数,而是功能.c文件。
在这要非常感谢夏虫不可与之言冰,各位也可以看看他的文章,对于ESP32的初学者的我来讲,受益匪浅。从0学起的esp-idf之旅——外设篇gpio 坑多归坑多,但对于一些简单的执行器外设,像LED、蜂鸣器、数码管什么的,从官方例程进行创建项目还是很便捷的,步骤可以大大省略。

1.1 使用VSCode命令行创建新工程

  1. Ctrl + Shift + P唤出命令行,并输入New Project
  2. 点击ESP-IDF:新建项目后会让你输入工程名(不要有中文)、工程路径(不要有中文)、开发板型号以及对应的COM口
  3. 输入完毕后点击右下角“Choose Template”,会进入选择官方例程界面,记住选择“ESP-IDF”
  4. 挑选你要依赖的官方例程
  5. 创建新工程并打开新工程界面
    点击红色框内的按钮后,右下角会有弹出提示是否要在新窗口打开工程,点击“yes”即可
  6. 更改.c文件名,同时删除一些对你没用的文件
    以blink例程为例,在完成上述创建后,进入main文件夹中直接将blink.c改成你想要的文件名,同时别忘了,在工程目录中的Makefile文件中的PROJECT_NAME := 后面的字符串该为修改后的文件名。
    接下来就是删除对我们没什么作用的内容,下图中框起来的,想删就删,不删也不影响。
  7. 修改.c文件,编写自己所要的代码

1.2 使用ESP-IDF CMD创建工程

如果说用VSCode以官方例程为依赖创建新工程是为了便利,那通过ESP-IDF CMD创建工程就是为了简洁。
在ESP32学习笔记( VSCode + ESP-IDF环境) 1 中我们可以通过ESP-IDF 的CMD命令框,通过idf.py命令进行工程编译和烧录,那我们同样用idf.py可以创建新工程。
步骤如下:

  1. 创建新工程文件夹(不要有中文)
  2. 打开ESP-IDF CMD窗口 cd到刚刚创建的工程文件目录
  3. 键入命令:idf.py create-project 工程名(不要是中文)
  4. 在VSCode中打开刚刚的工程文件夹就会看到如下的文件
  5. 继续回到CMD命令窗口,先cd到工程文件夹内,再通过命令:idf.py set-target esp32设置目标开发板为esp32,再看VSCode就会发现多出来几个文件,在设置目标开发板后会进行编译,同时会将对应SDKConfig加入。
  6. 在.c文件中开始进行编码,引入需要的头文件即可

使用ESP-IDF CMD命令进行工程创建,工程会变得非常简洁,但这需要你对ESP32所用的头文件非常熟悉,不然有限功能函数你无法调用,或者你无法得知哪个头文件是你所需要的。
综合考虑下来,如果是小白,对头文件还不熟悉,你可以使用例程为依托创建新工程,如果是大佬,那您随意!!!

2、ESP-IDF环境下的简单外设驱动

之前在Arduino IDE的环境中我写了很多单独模块的测试函数,既然现在开始使用VSCode以及ESP-IDF进行ESP32的开发了,那单独的模块测试也少不了,但由于使用ESP-IDF进行开发较为复杂,导致很多模块的开发还未完成,我会在后面慢慢的补上。
因为电路原理图和所用的单片机与嵌入式系统竞赛实训平台在之前的Arduino环境中都已经介绍过了,这里就不多浪费篇幅,直接上代码、接线说明和效果

2.1 一灯大师——点亮LED

只要是使用IO口输出,第一件事就是点亮LED灯
接线:GPIO19 -------- LED_IO

实验效果:LED间隔1S亮灭

代码:

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

#define BLINK_GPIO 19

void app_main(void)
{

    gpio_reset_pin(BLINK_GPIO);
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);

    while(1) 
    {
        printf("Turning off the LED\n");
        gpio_set_level(BLINK_GPIO, 0);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        printf("Turning on the LED\n");
        gpio_set_level(BLINK_GPIO, 1);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

2.2 蜂鸣器

接线:
GPIO 5 -------- LED_IO
GPIO 17 -------- BEEP_IO

实验效果:LED间隔1S亮灭,同时蜂鸣器间隔1S鸣叫和停止

代码:

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

#define BLINK_GPIO 5
#define BEEP_GPIO 17

void app_main(void)
{
    gpio_reset_pin(BLINK_GPIO);
    gpio_reset_pin(BEEP_GPIO);

    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_direction(BEEP_GPIO, GPIO_MODE_OUTPUT);
    
    while(1) {
        printf("关闭\n");
        gpio_set_level(BLINK_GPIO, 0);
        gpio_set_level(BEEP_GPIO, 0);
        vTaskDelay(1000 / portTICK_PERIOD_MS);

        printf("打开\n");
        gpio_set_level(BLINK_GPIO, 1);
        gpio_set_level(BEEP_GPIO, 1);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

2.3 数码管显示

接线:
GPIO 21 -------- SMG_245_A
GPIO 19 -------- SMG_245_B
GPIO 18 -------- SMG_245_C
GPIO 05 -------- SMG_245_D
GPIO 17 -------- SMG_245_E
GPIO 16 -------- SMG_245_F
GPIO 04 -------- SMG_245_G
GPIO 02 -------- SMG_245_DP
GPIO 27 -------- SMG_138_A
GPIO 14 -------- SMG_138_B
GPIO 12 -------- SMG_138_C

实验效果:8个数码管依次显示0~7

esp32 外接flash esp32 外接键盘_esp32 外接flash

代码:

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

#define LSA_GPIO 27
#define LSB_GPIO 14
#define LSC_GPIO 12

const int shumaguanPins[8] = {21, 19, 18, 5, 17, 16, 4, 2};

//显示1-10 高电平有效
unsigned char smgduan[10][8] =
{
  {1, 1, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 0, 0, 0},   //0 1
  {1, 1, 0, 1, 1, 0, 1, 0}, {1, 1, 1, 1, 0, 0, 1, 0},   //2 3
  {0, 1, 1, 0, 0, 1, 1, 0}, {1, 0, 1, 1, 0, 1, 1, 0},   //4 5
  {1, 0, 1, 1, 1, 1, 1, 0}, {1, 1, 1, 0, 0, 0, 0, 0},   //6 7
  {1, 1, 1, 1, 1, 1, 1, 0}, {1, 1, 1, 1, 0, 1, 1, 1}    //8 9
};

void app_main(void)
{
    gpio_reset_pin(LSA_GPIO);
    gpio_reset_pin(LSB_GPIO);
    gpio_reset_pin(LSC_GPIO);

    for(int i = 0; i < 8; i++)
    {
        gpio_reset_pin(shumaguanPins[i]);
    }
    
    gpio_set_direction(LSA_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_direction(LSB_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_direction(LSC_GPIO, GPIO_MODE_OUTPUT);

    for(int i = 0; i < 8; i++)
    {
        gpio_set_direction(shumaguanPins[i], GPIO_MODE_OUTPUT);
    }

    while(1) {
        unsigned char i, j;
        for (i = 0; i < 8; i++)
        {
            switch (i)
            {
                case(0):gpio_set_level(LSA_GPIO, 0);gpio_set_level(LSB_GPIO, 0);gpio_set_level(LSC_GPIO, 0);break;
                case(1):gpio_set_level(LSA_GPIO, 1);gpio_set_level(LSB_GPIO, 0);gpio_set_level(LSC_GPIO, 0);break;
                case(2):gpio_set_level(LSA_GPIO, 0);gpio_set_level(LSB_GPIO, 1);gpio_set_level(LSC_GPIO, 0);break;
                case(3):gpio_set_level(LSA_GPIO, 1);gpio_set_level(LSB_GPIO, 1);gpio_set_level(LSC_GPIO, 0);break;
                case(4):gpio_set_level(LSA_GPIO, 0);gpio_set_level(LSB_GPIO, 0);gpio_set_level(LSC_GPIO, 1);break;
                case(5):gpio_set_level(LSA_GPIO, 1);gpio_set_level(LSB_GPIO, 0);gpio_set_level(LSC_GPIO, 1);break;
                case(6):gpio_set_level(LSA_GPIO, 0);gpio_set_level(LSB_GPIO, 1);gpio_set_level(LSC_GPIO, 1);break;
                case(7):gpio_set_level(LSA_GPIO, 1);gpio_set_level(LSB_GPIO, 1);gpio_set_level(LSC_GPIO, 1);break;
                default:break;
            }
            for(j = 0; j < 8 ; j++)
            {
                gpio_set_level(shumaguanPins[j], smgduan[i][j]);
            }
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            for(j = 0; j< 8; j++) //消隐
            {
                gpio_set_level(shumaguanPins[j], 0);
            }
        }
        
    }
}

2.4 红外对射+继电器

接线:
GPIO 04 -------- RL_IO
GPIO 16 -------- IRF_IO

实验效果:
手遮住红外对射,继电器吸合,手放开,继电器断开


红外继电器演示


代码:

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

#define RELAY_GPIO 4
#define IRF_GPIO 16

void app_main(void)
{
    gpio_reset_pin(RELAY_GPIO);
    gpio_reset_pin(IRF_GPIO);

    gpio_set_direction(RELAY_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_direction(IRF_GPIO, GPIO_MODE_INPUT);

    while(1) {
        if (gpio_get_level(IRF_GPIO) == 1)
        {
            gpio_set_level(RELAY_GPIO, 0);  //低电平继电器断开
        }
        else
        {
            gpio_set_level(RELAY_GPIO, 1);
        }
        
        vTaskDelay(200 / portTICK_PERIOD_MS);
    }
}

持续更新中…