编写自己的Arduino库
參考及來源超給力啊:
?
https://www.cnblogs.com/lulipro/p/6090407.html
https://www.cnblogs.com/lulipro/p/6090407.html
lulipro - 代碼鋼琴家
學習知識的最大價值在于愉悅自己的大腦,其次才是讓自己生存。
如何編寫自己的Arduino庫?
一開始寫Arduino 的時候很不習慣,沒有main函數,因為好多東西都被隱藏了。一直想搞清楚,以便編寫自己的庫文件。于是研究一下午,下面是一些總結。
?
Arduino工程的初步認識
一、目錄規范
當創建一個空的工程,先按下ctrl+s保存一下。這個時候彈出對話框,命名工程。假如命名為LED,并保存在 我自己的Arduino工作目錄下? H:\Arduino\workspace\。
于是IDE會自動幫我們在workspace下創建1個文件夾,并將sketch主文件放在里面,而且主文件和文件夾同名。
H:\Arduino\workspace\ LED\ LED.ino二、主文件代碼框架規范
每一個Arduino程序(Sketch)都有1個主文件,后綴為 .ino ,它是程序的setup 函數和 loop函數所在的文件。
代碼框架如下:
void setup() {// put your setup code here, to run once://初始化操作代碼放在setup函數中,他們將在程序啟動的第一步得到執行 并只執行一次 } void loop() { // put your main code here, to run repeatedly: //將程序的主要邏輯代碼,放在loop里。他們將會反復執行下去。 }?
有C/C++開發經驗的人看到這個程序框架會愣住:我的main函數去哪里呢?
Arduino? 為了讓更多的人能夠使用Arduino平臺開發出好玩的東西出來,絞盡腦汁降低門檻,它隱藏了程序的細節,使得開發者將注意力放在實現上。
在Arduino IDE的安裝目錄下可以找到main.cpp這個代碼模板文件,main函數就位于此。文件位置:{Arduino安裝目錄}\hardware\arduino\avr\cores\arduino\main.cpp,內容如下:
?
/*main.cpp - Main loop for Arduino sketchesCopyright (c) 2005-2013 Arduino Team. All right reserved.This library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include <Arduino.h>// Declared weak in Arduino.h to allow user redefinitions. int atexit(void (* /*func*/ )()) { return 0; } // Weak empty variant initialization function. // May be redefined by variant files. void initVariant() __attribute__((weak)); void initVariant() { } void setupUSB() __attribute__((weak)); void setupUSB() { } int main(void) { init(); //硬件初始化 initVariant(); //特有硬件初始化。因為不同的開發板有自己獨特的初始化邏輯。 #if defined(USBCON) USBDevice.attach(); #endif setup(); for (;;) { loop(); if (serialEventRun) serialEventRun(); } return 0; }?
在項目中使用多文件
有時會程序越寫越大,越大越亂。多文件管理可以解決這個麻煩。Arduino程序可以有多個源代碼文件,但只有 1個 主文件,也就是存放 setup、loop函數的.ino文件。
為了使得代碼更清晰,我們讓主文件用來控制程序的主要邏輯部分,而把具體的細節封裝成單個模塊,存放在其他的文件中,這樣方便管理。
那么怎么創建其他的文件呢???下面開始介紹。
?
使用無后綴的文件(其實是以.ino為后綴的,只是在IDE中不會顯示后綴,而在電腦的資源管理器中會顯示.ino ?, 以下都稱為無后綴)
?
點擊下圖中標記的按鈕,選擇第一個選項 【新建標簽】,輸入文件名即可。
?
這樣我們的工程就有了2個文件了。如下,一個主文件和一個名為LED的文件。這就是最簡單的多文件方法。
?
?
我不推薦使用這種方法,這是為沒有C/C++編程經驗的小白準備的,他們不懂函數定義 后還要聲明才能使用,不懂得頭文件的包含。這些都被Arduino IDE幫他們做了。IDE的具體處理是
在編譯前期,Arduino IDE會將無后綴的文件 和 主文件合并成為1個文件,效果就像是寫在主文件中一樣。并在主文件第一行添加 ?#include "Arduino.h" 。 Arduino.h是 Arduino程序的核心頭文件。然后,IDE將掃描合并后文件的函數定義,并對已經定義的函數添加函數的聲明。(這個就是為什么即便我們定義的函數不聲明也能編譯通過的原因了) 但是官方明確說了,這個自動插入函數聲明的機制是不完美的!所以我也建議大家養成手動聲明函數的習慣。Also, this generation isn't perfect: it won't create prototypes for functions that have default argument values, or which are declared within a namespace or class.
?
使用傳統的 C/C++分離式文件
這種方式下,對于一個代碼模塊,我們需要一對文件:源文件和頭文件,即: .c? 和.h?? 或者 .cpp 和 .h? 。前者是C語言風格,后者是對會使用C++來說的。官方貌似推崇我們使用C++編寫Arduino代碼,無論是Arduino 的從標準庫,還是教程中,都透露出一股強烈的OOP氣息。所以我下面使用C++風格來舉例子。
例如我們想要將LED的控制封裝成一個模塊。一開始我們需要創建2個文件 :LED.h?? 、 LED.cpp
?
??
然后是想清楚我們需要讓提供LED控制的哪些操作。發揮你的想象力時候到了。規定操作后,我們先寫出頭文件,然后寫出實現,最后在主文件中使用這個模塊。在主文件中使用
#include"LED.h"預處理指令包含。
?
/******************* LED.h*******************/#ifndef _LED_H__ #define _LED_H__//導入Arduino核心頭文件 #include"Arduino.h" class LED { private: byte pin; //控制led使用的引腳 public: LED(byte p , bool state=LOW ); //構造函數 ~LED(); //析構函數 byte getPin(); //獲取控制的引腳 void on(); //打開LED void off(); //關閉LED bool getState(); //獲取LED狀態 void disattach(); //釋放引腳與LED的綁定,使得引腳可以控制其他的東西 }; #endif?
/***************** LED.cpp******************/#include"LED.h" #include"Arduino.h" LED::LED(byte p,bool state):pin(p) { pinMode(pin,OUTPUT); digitalWrite(pin,state); } LED::~LED() { disattach(); } void LED::on() { digitalWrite(pin,HIGH); } void LED::off() { digitalWrite(pin,LOW); } bool LED::getState() { return digitalRead(pin); } void LED::disattach() //引腳回收,恢復到上電狀態 { digitalWrite(pin,LOW); pinMode(pin,INPUT); }?
?
/********************** 實例化1個LED對象,用7號叫控制,讓他閃爍10次,并在串口打印出它的狀態。 10次完畢后釋放回收引腳 **********************/#include"LED.h" LED led(7); byte count =0; void setup() { Serial.begin(9600); } void loop() { if(count<10) { led.on(); delay(300); Serial.print("LED state:");Serial.println(led.getState(),DEC); led.off(); delay(300); Serial.print("LED state:");Serial.println(led.getState(),DEC); ++count; if(count==10) led.disattach(); } }
?
?
讓它成為你自己的庫!
如果上面的模塊你覺得好用,符合自己的使用習慣,而且經常要用到,那么你可以將它變成你自己的庫文件。這樣以后就可以直接拿來用啦。
Arduino的擴展庫都是放在 libraries目錄下的。
?
所以我們需要在這個目錄下創建一個文件夾,比如上面的例子是LED控制,于是我創建了 m_LED文件夾(前面加m是為了和官方庫區分開,這只是我自己的習慣而已)。然后把寫好的.cpp 和 .h文件拷貝到里面去,這樣就OK了。
?
這樣我們 的主文件就變成了下面這樣,是不是很簡潔干凈呢。
#include<LED.h> //注意,由于LED控制模塊已經是標準庫了,所以使用尖括號<> 包含LED led(7); byte count =0; void setup() { Serial.begin(9600); } void loop() { if(count<10){ led.on(); delay(300); Serial.println(led.getState(),DEC); led.off(); delay(300); Serial.println(led.getState(),DEC); ++count; if(count==10) led.disattach(); } }?
細心的同學會發現 和 LED.cpp? 、 LED.h 一起有個 keywords.txt文件,這個是什么用呢? 其實它沒有太大的實用性,只是為了配置自定義庫的語法高亮。讓我們自己的庫能在IDE下顯示不同的顏色而已。如果不配置,Arduino IDE不能渲染出顏色的。
?
?
?
下面是keywords.txt 的內容,其中#開頭的是注釋,完全可以不寫。格式:word【tab】DESCRIPTION word就是你要高亮的關鍵字接著1 個 tab 鍵 ,然后就是DESCRIPTION。 DESCRIPTION可以取的值: KEYWORD1 ?? 高亮類名 KEYWORD2??? 高亮方法名 LITERAL1?????? 高亮常量 注意中間使用的是 1? 個? tab 鍵 隔開的 #class (KEYWORD1) LED? ? KEYWORD1 #function and method (KEYWORD2) on? ? KEYWORD2 off? ? KEYWORD2 getState? ? KEYWORD2 disattach? ? KEYWORD2 #constant (LITERAL1) #none如果你覺得這個庫非常不錯,你還可以把它分享給別人使用。我們好像一直都在使用別人的東西,把自己的勞動成果分享出去,也為別人做出貢獻,豈不更好?
轉載于:https://www.cnblogs.com/MCSFX/p/10942043.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的编写自己的Arduino库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: inkscape 无法打开文档属性
- 下一篇: 解决ASP.Net第一次访问慢的处理 I