Arduino 代碼拆分

在項(xiàng)目中朝刊,有時(shí)我們需要很多的代碼残炮。如果將這些代碼全部都存放于一個(gè)文件中负懦,那么該文件將會(huì)過長筒捺,因此我們可以將 Arduino 代碼進(jìn)行拆分,存放于多個(gè)文件中纸厉。而一些可能以后會(huì)服復(fù)用到的文件系吭,也可以直接將文件粘貼過來,而不需要修改颗品,就可以使用肯尺。

比如,我們?cè)谑褂?Esp8266 系列的時(shí)候躯枢,經(jīng)常需要將 Esp8266 聯(lián)網(wǎng)则吟,而在以前,我們是將 WiFi 信息在代碼中寫死的锄蹂。如果想要將 WiFi 設(shè)置為配置式氓仲,可參考 http://www.reibang.com/p/5dc724e39fd1 這篇文章。但是這里代碼很長得糜,如果我們?cè)谶@里進(jìn)行修改敬扛,以后再其他項(xiàng)目中還需要進(jìn)行修改。所以我們可以將配置 WiFi 這一功能朝抖,做成一個(gè)通用的模塊啥箭,這樣我們就可以將其通用化,以后隨用隨取治宣,不必另行修改急侥。

比如我們一個(gè)很簡單的 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 行侮邀,將兩者合并到一個(gè)文件中缆巧,不僅主業(yè)務(wù)流程讀起來不清晰,還不方便進(jìn)行修改豌拙。

而我們可以將文章中配置 WiFi 的代碼稍作修改陕悬,存儲(chǔ)于一個(gè)獨(dú)立的文件中,以后不管哪個(gè)項(xiàng)目中需要使用按傅,只需要將此文件拷貝到相應(yīng)的項(xiàng)目文件夾中就可以使用了捉超。
WiFi 配置代碼修改如下:

//聲明
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <ESP8266mDNS.h>

int EPPROM_Address = 512;

// WiFi,可以寫入在這里預(yù)先輸入自己最常用的 WiFi 信息唯绍,也可以設(shè)置為空字符串
String WiFi_SSID = "";
String WiFi_Password = "";

//Ap 設(shè)置熱點(diǎn)信息
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();
}


/********* 從存儲(chǔ)器中讀取 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 連接需要時(shí)間拼岳,因此這里相當(dāng)于持續(xù)檢測 10 秒
  int times = 0;
  while ( times < 10 ) {
    if (WiFi.status() == WL_CONNECTED) {
      return true;
    }
    delay(1000);
    times++;
  }
  return false;
}

/********* 設(shè)置為 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);
  }
}

/********* 創(chuàng)建 AP 模式網(wǎng)頁 ***************/
void createApModeWeb()
{
  //加載網(wǎng)頁
  WebServer.on("/", []() {
    IPAddress ip = WiFi.softAPIP();
    webContent = "<!DOCTYPE HTML>";
    webContent += "<html>";
    webContent += "<title>WiFi 信息設(shè)置</title>";
    webContent += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
    webContent +=  "<p>請(qǐng)輸入 WiFi 信息</p>";
    webContent += wifiScanContent;
    //&nbsp;代表插入一個(gè)空格, 重復(fù)5個(gè)就是插入5個(gè)空格
    webContent += "<br>";
    webContent += "<form method='get' action='setting'>";
    webContent += "<table border=\"0\"><tr><td><label>SSID</label></td><td><input type=\"text\" placeholder=\"請(qǐng)輸入你要連接的 SSID\" name='ssid' maxlength=32 size=64></td></tr>";
    webContent += "<tr><td><label>PASSWORD</label></td><td><input type=\"text\" placeholder=\"請(qǐng)輸入該 WiFi 密碼\" name='pass' maxlength=64 size=64></td></tr></table>";
    //    webContent += "<input type=\"button\" value=\"重新掃描網(wǎng)絡(luò)\" onclick=\"self.location.href='/rescannetwork'\">";
    webContent += "&nbsp;&nbsp;&nbsp;<input type='reset' value=\"重設(shè)\">&nbsp;&nbsp;&nbsp;<input type='submit' value=\"存儲(chǔ)\"></form></html>";
    WebServer.send(200, "text/html", webContent);  //200代表服務(wù)器狀態(tài)碼為 OK, text/html代表用html網(wǎng)頁類型, 不加這個(gè)會(huì)找不到網(wǎng)頁
  });

  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 并不會(huì)馬上寫入 EEPROM, 而是要執(zhí)行 EEPROM.commit()才會(huì)實(shí)際的寫入EEPROM
        delay(50);

        webContent = "存儲(chǔ)成功, 請(qǐng)按 RESET 鍵重新開機(jī)!";
        webStatusCode = 200;
      }
      else {
        webContent = "<p>輸入錯(cuò)誤!!! SSID 允許的最大長度為 32,PASSWORD 允許的最大長度為 64, 按上一頁重新輸入</p>";
        webContent += "<input type=\"button\" value=\"上一頁\" onclick=\"self.location.href='/'\"></html>";
        webStatusCode = 404;
        }
    }
    else {
      webContent = "<p>輸入錯(cuò)誤!!! SSID 和 PASSWORD 都不允許為空, 按上一頁重新輸入</p>";
      webContent += "<input type=\"button\" value=\"上一頁\" onclick=\"self.location.href='/'\"></html>";
      webStatusCode = 404;
    }
    WebServer.send(webStatusCode, "text/html", webContent);
  });
}

