Playing with Arduino

A page to record my playing with Arduino
garretlab
digitalRead()

digitalRead()

Abstract

The digitalRead() returns if the specified pin is HIGH or LOW. If the value of the corresponding bit of the register is 1 it returns HIGH, if 0 it returns LOW.

There are three registers, PORTB, PORTC and PORTD. The relation of the bit of the registers and the pins of Arduino Uno is shown below. Ax is an analog pin, Dx is a digital pin.

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

The digitalRead() is a function that dose

  • calculate which bit of PORTx for the pin
  • read the value of the PORTx
  • return the result

Source Code

The digitalRead() is defined in hardware/arduino/cores/arduino/wiring_digital.c as below.

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;
}

The input argument is pin. The type of the variable is uint8_t.

First calculate the timer of the pin. Some of the digital pin are related to timer. These pins can output PWM.

        uint8_t timer = digitalPinToTimer(pin);

The digitalPinToTimer() is a macro defined in hardware/arduino/cores/arduino/Arduino.h. It returns a timer name if the pin is related to a timer. If not, it returns NOT_ON_TIMER.

Next calculate the bit mask, which bit in the PORTx, of the pin.

        uint8_t bit = digitalPinToBitMask(pin);

The digitalPinToBitMask() is a macro defined in hardware/arduino/cores/arduino/Arduino.h. It returns a value with a corresponding bit, shown in the table above, of DDR set to 1. For example, if the pin is 13, the value 0b00100000 is returned. It means the fifth bit of PORTB.

Next, calculate a port corresponds to the pin.

        uint8_t port = digitalPinToPort(pin);

The digitalPinToPort() is a macro defined also in hardware/arduino/cores/arduino/Arduino.h. It returns the PORT corresponds to the pin. If the pin is from 0 to 7, it returns PD, from 8 to 13 it returns PB, from 14(A0) to 19(A5) it returns PC.

If the port is NOT_A_PIN, the function returns LOW.

        if (port == NOT_A_PIN) return LOW;

Using Arduino Uno, if the input value is correcet, digitalPinToPort() dose not return NOT_A_PIN. And if the input value is not correct, the return value is undefined.

If the pin is related to a timer, PWM output is stopped.

        // 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);

The turnOffPWM() is a function defined in hardware/arduino/cores/arduino/wiring_digital.c, and it stops the timer.

After that, the port is converted to a register, then calculate logical AND with bit. If the result is not 0, the function returns HIGH, else it returns LOW.

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

The portInputRegister() is a macro defined in hardware/arduino/cores/arduino/Arduino.h. It converts the port to an address. It returns one of the PORTB, PORTC or PORTD. If the port is equal to PB, it returns PORTB.

Because PORTs are addresses, '*' is required to get the content of the address.

If the result of calculating logical AND with bit is not 0 it returns HIGH, if 0 it returns LOW.

Version

Arduino 1.0.5



Turn on JavaScript to display a menu.

Playing with Arduino
Copyright © 2012 garretlab all rights reserved.
inserted by FC2 system