用户工具

站点工具


技术细节:arduino库:编写arduino扩展库

本文档介绍了如何创建一个Arduino扩展库。它将向你描述如何将一个摩尔斯代码信号的功能做成一个扩展库。这将会使别人很容易使用你的代码,并且你也可以很方便的编辑和修改你的扩展库。

我们从写一个简单的摩尔斯码开始:

int pin = 13; void setup() {

   pinMode(pin, OUTPUT);

}

void loop() {

   dot();
   dot();    
   dot();
   dash();
   dash();
   dash();
   dot();
   dot();
   dot();
   delay(3000);

}

void dot() {

   digitalWrite(pin, HIGH);
   delay(250);
   digitalWrite(pin, LOW);
   delay(250);

}

void dash() {

   digitalWrite(pin, HIGH);
   delay(1000);
   digitalWrite(pin, LOW);
   delay(250);

}

运行这段代码,会使Pin 13脚发出SOS紧急呼救的莫尔斯代码信号。

代码有几个不同的函数,我们将其写入我们的库。首先,我们显然要有dot()函数和dash()函数功能,它们提供闪烁的功能。其次,还要用定义“ledpin”变量来确定使用哪个针脚。最后,要用pinmode()函数来初始化引脚输出。

让我们开始把程序写成扩展库! 你至少需要两个文件:一个头文件(扩展名为.h)和一个源文件(扩展名为.cpp)。头文件定义扩展库:基本上是一个原代码中所有元素的列表。我们引用我们的扩展库“Morse”,所以我们把头文件名写为“Morse.h”,让它看上去一目了然。头文件和源文件的文件名相同(文件类型不同)。

头文件的核心是一个扩展库中所有函数的列表,这个列表以及你所需要的所有的变量写在一个类里面: class Morse 类 { public: Morse(int pin); 构造函数

   void dot();
   void dash();
   private:
   int _pin;

};

类是一个函数和变量的简单集合。这些函数和变量可以是公开的,以使别人可以使用你的扩展库。或者,他们只能从类内部访问。每个类有一个特殊的函数,称为构造函数,它用来创建一个类的过程。构造函数与类具有相同的名字,但它没有返回类型。

在头文件里你还需要一些其他的东西。用一个#include声明让你访问Arduino语言中的标准变量和常量(它自动添加,但不在扩展库中)。就像这样(它将在最开始运行): #include “WProgram.h”

最后,它将把整个头文件打包进一个特殊的构造里:

#ifndef Morse_h #define Morse_h the #include statment and code go here… 把声明和代码写在这里 #endif

基本上,这可以防止别人不小心重复引用库。 最后,我们通常会在顶部加入一些自己的信息,比如库的名字、简短的描述、作者的名字、日期和许可等等。

下面,让我们看一下完整的头文件:

/* Morse.h - Library for flashing Morse code. Created by David A. Mellis, November 2, 2007. Released into the public domain. */ #ifndef Morse_h #define Morse_h #include “Arduino.h” class Morse {

   public:
   Morse(int pin);
   void dot();
   void dash();
   private:
   int _pin;

}; #endif

现在让我们看看.cpp文件的组成部分。 首先是一组#include报表,要把它写在文件开头,提供其余代码使用标准Arduino功能:

#include “Arduino.h” #include “Morse.h” 然后是构造函数,再次声明当有人使用你的类的过程时会发生什么。在本例中,用户可以指定要使用的针脚。我们将输出引脚的配置保存到一个私有变量用于其他功能: Morse::Morse(int pin) { pinMode(pin, OUTPUT); _pin = pin; } 有一些特殊的东西在这个代码里。首先是在这个函数名字前的“Morse::”。这表示,此函数属于“Morse”类,你会在这个类的其它函数里多次看到。其二是在私有变量名称前的下划线,“_pin”。这个变量可以是其它名字,只要可以与头文件匹配。加下划线开始的名字是私有变量的一个约定俗成的写法,同时也能从函数的功能段区分名字(在本例中)。

扩展库的代码和源代码看起来非常类似,除了函数名前有“Morse::”和用“_pin”代替了“pin”:

void Morse::dot() { digitalWrite(_pin, HIGH); delay(250); digitalWrite(_pin, LOW); delay(250); }

void Morse::dash() { digitalWrite(_pin, HIGH); delay(1000); digitalWrite(_pin, LOW); delay(250); }

最后,在源文件的顶部同样会有注释部分。让我们来看看整个扩展库源文件:

/*

Morse.cpp - Library for flashing Morse code.
Created by David A. Mellis, November 2, 2007.
Released into the public domain.

*/

#include “Arduino.h” #include “Morse.h”

Morse::Morse(int pin) {

pinMode(pin, OUTPUT);
_pin = pin;

}

void Morse::dot() {

digitalWrite(_pin, HIGH);
delay(250);
digitalWrite(_pin, LOW);
delay(250);  

}

