4.2 Relationship among PORTX, PINX, DDRX; pinMode(); digitalWrite(), bitSet(), bitClear(), bitWrite(); digitalRead(), bitRead(); PORTX = 0xNN, DDRX = 0xNN
1. PORTB: PORTB stands for Port-B Register (PBR). It is a latch type (Flip-flop) register; it receives data from the Processor Unit (PU) for the output port-lines (PB5-PB0). We may recognize PORTB as a 'Data Transmission Register' for those port-lines which have been configured to work as output. In the present case, we have only one output port-line (PB5).
There is no internal pull-up resistor associated with an output port-line.
2. PINB: PINB stands for Pin-B Register. It receives data from the pins of the input port-lines (PB5-PB0). We may recognize PINB as a 'Data Reception Register' for those port-lines which have been configured to work as input. In the present case, we have only one input port-line (PB0).
Every input port-line is associated with an internal pull-up resistor, which (by default) remains disconnected. It can be connected with input line using program instruction.
3. DDRB: The full-name of DDRB is Data Direction Register for port-lines (PB5-PB0). This register helps to set the directions of the IO lines (port-lines) either as input or output depending on the requirement.
To set the direction of a port-line (say, PB5) as output, we write LH (1) at the corresponding bit (DDRB5) of the DDRB register. To set direction as input, we store LL (0) at the corresponding bit of DDRB.
4. Setting Direction of Port-line:
(a) To set the the direction of a single port-line (PB5) as output, we use the following function:
pinMode(DPin, value);
===> pinMode(13, HIGH);
(b) To set the the direction of a single port-line (PB0) as input with internal pull-up resistor
connected, we use the following function:
pinMode(DPin, value);
===> pinMode(8, INPUT_PULLUP);
(c) To set the the direction of all the six (6) port-lines (PB5-PB0) as output at the same time, we
take the help of DDRB register and use the following assignment statement:
DDRB = B00111111; //Leading two zeros are padding bits; B is notation for binary
===> DDRB = 0xFF; //0x is notation for hexadecimal number.
(d) To set the the direction of all the six (6) port-lines (PB5-PB0) as input (without internal pull-up
register) at the same time, we take the help of DDRB register and use the following assignment
statement:
DDRB = B00000000;
===> DDRB = 0x00;
(e) To connect internal pull-up resistors with all the input port-lines (PB5-PB0) of Step-4d, we use the
following assignment statements:
DDRB = B00000000; // port-pins must be set as inputs
PORTB = B00111111; // 1s should be written to PORTB see Figure-2
LL ---> PUD-bit (Bit-4) of MCUCR; bitClear (MCUCR, 4); //see Figure-2
(f) In summary: (due to CrossRoads of Arduino Forum)
Or just use one of these in setup(), easier to remember and not mess it up:
pinMode (pinX, INPUT); // pinX = 0 to 13, A0 to A5
pinMode (pinX, INPUT_PULLUP);
pinMode (pinX, OUTPUT);
5. Writing Data into Port-line:
(a) To write 1-bit (0 or 1) into a port-line (PB5), we use the following function:
(i) digitalWrite(DPin, Value);
===> digitalWrite(13, HIGH);
(ii) bitSet(13); //writing LH at PB5
bitClear(13); //writing LL at PB5
(iii) bitWrite(PORTX, n, x); // X = B/C/D, n=Bit_position, x = Bit_value
===> bitWrite(PORTB, 5, HIGH);
(b) To write to all port-lines (PB5-PB0) at the same time, we use the following statements:
PORTB = 0xFF; // 1s are written to all pins
PORTB = 0x00; // 0s are written to all pins
(c) In summary
digitalWrite(Dpin, Value); //DPin = 0 to 13, A0 to A5
bitSet(VAR, n); // VAR (variable) PORTX, DDRX; n = 0 to 7
bitClear(VAR, n);
bitWrite(VAR, n, x); // x = HIGH or LOW
6. Reading Data from Port-line:
(a) To read 1-bit data from a port-line, we use the following functions:
(i) boolean x = digitalRead(8
); //reading 1-bit data
(ii) boolean x = bitRead(PORTB, 0);
(b) To read data from all the port-lines at the same time, we use the following assignment
statement:
byte x = PINB;
(c) In summary
boolean y = digitalRead(Dpin); //DPin = 0 to 13, A0 to A5
boolean z = bitRead(VAR, n); // VAR (variable) PINX; n = 0 to 7
byte = PINX; // PINX = PINB, PINC, PIND
7. Examples:
(a) Write C/C++ codes to check that K1-switch of Figure-1 is closed and only then keep blinking
L (built-in LED) at 1-sec interval. Test the program (sketch) using Arduino UNO Kit. Use
goto statement and if-else structure.
void setup() //keep under this functions those tasks that are executed only for once/limited number
//of times.
{
//set direction of IO lines as needed (known as initialisation)
pinMode(13, OUTPUT); //PB5 as outut port-line
pinMode(8, INPUT_PULLUP); // PB0 as input port-line with internal pull-up resistor enabled
//check if K1 is closed or not
L1: boolean x = digitalRead(8);
L2: if (x != LOW)
goto L1;
}
void loop() //keep under this function those tasks that keeps executing
{
digitalWrite(13, HIGH);
delay(1000);
bitWrite(PORTB, 5, LOW);
delay(1000);
}
8. Exercises:
(a) Repeat Example-(a) using while-do structure instead of goto, if-else.
(b) Discuss merits and demerits of the programs of Example-(a) and Exercise-(a).
(c) Repeat Exercise-(a) by including cli() instruction under setup() function (before while-
- do*). Observe that the L is not blinking even though you have closed K1. Find the exact reason
for the L not to blink and then solve the problem by keeping the cli() instruction.