7

デバイス用のArduinoライブラリを作成しましたが、そのライブラリは一般的にいくつかの方法で構成できます。たとえば、割り込みを使用するか、ポーリングします。他の例から、ライブラリ用に以下に示すfoo.h、fooConfig.h、およびfoo.cppのファイルを作成しました。ここで、fooConfig.hには、シールドの使用方法の構成が含まれています。割り込みの有無など...

そうすることで、メインスケッチのINOファイルが#defineを使用して宣言されたデフォルト設定を上書きできるようにしたいと思います。ライブラリのインスタンスに含めます。結果はそれが本当にそうすることを示しています。少なくとも私がやっている方法。

以下のコードは、問題のある単純化された例です。

definetest.ino

#define BAR USE_POLL
#include <foo.h>

foo test;

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.print(F("setup's defined BAR was "));
  Serial.println(BAR);

  Serial.print(F("inside foo.begin defined BAR was "));
  Serial.println(test.begin());
}

void loop() {
}

foo.h

#ifndef FOO_h
#define FOO_h

#include "FOOConfig.h"

class foo {
  public:
    int begin();
};
#endif // FOO_h

FooConfig.h

 #ifndef FOOCONFIG_h
  #define FOOCONFIG_h

  #define USE_INT      1
  #define USE_POLL     2

  #ifndef BAR
    //default to using interrupts
    #define BAR USE_INT
  #endif // BAR

#endif  // FOOCONFIG_h

foo.cpp

#include <foo.h>

int foo::begin() {
#if defined(BAR) && BAR == USE_INT
  Timer1.attachInterrupt( isr );  // error here, because of the define...
  return 1;
#elif defined(BAR) && BAR == USE_POLL
  return 2;
#endif
  return 0;
}

次のシリアル出力が生成されます。

setup's defined BAR was 2
inside foo.begin defined BAR was 1

foo.begin内のBARを1ではなく2に等しくすることが望まれる場合、プリコンパイラーにattachInterruptを省略するかどうかを決定させることが望ましいことに注意してください。ライブラリが使用されていない場合、ライブラリのリソースの依存性と消費を望まないでください。単に高度なオプションにしたいだけです。

これはmakeファイルまたはeclipseで最も適切に処理できることを理解していますが、現在1.0.3でArduinoIDE用にこのライブラリを公開しようとしています。

どんな助けでも大歓迎です。

参考までに、実際のコード全体はここにあります。 https://github.com/mpflaga/Sparkfun-MP3-Player-Shield-Arduino-Library/tree/master/SFEMP3Shield

4

4 に答える 4

8

ツールチェーンに関係なく、プログラムはライブラリのコンパイル方法を決定しませんし、決定するべきでもありません。ライブラリの重要な概念は、プログラムが存在しなくても、ライブラリが完全に開発、コンパイル、およびパッケージ化されることです。一方向の依存関係があります。プログラムはライブラリに依存します。ライブラリはどのプログラムにも依存しません。これを強調する重要な点は、ライブラリを使用するためにソースコードを配布する必要がないということです。ライブラリは、ヘッダーとバイナリ(.a)だけで使用できます。使用されているすべてのWinAvrライブラリを確認してください。

あなたが求めているのは、ライブラリの複数の構成を作成する方法です。他のツールチェーンでは、これはプロジェクトレベルで簡単に実行でき、任意の数の出力構成を作成できます。あなたの場合、pollとintがあり、ツールチェーンは2つのライブラリを生成します。例:
libMySomething_int.a
libMySomething_poll.a

プログラムは、使用するライブラリの構成を選択します。

他の人が指摘しているように、ArduinoIDEはこの形式の複雑さを提供しません。あなたはそのツールチェーン内にとどまるつもりであると述べたので、これらは私が見ることができる解決策です:

  1. 1つの#defineだけが異なるライブラリのコピーを2つ作成します。これは基本的に2つの構成を提供することです。それらはわずかに異なるため、WinMergeを2つにまとめて、コードベースの同期を維持するのは簡単です。

  2. 2つのフォームへの1つのインターフェースが必要かどうかを再考してください。begin()を1つだけ持つ必要はなく、2つの形式を持つことができます。

    void beginInt();
    void beginPoll();

    void getSomethingInt();
    void getSomethingPoll();

これはコードスペースを浪費しないことに注意してください。リンカは、最終的なプログラムからすべての未使用の関数を削除するため、Intフォームを使用するだけで、すべてのPoll関数が削除されます。

これら2つのどちらを選択するかは明確ではなく、ある程度主観的です。決定では、ライブラリに何をカプセル化/非表示にするのか、何を明確にしたいのかを考慮する必要があります。このライブラリがさまざまなリアルタイムクロックチップへのインターフェイスである場合、すべての違いをカプセル化し、1セットの関数を提供することは明らかに公平です。しかし、あなたの場合、リソース消費、タイミング、および同時実行性の重要な変更を暗示しています。これを非表示にするのが最善かどうかはわかりません。

于 2013-01-20T21:24:41.783 に答える
2

Arduino IDEはライブラリを個別にコンパイルするため、コンパイル中に-Dオプションとして定義を渡す必要があります。Arduino IDEは現在、それを簡単に行うための機能を提供していません。Arduino 1.5はboards.txtシステムを介していくつかの機能を提供しますが、これではおそらく必要な柔軟性が提供されません。

したがって、あなたが言うように、オプションは、Eclipseなどの製品でmakeファイルを編集するか、Visual Studio Proで「Defines」プロジェクトプロパティの1つ(「Defines-Project」など)を設定することです。

または、TeensyDuino IDEを使用して、boards.txtに独自の定義を追加しmenu.ます

于 2013-01-20T00:58:50.927 に答える
1

ライブラリがメインスケッチからのみ使用され、
すべてのコードを.hファイル(つまり、.cppファイルなし)に入れて生きることが
できる場合は、目的を達成できます。

これを行うことは疑わしいコーディング慣行ですが、Arduinoの世界では珍しいことではないようです。

PS:完全に正確に言うと、実際には.cppファイルを作成することも可能ですが、そのコンパイルがオーバーライド可能な#defineの影響をまったく受けない場合に限ります。

于 2013-07-14T10:40:44.680 に答える
0

私はArduinoのスペシャリストではありませんが、一見しただけです。foo :: begin()は1を出力します。これは、foo.cppで「BAR」を定義しなかったため、プリプロセッサがデフォルトになります。「foo」クラスに「configuration」メソッドを追加できるかもしれません。このメソッドは、望ましい構成の引数を受け取るため、定義をパラメーターとしてINOファイルから「foo」クラスインスタンスに渡すことができます。

于 2013-01-19T21:51:35.890 に答える