《ESP32S3 Arduino开发指南 V1.0 》第七章 LED实验

第七章 LED实验


       本章将通过一个经典的点灯实验,带大家开启ESP32-S3 Arduino开发之旅。通过本章学习,我们将会学习到如何实现ESP32-S3的IO作为输出功能。

       本章分为如下几个小节:

       7.1 GPIO介绍

       7.2 硬件设计

       7.3 软件设计

       7.4 下载验证


        7.1 GPIO介绍

       在前面的第四章中,有对ESP32-S3的IO进行说明。ESP32-S3芯片具有45个物理 GPIO 管脚(GPIO0 ~ GPIO21和GPIO26 ~ GPIO48)。对于ESP32-S3模组引出的IO会变得更少些,只有36个。每个管脚都可用作一个通用IO,或连接一个内部外设信号,可见ESP32-S3的管脚的强大。

       “通用IO”,官方会称之为“GPIO”,英文详称为General-Purpose Input/output Port,通用输入/输出接口,当设置成输入模式可用于感知外界信号,设置成输出模式可用于控制外部设备。在开发中,我们经常会用到一些比较简单的外部模块:LED、按键等,使用它们其实很简单,只需要把它们跟芯片的GPIO连接,控制GPIO输出/读取高低电平即可。

       当管脚作为一个内部外设信号去使用,这种情况可以称之为引脚复用,通常就是作为某个协议的引脚。

       本章节就是介绍ESP32-S3管脚作为一个GPIO去点亮LED。


       7.1.1 ESP32-S3的GPIO简介

       ESP32-S3模组可作为GPIO的管脚情况如下图所示。


图7.1.1.1 ESP32-S3模组可做GPIO功能管脚图


       GPIO口输出来的信号是数字信号。数字信号是以0,1表示的不连续信号,也就是以二进制形式表示的信号。在Arduino中数字信号用高低电平来表示,高电平为数字信号1,低电平为数字信号0。如下图所示:


图7.1.1.2数字信号


       图中Arduino输出的低电平为0V,输出的高电平为当前Arduino的工作电压,对于ESP32-S3模组的工作电压为3.3V,则其高电平为3.3V。


       7.1.2 GPIO函数介绍

       本小节介绍到的函数可在以下文件中找到:

       Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32\esp32-hal-gpio.c

       当我们调用Arduino库的函数时,实际上调用的是arduino-esp32库里的函数。换句话来说,每个芯片的arduino库都会有相同的函数,当工程设定好开发板参数,就会调用该芯片的arduino库下的函数接口,如下图所示。


图7.1.2.1 不同芯片的Arduino库情况


       Arduino库有pinMode函数,同样的,其他芯片Arduino库也会有该函数的存在。唯一不同的就是该函数的实现会因芯片不同而不同。

       接下来,我们就介绍一下本章节所用到的GPIO函数。

       第一个函数:pinMode函数,该函数功能是设置引脚的工作模式。在使用输入或输出功能前,需要先通过pinMode函数配置引脚的模式为输入模式或输出模式。

void pinMode(uint8_t pin, uint8_t mode);

        参数pin为指定配置的引脚编号,比如要配置IO1,那么pin设置为1即可。

       参数mode为指定的配置模式,如下表所示。


表7.1.2.1 引脚配置的模式


       无返回值。

       第二个函数:digitalWrite函数,该函数功能是向指定引脚输出高低电平数字信号。

void digitalWrite(uint8_t pin, uint8_t value);

       参数pin为指定输出的引脚编号。

       参数value为要指定的输出电平,使用HIGH指定输出高电平,使用LOW指定输出低电平。HIGH和LOW是Arduino核心库定义的关键字,分别代表1和0,目的就是方便阅读、提高编程效率。当代码中使用了HIGH和LOW,在编译时,会分别替换为1和0。所以有时候,我们直接用1和0而不用HIGH和LOW。

       无返回值。

       第三个函数:digitalRead函数,该函数的功能是从指定引脚读取外部输入的数字信号。

int digitalRead(uint8_t pin);

       参数pin为指定读取状态的引脚编号。

       返回值:当外部输入高电平时,返回值为1;当外部输入低电平时,返回值为0。


        7.2 硬件设计


       1. 例程功能

       LED 灯:LED每过500ms一次交替闪烁,实现类似跑马灯的效果。


       2. 硬件资源


       1)LED灯

              LED-IO1


       3. 原理图

       本章用到的硬件有 LED 灯。电路在开发板上已经连接好,所以在硬件上不需要动任何东西,直接下载代码就可以测试使用。其连接原理图如下图所示。


