如何編寫本身的Arduino庫?

一開始寫Arduino 的時候很不習慣,沒有main函數,由於好多東西都被隱藏了。一直想搞清楚,以便編寫本身的庫文件。因而研究一下午,下面是一些總結。git

 

Arduino工程的初步認識

1、目錄規範redis

當建立一個空的工程,先按下ctrl+s保存一下。這個時候彈出對話框,命名工程。假如命名爲LED,並保存在 我本身的Arduino工做目錄下  H:\Arduino\workspace\。編程

因而IDE會自動幫咱們在workspace下建立1個文件夾,並將sketch主文件放在裏面,並且主文件和文件夾同名。框架

 H:\Arduino\workspace\
    LED\
      LED.ino
 

2、主文件代碼框架規範函數

每個Arduino程序(Sketch)都有1個主文件,後綴爲 .ino是程序的setup 函數和 loop函數所在的文件。oop

代碼框架以下:ui

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函數去哪裏呢?this

Arduino  爲了讓更多的人可以使用Arduino平臺開發出好玩的東西出來,絞盡腦汁下降門檻,它隱藏了程序的細節,使得開發者將注意力放在實現上。spa

在Arduino IDE的安裝目錄下能夠找到main.cpp這個代碼模板文件,main函數就位於此。文件位置:{Arduino安裝目錄}\hardware\arduino\avr\cores\arduino\main.cpp,內容以下:prototype

 

/*
  main.cpp - Main loop for Arduino sketches
  Copyright (c) 2005-2013 Arduino Team.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 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 of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, 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
 

若是你以爲這個庫很是不錯,你還能夠把它分享給別人使用。咱們好像一直都在使用別人的東西,把本身的勞動成果分享出去,也爲別人作出貢獻,豈不更好?

相關文章
相關標籤/搜索