Arduinoで遊ぶページ

Arduinoで遊んだ結果を残すページです。
garretlab
digitalRead()

digitalRead()

概要

digitalRead()は、指定したピンがHIGHなのかLOWなのかを返します。指定したピンのポートに対応するレジスタのビットの値が1であればHIGH、0であればLOWです。

レジスタは、PORTBとPORTC、PORTDの3種類あります。それぞれのレジスタはArduino Unoのピンと以下のように対応しています。Axはアナログピン、Dxはデジタルピンです。初期値は0(LOW)です。

PORTB
ビット 7 6 5 4 3 2 1 0
ピン - - D13 D12 D11 D10 D9 D8
PORTC
ビット 7 6 5 4 3 2 1 0
ピン - - A5 A4 A3 A2 A1 A0
PORTD
ビット 7 6 5 2 4 3 1 0
ピン D7 D6 D5 D4 D3 D2 D1 D0

digitalRead()は、入力したピン番号をもとに、どのポートのどのビットかを求め、そのビットが0のときはLOW、1のときはHIGHを返すプログラムです。

digitalRead()のリファレンスはこちらをご覧ください。

ソースコード

digitalRead()は、hardware/arduino/cores/arduino/wiring_digital.c に定義されています。以下に全ソースコードを示します。

int digitalRead(uint8_t pin)
{
        uint8_t timer = digitalPinToTimer(pin);
        uint8_t bit = digitalPinToBitMask(pin);
        uint8_t port = digitalPinToPort(pin);

        if (port == NOT_A_PIN) return LOW;

        // If the pin that support PWM output, we need to turn it off
        // before getting a digital reading.
        if (timer != NOT_ON_TIMER) turnOffPWM(timer);

        if (*portInputRegister(port) & bit) return HIGH;
        return LOW;
}

入力はpinでuint8_t型の変数です。ピンの状態により、HIGHもしくはLOWを返します。

まず、pinに対応するタイマを求めます。ATmega328Pのデジタルピンの中には、タイマに対応しているピンがあります。これは、PWM出力に利用されています。

        uint8_t timer = digitalPinToTimer(pin);

digitalPinToTimer()は、hardware/arduino/cores/arduino/Arduino.h で定義しているマクロです。ピンがタイマに対応している場合はタイマ名が返ってきます。対応していない場合は、NOT_ON_TIMERが返ってきます。

次に、pinに対応するビットマスクを求めます。

        uint8_t bit = digitalPinToBitMask(pin);

digaitalPinToBitMask()は、hardware/arduino/cores/arduino/Arduino.h で定義しているマクロで、上の表で示した各ピンに対応するビットを1にした値が返ってきます。例えば、pinに13を指定すると、0b00100000 という値が返ってきます。

次に、pinに対応するポートを求めます。

        uint8_t port = digitalPinToPort(pin);

digitalPinToPort()も、hardware/arduino/cores/arduino/Arduino.h で定義しているマクロで、ピンに対応するポートを返却します。ピン番号が0から7のときはPD、8から13のときはPB、14(A0)から19(A5)のときはPCという値を返却します。PBとPC、PDは、hardware/arduino/variants/standard/pins_arduino.hで、それぞれ2と3、4と定義されています。pinが13のときはPBが返ってきます。

返ってきたportがNOT_A_PINであれば、この関数はLOWを返します。

        if (port == NOT_A_PIN) return LOW;

Arduino Unoでは、(入力値が正しい場合は)digitalPinToPort()はNOT_A_PINを返すことはありません。

ピンがタイマに対応している場合は、PWM出力を停止します。

        // If the pin that support PWM output, we need to turn it off
        // before doing a digita reading.
        if (timer != NOT_ON_TIMER) turnOffPWM(timer);

turnOffPWM()は、hardware/arduino/cores/arduino/wiring_digital.cに定義されている関数で、指定したタイマを停止します。

その後、portをレジスタに変換し、bitとの論理積をとり、0以外であればHIGH、0であればLOWを返します。

        if (*portInputRegister(port) & bit) return HIGH;
        return LOW;

portInputRegister()は、hardware/arduino/cores/arduino/Arduino.hで定義しているマクロです。portをレジスタのアドレスに変換します。入力した値により、PORTB・PORTC・PORTDのいずれかが返ってきます。portがPBのときはPORTBが返ってきます。

ポートはアドレスなので、そのアドレスの内容を取得するために、*をつけて値を参照します。

最後に、bitとの論理積をとり、0以外であればHIGH、0であればLOWを返します。

バージョン

Arduino 1.0.5



メニューを表示するためにJavaScriptを有効にしてください。

Arduinoで遊ぶページ
Copyright © 2012 garretlab all rights reserved.
inserted by FC2 system