图7.3.1 LED与ESP32-S3模组连接原理图

       从上图可知,若IO1输出低电平时,则LED亮起,反之,熄灭。


        7.3 软件设计


       7.3.1 程序流程图

       程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。

       下面看看本实验的程序流程图:


图7.3.1.1 程序流程图


       7.3.2 程序解析


       1. led驱动代码

       这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。LED驱动源码包括两个文件:led.cpp和led.h。

       下面我们先解析led.h的程序,我们把它分两部分功能进行讲解。

       由硬件设计小节,我们知道LED灯在硬件上连接到IO1,再结合Arduino库,我们做了下面的引脚定义。

/* 引脚定义 */
#define LED_PIN       1   /* 开发板上LED连接到GPIO1引脚 */

       这样的好处是移植更加方便,函数命名更亲近实际的开发板。比如:当我们看到LED_PIN这个宏定义,我们就知道这是灯LED的端口号。大家后面学习时间长了就会慢慢熟悉这样的命名方式。

       为了后续对LED灯进行便捷的操作,我们为LED灯操作函数做了下面的定义。

/* 宏函数定义 */
#define LED(x)         digitalWrite(LED_PIN, x)
#define LED_TOGGLE()   digitalWrite(LED_PIN, !digitalRead(LED_PIN))

       LED宏定义,控制LED亮灭。如果要设置LED0输出低电平,那么调用宏定义LED0(0)即可,如果要设置LED0输出高电平,调用宏定义LED0(1)即可。宏定义LED1(x)同理。

       LED_TOGGLE宏定义,分别是控制LED的翻转。这里利用digitalWrite和digitalRead函数组合实现IO口输出电平取反操作。

       下面我们再解析led.cpp的程序,这里只有一个函数led_init,这是LED灯的初始化函数,其定义如下:

/**
* @brief       初始化LED相关IO口
* @param       无
* @retval      无
*/
void led_init(void) 
{
    pinMode(LED_PIN, OUTPUT);      /* 设置led引脚为输出模式 */
    digitalWrite(LED_PIN, HIGH);   /* 结合原理图设计,实物LED获得高电平会熄灭 */
}

       LED灯的引脚设置为输出模式。最后关闭LED,防止没有操作灯就亮了。


       2. 01_led.ino代码

       在01_led.ino里面编写如下代码:

#include "led.h"
 
 
/**
* @brief   当程序开始执行时,将调用setup()函数,通常用来初始化变量、函数等
* @param    无
* @retval  无
*/
void setup() 
{
    led_init();   /* LED初始化 */
}
 
/**
* @brief     循环函数,通常放程序的主体或者需要不断刷新的语句
* @param    无
* @retval   无
*/
void loop() 
{
LED(0); 
/* 该宏函数在led.h有定义,等同于digitalWrite(LED, LOW),LED引脚输出接低电平,点亮 */
    delay(500);   /* 延时500毫秒 */
LED(1);
/* 该宏函数在led.h有定义,等同于digitalWrite(LED, HIGH),LED引脚输出接高电平,熄灭 */
    delay(500);   /* 延时500毫秒 */
 
    /* 以上4行代码实现的效果也可以用以下两行代码实现
    LED_TOGGLE(); // led状态翻转
    delay(500);   // 延时500毫秒
    */
}

       在setup函数中,调用led_init函数对LED进行初始化。接下来,在loop函数中,提供了两种方法实现LED灯的闪烁效果,第一种:先调用LED(0)宏函数实现LED点亮,调用delay(500)实现500ms延时,这时候LED就相当于亮了500ms,然后调用LED(1)宏函数实现LED熄灭,调用delay(500)实现500ms延时,这时候就相当于LED熄灭500ms,循环这个过程。第二种:调用LED_TOGGLE()函数实现LED灯状态的变化并延时500ms,循环这个过程。

       delay()为毫秒延时函数,在本程序用来控制开关LED的间隔时间。大家可以修改delay函数里面的参数,观察运行效果的变化。

       可能很多小伙伴会提出疑问,这里怎么不是main函数,main函数是有的,但是其实已经隐藏起来了,对于Arduino这种代码架构,提供出setup函数和loop函数给用户使用。大家遵循Arduino规则去开发即可,有兴趣的也可以自己去搜索。


        7.4 下载验证

       下载完之后,可以看到 LED以每次500ms闪烁。


请使用浏览器的分享功能分享到微信等