/********* 掃描無線網(wǎng)絡(luò) ***************/
void ScanNetwork() {
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  delay(100);
  int wifiCount = WiFi.scanNetworks();

  // 將 WiFi 信息構(gòu)造成 html 格式
  wifiScanContent = "<ol type=\"1\" start=\"1\">";
  for (int i = 0; i < wifiCount; ++i)
  {
    // Print SSID and RSSI for each network found
    wifiScanContent += "<table border=\"0\"><tr><td width=\"300px\">";
    wifiScanContent += String(i + 1) + ". ";
    wifiScanContent += WiFi.SSID(i);
    wifiScanContent += " (";
    wifiScanContent += WiFi.RSSI(i);
    wifiScanContent += ")";
    wifiScanContent += "</td><td width=\"200px\">";

    byte encryption = WiFi.encryptionType(i);
    wifiScanContent += getEncryptionTypeString(encryption);
    wifiScanContent += "</td></tr>";
  }
  wifiScanContent += "</ol></table><br>";
}

String getEncryptionTypeString(byte type)
{
  String str = "";
  switch (type) {
    case 2: str = "TKIP(WPA)"; break;
    case 5: str = "WEP"; break;
    case 4: str = "CCMP(WPA)"; break;
    case 7: str = "NONE"; break;
    case 8: str = "AUTO(WPA or WPA2)"; break;
    default:
      str = "";
  }
  return str;
}

void createConnectedWeb()
{
  WebServer.on("/", []() {
    webContent = "<!DOCTYPE HTML>";
    webContent += "<html>";
    webContent += "<title>WiFi 信息</title>";
    webContent += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
    webContent +=  "<p>當(dāng)前 WiFi 信息</p>";
    //    webContent += wifiScanContent;
    //&nbsp;代表插入一個(gè)空格, 重復(fù)5個(gè)就是插入5個(gè)空格
    webContent += "<br>";

    webContent += "<table border=\"0\"><tr><td><label>當(dāng)前 SSID: </label></td>";
    webContent += "<td><label>" + WiFi_SSID + "</label></td></tr>";
    webContent += "<tr><td><label>當(dāng)前 IP 地址: </label></td>";
    webContent += "<td><label>" +  WiFi.localIP().toString() + "</label></td></tr></table>";
    webContent += "</html>";
    WebServer.send(200, "text/html", webContent);
  });
}

**BLink 程序修改如下

void setup() {
  //初始化 WiFi
  initWiFi();

  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  wifiTask();

  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
}

只需要在 setup() 函數(shù)中添加一行 initWiFi() 况芒,在 Loop 中添加一行 wifiTask() 即可惜纸。

將上述 WiFi 文件復(fù)制到 Blink 項(xiàng)目文件夾內(nèi),重新打開 Blink 項(xiàng)目,即可加載耐版。


項(xiàng)目結(jié)構(gòu)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末祠够,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子粪牲,更是在濱河造成了極大的恐慌古瓤,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腺阳,死亡現(xiàn)場離奇詭異落君,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)亭引,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門绎速,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人焙蚓,你說我怎么就攤上這事朝氓。” “怎么了主届?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵赵哲,是天一觀的道長。 經(jīng)常有香客問我君丁,道長枫夺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任绘闷,我火速辦了婚禮橡庞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘印蔗。我一直安慰自己扒最,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布华嘹。 她就那樣靜靜地躺著吧趣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪耙厚。 梳的紋絲不亂的頭發(fā)上强挫,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音薛躬,去河邊找鬼俯渤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛型宝,可吹牛的內(nèi)容都是我干的八匠。 我是一名探鬼主播絮爷,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼梨树!你這毒婦竟也來了坑夯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤劝萤,失蹤者是張志新(化名)和其女友劉穎渊涝,沒想到半個(gè)月后慎璧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體床嫌,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年胸私,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厌处。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岁疼,死狀恐怖阔涉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捷绒,我是刑警寧澤瑰排,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站暖侨,受9級(jí)特大地震影響椭住,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜字逗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一京郑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧葫掉,春花似錦些举、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闲孤。三九已至,卻和暖如春绪抛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背电禀。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工幢码, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人尖飞。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓症副,卻偏偏與公主長得像店雅,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贞铣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容