digitalPinToPort:Arduinoのピン番号からCPUのポートを取得

特別ライブラリー

Arduinoの標準関数であるdigitalWrite()などをAVRレベルで使用する際、ピン番号ではなくCPUのポート番号で制御する必要があります。その時に利用する関数がdigitalPinToPort()関数です。この関数を使うことでArduinoとして与えられているピン番号からCPUポートを得ることができます。

digitalPinToPort()の使い方と関数仕様

digitalPinToPort()は、Arduino開発環境内部で使われる関数であり、指定したデジタルピンが属するポートを識別します。この関数は、低レベルのポート操作での使用や、特定のピンのハードウェア属性をプログラムで直接扱う場合に重要です。各デジタルピンは特定のマイクロコントローラのポートに割り当てられており、この関数を通じてそのポートの識別子を取得できます。

仕様

  • 記述:指定されたデジタルピンが属するポートを返します。
  • 引数:pin: ポートを知りたいデジタルピンの番号。
  • 戻り値:ピンが属するポートを示す識別子。有効なピンの場合は、そのポートの識別子(例: PORTBPORTC)が返されます。無効なピンの場合は、特定のエラー値(例: NOT_A_PIN)が返されることがあります。

サンプルプログラム

digitalPinToPortを使ったサンプルプログラム

digitalPinToPort()を使ってArduinoの13番ピン(多くのArduinoボードでオンボードLEDが接続されているピン)のLEDを点滅させるためのプログラムを以下に示します。このプログラムは直接ポート操作を行い、標準のdigitalWrite()関数よりも高速に動作します。ただし、この手法はArduinoの初心者には推奨されません。理解と正確な使用が必要です。

#include <Arduino.h>

// ピン定義
const int ledPin = 13; // LEDが接続されているピン

void setup() {
  // ピン13のポートレジスタとビットマスクを取得
  volatile uint8_t* port = portOutputRegister(digitalPinToPort(ledPin));
  uint8_t bit = digitalPinToBitMask(ledPin);
  // ピンを出力として設定
  pinMode(ledPin, OUTPUT);
  while(true) {
    // LEDをONにする
    *port |= bit;
    delay(500);
   // LEDをOFFにする
   *port &= ~bit;
   delay(500);
  }
}

void loop() {
  // setup()で無限ループに入るため、ここには何も書かない
}

プログラム解説

  • ピンの設定: pinMode() を使用して、13番ピンを出力として設定します。
    ※ここでは動作を確実にするためにあえてpinModeを使いました。
  • 無限ループ: setup() 関数内で無限ループを使用しています。
  • LEDの点灯と消灯: ポートレジスタへの直接書き込みにより、LEDを点灯および消灯します。この操作はdigitalWrite()よりも高速ですが、使用する際にはマイクロコントローラのデータシートをよく理解する必要があります。

pinModeを使わないプログラム

この方法では、ピンの方向を設定するためにデータディレクションレジスタ(DDR)に直接アクセスします。

#include <Arduino.h>

// ピン定義
const int ledPin = 13; // LEDが接続されているピン

void setup() {
// ピン13のポートレジスタとビットマスクを取得
volatile uint8_t* ddr = portModeRegister(digitalPinToPort(ledPin));
volatile uint8_t* port = portOutputRegister(digitalPinToPort(ledPin));
uint8_t bit = digitalPinToBitMask(ledPin);

// ピンを出力として設定(pinModeの代わり)
*ddr |= bit;

while(true) {
  // LEDをONにする
  *port |= bit;
  delay(500);

  // LEDをOFFにする
  *port &= ~bit;
  delay(500);
  }
}

void loop() {
  // setup()で無限ループに入るため、ここには何も書かない
}

DDRの確認(ATmega328p)

 

タイトルとURLをコピーしました