そして、それをどのように使用しますか?
前回の記事では、I / Oポートを操作するためのクラスを作成しました。それで、次は何ですか?なぜこれをすべてクラスに詰め込むのですか?
例として、簡単なボタンポーリングを見てみましょう。
このスキームの場合、最も単純なケースでは、調査は次のようになります。
int GetKey()
{
volatile uint32_t* addr = reinterpret_cast<uint32_t*>(GPIOA_IDR);
uint32_t ret_val = *addr;
return ret_val & 0x0F;
}
ただし、回路のボタンに接続されているポートを変更する場合は、ポーリング機能を変更する必要があります。そして、すべてのプロジェクトでそうです。これは必ずしも便利ではありません。一度書いて、テストして、使ってみたいです。
以前に作成したクラスでこの関数を書き直してみましょう。
int GetKey(Pin* p0, Pin* p1, Pin* p2, Pin* p3)
{
int ret_val = p0->Get() + (p1->Get() << 1) + (p2->Get() << 2) + (p3->Get() << 3);
return ret_val;
}
ポートを初期化して関数に渡すのはメインプログラムに残ります。
...
using namespace STM32F1xx;
Pin key0('a', 0);
Pin key1('a', 1);
Pin key2('a', 2);
Pin key3('a', 3);
...
int main()
{
key0.ModeInput();
key1.ModeInput();
key2.ModeInput();
key3.ModeInput();
int key_code = GetKey(&key0, &key1, &key2, &key3);
...
return 0;
}
インターフェイスはどこにありますか?
ここで、f10xシリーズのコントローラーが不足していると想像してみましょう。ただし、f030がたくさんあります。パフォーマンスとピン数に関しては、それで十分です。GetKey関数のヘッダーを変更するか、...#ifdefを使用するだけです。使用するコントローラーのタイプ(#define STM32F030など)を含むグローバルヘッダーファイルを作成し、一連の定義を積み上げます。いいえ、これは、マクロで混乱するために高レベルの言語が作成された理由ではありません!
逆に行きましょう。ポートを操作するために私たちが生活に必要な仮想メソッドをリストするクラスを作成しましょう。
iPin.h
#pragma once
class iPin
{
public:
virtual void ModeInput() = 0;
virtual void ModeAnalogInput() = 0;
virtual void ModeInputPulled() = 0;
virtual void ModeOutput() = 0;
virtual void ModeOutputOpenDrain() = 0;
virtual void Set(bool st) = 0;
virtual bool Get() = 0;
virtual void Reverse() { Set(!Get());}
void On() { Set(true); }
void Off() { Set(false); }
};
(0に等しいメソッドは、派生クラスで定義する必要があります!)
そして、Pinクラスのベースとして使用します。
...
#include "iPin.h"
...
class Pin : public iPin
...
次に、GetKey関数がわずかに変更されます。
int GetKey(iPin* p0, iPin* p1, iPin* p2, iPin* p3)
{
int ret_val = p0->Get() + (p1->Get() << 1) + (p2->Get() << 2) + (p3->Get() << 3);
return ret_val;
}
これで、コントローラーは気になりません。SPIまたはI2C上で動作するバスエキスパンダーであっても。次の記事では、シリアルインターフェイスについて検討します。
それで、次は何ですか?
次に、システムタイマーを操作するためのクラスを設計する必要があります。しかし、これはすでに次の出版物にあります。