Arduinoの標準関数であるdigitalWrite()などをAVRレベルで使用する際、ピン番号ではなくCPUのポート番号で制御する必要があります。その時に利用する関数がdigitalPinToPort()関数です。この関数を使うことでArduinoとして与えられているピン番号からCPUポートを得ることができます。
digitalPinToPort()の使い方と関数仕様
digitalPinToPort()は、Arduino開発環境内部で使われる関数であり、指定したデジタルピンが属するポートを識別します。この関数は、低レベルのポート操作での使用や、特定のピンのハードウェア属性をプログラムで直接扱う場合に重要です。各デジタルピンは特定のマイクロコントローラのポートに割り当てられており、この関数を通じてそのポートの識別子を取得できます。
仕様
- 記述:指定されたデジタルピンが属するポートを返します。
- 引数:
pin
: ポートを知りたいデジタルピンの番号。 - 戻り値:ピンが属するポートを示す識別子。有効なピンの場合は、そのポートの識別子(例:
PORTB
、PORTC
)が返されます。無効なピンの場合は、特定のエラー値(例: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)