整理在做毕业设计过程中学到的知识,经常使用的文档、网站:
下表显示了丝印标签和GPIO编号之间的对应关系、最适合使用的引脚,以及需要谨慎使用的引脚。用“√ ”标出的引脚可以使用。“※”可以使用,但是需要注意:它们在启动时有意料之外的行为。“×”的引脚不建议用作输入或输出。
丝印标签 | GPIO | 输入 | 输出 | Notes |
---|---|---|---|---|
D0 | GPIO16 | × | 没有PWM,不支持I2C | 启动时高电平,用来唤醒深度睡眠 |
D1 | GPIO5 | √ | √ | SCL |
D2 | GPIO4 | √ | √ | SDA |
D3 | GPIO0 | 上拉 | √ | 连接到FLASH,如果下拉会启动失败 |
D4 | GPIO2 | 上拉 | √ | 连接到板载LED,如果下拉会启动失败 |
D5 | GPIO14 | √ | √ | SPI( SCLK ) |
D6 | GPIO12 | √ | √ | SPI( MISO) |
D7 | GPIO13 | √ | √ | SPI( MOSI ) |
D8 | GPIO15 | ※ | SPI( CS ) 如果上拉,启动失败 | |
RX | GPIO3 | ※ | RX引脚 | 启动时高电平 |
TX | GPIO1 | × | ※ | 启动时高电平,输出debug信息; 如果拉低则启动失败 |
A0 | ADC0 | 模拟输入 | × | 分辨率:10bit |
1. 引脚
1.1 启动时使用的引脚
如果某些引脚被拉低或高,ESP8266 启动会被阻止。以下列表显示启动时引脚的状态:
GPIO | 状态 |
---|---|
GPIO0 | 拉低,启动失败 |
GPIO1 | 拉低,启动失败 |
GPIO2 | 拉低,启动失败 |
GPIO3 | 启动高电平 |
GPIO9 | 启动高电平 |
GPIO10 | 启动高电平 |
GPIO15 | 拉高,启动失败 |
GPIO16 | 启动高电平 |
1.2 启动时输出高电平的引脚
当 ESP8266 启动时,某些引脚会输出 3.3V。如果有继电器或其他外设与这些 GPIO 相连可能会有问题。以下 GPIO 在引导上输出高信号:GPIO1、GPIO3、GPIO9、GPIO10、GPIO16。 继电器通常与 GPIO5 和 GPIO4相连。
1.3 RST 引脚
当 RST 引脚拉低时,ESP8266 将重置。这与按下机载RST按钮相同。
1.4 GPIO0
当 GPIO0 被拉低时,它会将 ESP8266 设置为引导加载器模式。这与按下机载FLASH/ BOOT按钮相同。
1.5 GPIO16
用于从深度睡眠中唤醒 ESP8266。要从深度睡眠中唤醒 ESP8266,GPIO16 应连接到 RST 引脚。
1.6 中断引脚
除GPIO16 都可设置中断,慎用、不用3(D3连接到FLASH)
2. ADC输入电压范围
-
ESP8266 开发板的 ADC 电压范围:0 - 3.3V(例如:ESP8266 12-E NodeMCU Kit、WeMos D1 Mini)
-
ESP8266 芯片中的 ADC 电压范围:0-到 1V(例如:ESP-07 芯片、ESP-12E 芯片)
3.中断
attachInterrupt (digitalPinToInterrupt(GPIO), ISR, mode)
-
digitalPinToInterrupt(GPIO)
:中断引脚,除GPIO16都可以设置中断。
eg:digitalPinToInterrupt(14)
-
ISR
: 中断服务例程。功能应尽可能简单,以便处理器快速恢复主程序的执行。最好的方法是使用全局变量、在loop()
中检查并清除该标志并执行代码。 -
mode
: 中断模式。CHANGE
:引脚电平值改变时触发中断FALLNG
:引脚电平从高到低时触发中断RISING
:引脚电平从低到高时触发中断
ISR
需要有 ICACHE_RAM_ATTR
修饰,如果没有该属性会在attachInterrupt
部分报错。如下是HX711的一个中断实例:
//HX711的中断处理函数
ICACHE_RAM_ATTR void dataReadyISR() {
if (LoadCell.update()) {
newDataReady = 1;
}
}
※Notes:
- 中断过程中不能调用delay( )或yield( ),或调用内部使用
delay()
或yield( )的任何例程。 - 长时间运行(> 1ms)的中断任务将导致程序不稳定或崩溃。如果中断被长时间运行的中断阻塞,WiFi和核心的其他部分可能会变得不稳定。如果有很多事情要做,可以设置一个易失的全局标志,以便主循环
loop()
检查或者使用scheduled 函数(在安全的情况下在中断上下文之外调用该函数)来进行长时间运行的工作。 - 内存操作是危险的,应该在中断中避免。尽量减少对new或malloc的调用。因为如果内存被分割,可能需要很长的运行时间。出于同样的原因,realloc和free绝对不能被调用,也不能使用任何调用free或realloc本身的例程或对象。这意味着使用String、std:string 、std::vector和其他可调整大小的连续内存的类时必须非常小心(确保不改变字符串,不添加vector元素,等等)。
4.深度睡眠
- 使用 ESP.deepSleep(μs) 将 ESP8266 置于深度睡眠模式,通过传参设置睡眠时间。GPIO 16 必须连接到RST引脚才能将ESP8266唤醒。
- 将ESP8266置于深度睡眠模式,无限期使用ESP.deepSleep(0)。当 RST 引脚收到低信号时,ESP8266 将唤醒。
- 睡眠模式有三种不同类型:modem sleep、light sleep、deep sleep。下表显示了每个模式之间的差异。
- 唤醒来源
- 定时器唤醒:ESP8266在预先定义的时间段后自行唤醒
- 外部唤醒:ESP8266 在按 RST 按钮时唤醒(ESP8266 重新启动)
// ESP8266 Deep sleep mode example
void setup() {
Serial.begin(115200);
Serial.setTimeout(2000);
// Wait for serial to initialize.
while(!Serial) { }
///深度睡眠模式,直到RESET引脚连接到一个低电平
Serial.println("I'm awake, but I'm going into deep sleep mode until RESET pin is connected to a LOW signal");
ESP.deepSleep(0);
}
void loop() {
}
5. 串口
该Serial
对象的工作方式与常规Arduino相同。除了硬件FIFO(用于TX和RX的128字节)之外,Serial
还有一个可定制256字节的RX缓冲区。用户可以通过在begin()之前调用函数setRxBufferSize(size_t size)更改RX缓冲区的大小。size参数至少应足够大以容纳读取接收到的所有数据。
接收是由中断驱动的,但发送轮询和繁忙等待。阻塞行为如下:如果字节数适合TX FIFO(先入先出队列,常见的数据结构,不懂自行搜索)中的当前空间,则::write()
调用不会阻塞。如果TX FIFO已满,则调用将阻塞,并等待直到有空间再向其中写入更多字节,直到所有字节被写入为止。换句话说,当调用返回时,所有字节均已写入TX FIFO,但这并不意味着所有字节均已通过串行线路发送出去。
read()调用不会阻塞,即使没有可供读取的字节也不会阻塞。但是 readBytes()调用会阻塞,直到读取的字节数符合传入的参数所需的字节数为止。
flush()调用会阻塞,等待TX FIFO为空再返回。
※Notes:
HardwareSerial
类有Serial
和Serial1
两个对象。
Serial
使用UART0 (TX 、RX),该UART0映射到GPIO1(TX)和GPIO3(RX)引脚。通过在Serial.begin
之后调用Serial.swap()
可以将串口重新映射到GPIO15(TX(D8))和GPIO13(RX(D7)) 。再次调用swap
将UART0映射回GPIO1和GPIO3。
Serial1
使用UART1,TX引脚为GPIO2(D4)。UART1不能用于接收数据,因为通常它的RX引脚被用于闪存芯片连接。要使用Serial1
,需要配置Serial1.begin(baudrate)
。
如果未使用Serial1并且未交换Serial-UART0的TX可以通过在Serial.begin之后调用Serial.set_tx(2)或直接通过Serial.begin(baud,config,mode,2)将UART0的TX引脚映射到GPIO2(D4)。
默认情况下,调用Serial.begin()
,WiFi库的诊断输出是禁用的。要启用调试输出,需要调用 Serial.setDebugOutput(true)
。要将调试输出重定向到Serial1
,请调用Serial1.setDebugOutput(true)
。
使用Serial.setDebugOutput(true)
启用printf()
功能的输出。
Serial
与Serial1
对象支持5,6,7,8个数据位,奇、偶、无校验位,和1、2个停止位。通过调用Serial.begin(baudrate, SERIAL_8N1)
或Serial.begin(baudrate, SERIAL_8N1)
设置预期的工作模式。默认配置模式为SERIAL_8N1。可选的模式有SERIAL_[5 6 7 8][ N E O][1 2]。例如:SERIAL_8N1为8位数据位,无校验位,1位停止位。
6. 文件系统
保留了自己用到的,如果需要详细了解文件系统可以配合翻译软件查看ESP8266-Arduino Core 官方文档
6.1 FLASH布局
文件系统与程序存储在同一FLASH中,编写新 sketch 不会修改文件系统内容。这允许使用文件系统来存储 sketch 数据,配置文件或Web服务器的内容。下图说明了Arduino环境中的 Flash 布局:
要在sketch中使用文件系统功能,需要添加以下内容:
#include "FS.h" // SPIFFS is declared
#include "LittleFS.h" // LittleFS is declared
6.2 SPIFFS和LittleFS
在ESP8266上有两个板载Flash的文件系统:SPIFFS、LittleFS。
-
SPIFFS 是原始文件系统,适合空间和RAM受限的应用程序,但是不是真正的目录支持, 在未来版本将会逐渐弃用。
-
LittleFS 支持实际的目录,大多数操作的速度要比 SPIFFS 快很多倍,但文件系统和每个文件的开销更大(最小4K,而SPIFFS最小256字节)。
-
SPIFFS 和 LittleFS 的函数调用接口 API 是兼容的,但在 flash 上的实现并不一样。如果在 LittleFS 下挂载 SPIFFS 可能会导致格式化,不会保留任何文件,反之亦然。
从这两个文件系统返回的对象 File
和 Dir
是一样的,将应用程序从SPIFFS 转换为LittleFS,只需将 SPIFFS.begin()
更改为 LittleFS.begin()
;SPIFFS.open()
改为 LittleFS.open()
,其余代码可以保持不变。
6.2.1 SPIFFS文件系统限制
ESP8266的SPIFFS实现必须适应芯片的限制,其中包括有限的RAM。 SPIFFS是为小型系统设计的,但这是以简化和限制为代价的。
1、SPIFFS不支持目录,它只存储一个“扁平”的文件列表。但是与传统文件系统相反,文件名中允许使用'/'
,因此处理目录列表 ( eg:openDir("/website")
)的功能基本是过滤文件名,并保留以/website/
请求的前缀开头的文件名。
2、文件名总共不能超过32个字符。'\0'
为C字符串终止保留的,因此我们剩下31个可用字符。这意味着要尽量使用短文件名,而不要使用深度嵌套的目录,因为每个文件的完整路径(包括目录,'/'
字符,基本名称,点和扩展名)最多不能超过31个字符。例如,文件名 /website/images/bird_thumbnail.jpg
是34个字符,如果使用,将导致一些问题。例如:在另一个文件以相同的前31个字符开头的情况下使用exists()
。
Notes:很容易达到限制,并且如果忽略该问题。由于在编译或运行时都不会出现错误消息,因此可能不会引起注意。有关SPIFFS实现内部细节的更多信息,请参见 SPIFFS自述。
6.2.2 LittleFS文件系统的局限性
ESP8266的LittleFS实现支持最多31个字符+以零结尾的文件名(即 char filename[32]
),以及空间允许的尽可能多的子目录。
如果不存在“ /”,则假定文件名位于根目录中。
在子目录中打开文件需要指定文件的完整路径eg: open("/sub/dir/file.txt");
当在子目录中创建文件时,会自动创建子目录;当删除子目录中的最后一个文件时,会自动删除子目录本身。现有的SPIFFS文件系统中没有mkdir()
方法。
与SPIFFS不同,实际文件描述符是根据应用程序的请求分配的,因此在内存不足的情况下,可能无法打开新文件。相反,这也意味着只有使用的文件描述符实际上会在堆上占用空间。
由于存在目录,因此openDir
方法的行为不同于SPIFFS。遍历a时, SPIFFS返回“子目录”中的文件Dir::next()
(实际上并不是子目录,而只是名称中带有“ /”的文件),而LittleFS仅返回特定子目录中的文件。
6.3 将文件上传到文件系统
ESP8266FS 是一个集成到Arduino IDE中的工具。它在菜单栏“工具”中添加了一个菜单项,用于将sketch的 data
目录的内容上传到ESP8266 Flash文件系统中。ESP8266LittleFS 与 ESP8266FS 等效,使用方法一样,具体步骤如下:
-
在 Arduino 的工作目录下,创建
tools
目录 -
压缩包解压到
tools
中,如果要升级,直接覆盖现有的就可以 -
重新启动Arduino IDE,然后打开、创建一个sketch
-
转到sketch目录(选择“sketch”>“显示sketch文件夹”)
-
在sketch文件夹下中创建一个名为
data
的目录,将需要上传的文件放入其中 -
选择好开发板、端口,并且关闭串行监视器 (上传文件过程中若开着串口监视器会报错)
-
上传sketch,选择 “工具> ESP8266 sketch Data Upload”,将文件上传到ESP8266 Flash文件系统中。完成后,IDE状态栏将显示消息
SPIFFS Image Uploaded
7. ESP8266常用库
7.1 SPI
SPI库支持整个Arduino SPI API,包括事务,包括设置阶段(CPHA)。目前尚不支持设置时钟极性(CPOL)(SPI_MODE2和SPI_MODE3不起作用)。
常用的SPI引脚为:
MOSI
= GPIO13 (D7)
MISO
= GPIO12 (D6)
SCLK
= GPIO14 (D5)
有一个扩展模式,将普通引脚交换为SPI0硬件引脚。通过在调用SPI.begin()
之前调用SPI.pins(6, 7, 8, 0)
来启用此功能。引脚将变为:
MOSI
= SD1
MISO
= SD0
SCLK
= CLK
HWCS
= GPIO0
此模式与控制器共享SPI引脚,该控制器从FLASH读取程序代码,并由硬件仲裁器控制(FLASH始终具有更高的优先级)。在这种模式下,CS将由硬件控制,因为无法使用GPIO处理CS线路,实际上并不知道仲裁器会何时将授予访问总线的权限,因此必须让它自动处理CS。