void Morse::dash() {

digitalWrite(_pin, HIGH);
delay(1000);
digitalWrite(_pin, LOW);
delay(250);

}

这就是所有必要的部分(其它一些可选的东西,我们将在以后再谈)。让我们来看看如何使用扩展库。 首先,在扩展库的子目录建一个莫尔斯扩展库目录。把Morse.h和Morse.cpp文件复制或移动到该目录中。现在打开Arduino编译器。打开“Sketch”>“Import Library”菜单,你应该看到有“Morse”选项。在使用的时候该扩展库将同时被编译。如果没有看到这个扩展库,请确保文件名为正常的“.cpp”和“h”(没有其它多余的如“.pde”或“.txt”这样的扩展名)。

让我们看看现在我们怎样用新的扩展库来编写我们的原先的程序: #include <Morse.h>

Morse morse(13); 实例化类 void setup() { } void loop() { morse.dot(); morse.dot(); morse.dot(); morse.dash(); morse.dash(); morse.dash(); morse.dot(); morse.dot(); morse.dot(); delay(3000); } 除了将一些代码已经转移到扩展库里,这些代码有些差别。 首先,我们仅需要在代码顶部添加#include语句,就可以使程序使用这个扩展库,并且在编译时会被同时编译进去。这也意味着你在程序中不需要再编写长长的代码。而且如果你不再需这个功能,只要删除这个“#include”语句就可以了。 现在,我们来创建一个莫尔斯类的过程: Morse morse(13); 当此行被执行时(实际上它在setup()函数执行之前就已经被执行了),将引用“Morse”类(本例子中使用针脚13)。 请注意,在这里“void setup()”是空的,这是因为“pinMode()”的调用发生在扩展库中(在调用函数的时候)。 最后,调用“dot()”和“dash()”函数时,我们需要用“morse”作它们的的前缀。程序中我们可以多次引用,它们每个的针脚数据都储存在“_pin”私有变量里。我们可以定义多个“Morse”类的函数,每一个都有自己的“_pin”私有变量。在某过个程中调用函数时,我们可以指定的不同的针脚变量,这些私有变量都仅是在函数调用过程中被使用。也就是说,如果我们有两次调用: Morse morse(13); Morse morse2(12); 后面的私有变量“_pin”将会是针脚12 。 如果你尝试使用新的的代码,你会看到我们的扩展库没有被认可,即没有被高亮显示出来。不幸的是,Arduino软件不能自动找出你在扩展库中已经定义的功能(虽然这将是一个很好的功能),所以你必须给它一个小小的提示。为了做到这一点,我们要在Morse扩展库目录中创建一个名为“keywords.txt”的文件。它的内容是这样的: Morse KEYWORD1 dash KEYWORD2 dot KEYWORD2 每行有一个关键字,后面有个Tab(注意,不是空格),再后面是keyword。类名为KEYWORD1; 函数是KEYWORD2。你必须重新启动Arduino的环境,找到到新的关键字。 以下是一个实例,里面有详细的解释: H文件内容: /* Add2.h - Library 功能:将两个操作数相加,返回结果 Created by czad */ #ifndef Add2_h #define Add2_h #include “Arduino.h” 此句声明了Arduino的标准常量和变量,必须要

class Add2 类名称(可与文件名不同) { public: 此处定义全局函数和变量

  Add2(); //构造函数,名字要与类名相同
  int Calculation(int Val1, int Val2);
private: //此处定义私有函数和变量
      int Result; //私有函数名前习惯加下划线“_”

};

#endif

CPP文件内容:

/*

Add2.h - Library
功能:将两个操作数相加,返回结果
Created by czad

*/

#include “Arduino.h” #include “Add2.h”

Add2::Add2() 构造函数,名字要与类名相同,内部可有过程,但没有返回值,一般用于初始化功能 { } int Add2::Calculation(int Val1, int Val2) 本名表明Calculation为Add2类下的函数 {

Result = Val1 + Val2;
return Result;

}

keywords文件内容:

Add2 KEYWORD1 类名,用KEYWORD1,注意:中间为Tab符,而不是空格 Calculation KEYWORD2 函数名,用KEYWORD2,,注意:中间为Tab符,而不是空格

示例程序:

#include <Add2.h> Add2 ad; 此处声明扩展库中的Add2类在本代码中使用的缀名,可自定义 void setup() { Serial.begin(9600); } void loop() { for (int i = 0; i < 500; i++) { int val = ad.Calculation(i,i); Serial.println(val); delay(500); } } 库其实就是一个类,把某些个功能封装起来,提供给别人用的,省得每次重写。 根据目测–还没看官网reference的–库的命名有点规律,就是文件名/文件夹名称/类名相同,放在libraries目录中。如果是范例,要在库文件的根目录底下再建一个examples文件夹,然后根据一个范例一个文件夹的规则在examples下面。

技术细节/arduino库/编写arduino扩展库.txt · 最后更改: 2021/04/22 14:26 由 imodu