在项目中,有时我们需要很多的代码。如果将这些代码全部都存放于一个文件中,那么该文件将会过长,因此我们可以将 Arduino 代码进行拆分,存放于多个文件中。而一些可能以后会服复用到的文件,也可以直接将文件粘贴过来,而不需要修改,就可以使用。
比如,我们在使用 Esp8266 系列的时候,经常需要将 Esp8266 联网,而在以前,我们是将 WiFi 信息在代码中写死的。如果想要将 WiFi 设置为配置式,可参考 https://www.jianshu.com/p/5dc724e39fd1 这篇文章。但是这里代码很长,如果我们在这里进行修改,以后再其他项目中还需要进行修改。所以我们可以将配置 WiFi 这一功能,做成一个通用的模块,这样我们就可以将其通用化,以后随用随取,不必另行修改。
比如我们一个很简单的 Blink 代码:
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
总共不超过 10 行,而配置 WiFi 的代码就将近 300 行,将两者合并到一个文件中,不仅主业务流程读起来不清晰,还不方便进行修改。
而我们可以将文章中配置 WiFi 的代码稍作修改,存储于一个独立的文件中,以后不管哪个项目中需要使用,只需要将此文件拷贝到相应的项目文件夹中就可以使用了。
WiFi 配置代码修改如下:
//声明
#include
#include
#include
#include
int EPPROM_Address = 512;
// WiFi,可以写入在这里预先输入自己最常用的 WiFi 信息,也可以设置为空字符串
String WiFi_SSID = "";
String WiFi_Password = "";
//Ap 设置热点信息
const char* AP_Host = "esp8266";
const char* AP_SSID = "Esp8266AP";
const char* AP_Password = "12345678";
// web
String webContent;
int webStatusCode;
String wifiScanContent;
ESP8266WebServer WebServer(80);
void initWiFi() {
EEPROM.begin(EPPROM_Address);
readWiFiInfoFromEEPROM();
bool connectStatus = tryToConnectToWiFi();
if (connectStatus)
{
createConnectedWeb();
}
else
{
ScanNetwork();
SetupToAPMode();
connectStatus = tryToConnectToWiFi();
}
WebServer.begin();
delay(100);
}
void wifiTask() {
WebServer.handleClient();
}
/********* 从存储器中读取 WiFi 信息 ***************/
void readWiFiInfoFromEEPROM()
{
//--- 从 EEPROM 中读取 WiFi 的 SSID 和密码
//--- 读取 wifi ssid
WiFi_SSID = "";
for (int i = 0; i < 32; ++i)
{
WiFi_SSID += char(EEPROM.read(i));
}
delay(100);
//--- 读取 wifi 密码
WiFi_Password = "";
for (int i = 32; i < 96; ++i)
{
WiFi_Password += char(EEPROM.read(i));
}
delay(100);
}
/********* 尝试连接 WiFi ***************/
bool tryToConnectToWiFi()
{
WiFi.mode(WIFI_STA);
WiFi.begin(WiFi_SSID.c_str(), WiFi_Password.c_str());
delay(100);
// WiFi 连接需要时间,因此这里相当于持续检测 10 秒
int times = 0;
while ( times < 10 ) {
if (WiFi.status() == WL_CONNECTED) {
return true;
}
delay(1000);
times++;
}
return false;
}
/********* 设置为 AP 模式 ***************/
void SetupToAPMode() {
WiFi.mode(WIFI_AP);
WiFi.softAP(AP_SSID, AP_Password, 6, 0);
createApModeWeb();
//貌似 dns 不生效
if (MDNS.begin(AP_Host))
{
MDNS.addService("http", "tcp", 80);
}
}
/********* 创建 AP 模式网页 ***************/
void createApModeWeb()
{
//加载网页
WebServer.on("/", []() {
IPAddress ip = WiFi.softAPIP();
webContent = "";
webContent += "";
webContent += "WiFi 信息设置 ";
webContent += "";
webContent += "请输入 WiFi 信息
";
webContent += wifiScanContent;
// 代表插入一个空格, 重复5个就是插入5个空格
webContent += "
";
webContent += "";
WebServer.send(200, "text/html", webContent); //200代表服务器状态码为 OK, text/html代表用html网页类型, 不加这个会找不到网页
});
WebServer.on("/setting", []() {
WiFi_SSID = WebServer.arg("ssid");
WiFi_Password = WebServer.arg("pass");
if (WiFi_SSID.length() > 0 && WiFi_Password.length() > 0)
{
if (WiFi_SSID.length() <= 32 && WiFi_Password.length() <= 64)
{
for (int i = 0; i < 96; ++i) {
EEPROM.write(i, 0);
}
for (int i = 0; i < WiFi_SSID.length(); ++i)
{
EEPROM.write(i, WiFi_SSID[i]);
}
for (int i = 0; i < WiFi_Password.length(); ++i)
{
EEPROM.write(32 + i, WiFi_Password[i]);
}
EEPROM.commit(); //EEPROM.write 并不会马上写入 EEPROM, 而是要执行 EEPROM.commit()才会实际的写入EEPROM
delay(50);
webContent = "存储成功, 请按 RESET 键重新开机!";
webStatusCode = 200;
}
else {
webContent = "输入错误!!! SSID 允许的最大长度为 32,PASSWORD 允许的最大长度为 64, 按上一页重新输入
";
webContent += "