第七章 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灯的初始化函数,其定义如下: /** * @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闪烁。
|