Technology is in everywhere not in everything

ATmega328P - GPIO - Pin Change Interrupt

Hi everyone,


This post is about using pin change interrupts and I will give a basic example to learn this topic very well. Before starting, we need to recover some terms such as interrupt, ISR and more.
Interrupt is an asynchronous signal to the processor and it indicates an event which needs immediate attention. When an interrupt is received, the processor completes the on-going instruction and redirect the interrupt request. This redirection procedure is called as ISR (Interrupt Service Routine).

Interrupt can be categorized as software based interrupts and hardware based interrupts. In software based interrupts, a special instruction or an exceptional situation might cause this type of interrupts. On the other hand, a signal is sent to the processor from an external unit in hardware based interrupts.

What if we do not use interrupt for detecting pin changes? Are there any alternatives to detect pin changes? Of course, there always exist a way which is called polling technique. Let’s look close the polling technique and its advantages and disadvantages due to using interrupt.
In the polling technique, the processor checks the event continuously. Because of this continuous checking, the processor does not do anything until event occurs. The main disadvantages of polling technique due to the interrupts are; timing accuracy, power consumption, wasting processor time.

In the previous lecture, I mentioned about ATmega328P pins. When you use pin change interrupt, you need to know PCINT value for enabling pin change interrupt for that specific pin.

undefined

Figure 1: Pinout Diagram for 28-pin PDIP[1]

For Arduino UNO users, it seems confusing because there is no information which pin is port-B on Arduino UNO.

undefined

Figure 2: Arduino UNO Pinout Diagram [2]

PCICR (Pin Change Interrupt Control Register) controls the pin change interrupt.

undefined

Figure 3: PCICR Register [3]

undefined

PCMSKn (Pin Change Mask Register) selects which pin change interrupt property is enabled. There are 3 type o PCMSKn and these are PCMSK2, PCMSK1, PCMSK0.


PCMSK2 Register:

undefined

PCMSK1 Register:

undefined

PCMSK0 Register:

undefined

There are 3 steps to use pin change interrupts.
  • Turn on pin change interrupt
  • Decide which pins to interrupt is enabled
  • Write an ISR for those interrupts.

undefined

Figure 8: Circuit Schematic of Lecture 2

 

#include <avr/io.h>
#include <avr/interrupt.h>
int main(void)
{
    DDRB |= 0xFF; // Set all PORT-B pins as output.
    PCICR |= 0b00000100; // Enable pin change interrupt on PORT-D
    PCMSK2 |= 0b00000001; // PIND0 pin change interrupt is enabled
    sei();
    while(1){
        asm("NOP");
    }
    return 0;
}
ISR(PCINT2_vect) {
    PORTB ^= 0xFF;
}

undefined

Figure 9: Oscilloscope Result

The yellow line represents the PD0 pin and blue one represents the one of the LEDs. When the PD0 pin change the ISR will run and toggle the all port-B pins that are connected to the LEDs.

 

Reference

[1] ATmega328P Datasheet
[2] Website
     http://makezine.com/2013/02/06/arduino-uno-pinout-diagram/
[3] ATmega328P Datasheet
[4] ATmega328P Datasheet

ATmega328P - GPIO - Blink a LED

Hi everyone,
This post will cover usage of I/O ports in ATmega328P. I will start with a simple code to blink a LED.

undefined

Figure 1: Pin Diagram for 28-pin PDIP

In the previous figure, the schematic gives us information about ATmega328P pin capabilities and their special property. The following table contains brief information about pins.

 

undefined

undefined

Figure 2: I/O Pin Equivalent Schematic [2]

As can be seen from the Figure 1, All port pins have selectable pull-up resistors and protection diodes for Vcc and GND. What is pull-up or pull-down resistors? Here is a brief information about what they are. Suppose that, there is an input pin and you want to decide the state of pin. Is it high or low? This might be a little bit difficult because of these reasons, pull-up and pull-down resistors are highly used to ensure the pin state. For further information about pull-up and pull-down resistors please visit these sites;

http://playground.arduino.cc/CommonTopics/PullUpDownResistor

https://learn.sparkfun.com/tutorials/pull-up-resistors

 

Let’s look registers for I/O. There are three port pin register bits; PINx, DDRx and PINx. Each register has special purpose. I wondered that why there is not PORTA in Atmega328P and I have found a few sources. I do not know the real reason why PORTA does not exist.

 

http://electronics.stackexchange.com/questions/122017/why-atmega328p-has-no-porta

 

undefined

Figure 3: Register Summary for I/O [3]

 

DDRxn (Data Direction Register) selects the direction of this pin.

undefined

For reading data from register, you can simple use PINx register.

The PORTxn register has different properties according to the pin is input or output. From figure 3, you can see how things change based on pin situation and PORTxn value.

undefined

Figure 4: Port Pin Configuration [4]

If you want to learn more information about ATmega328P, you should read datasheet (section 18.3).

For simulating this lecture, you need to build the following circuit in Proteus. Also, I will share all source and project files.

undefined

Figure 5: Circuit Schematic for Lecture-1

 

Printing ‘Hello World’ on a screen is probably first program that every programmer writes. In embedded world, blinking a led is the first step into embedded programming.

 

#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
    DDRB |= 0xFF; // All PORT-B is configured as an output
    while (1) {
        PORTB |= 0x01; // PINB0 is configured as a high
        _delay_ms (500); // wait 500ms 
        PORTB = 0x00; // PINB0 is configured as a low
        _delay_ms (500); // wait 500ms
    }
    return 0;
}

The main of the example is that blinking the led every 500ms. Because of these reason, the io and delay libraries are included. The io library is about input-output operations and the delay library is about delay.

DDRB is register that controls the port-B pins are output or input. As mentioned in the beginning of the tutorial, if ‘1’ is written to that register, the pin becomes output. Otherwise, it is configured as an input. We must define the pins as output because, we want to control the LEDs. This means that we control the voltage that goes to LEDs.

undefined

As you know, there are 8 pins in Port-B. By writing ‘0xFF’ to PORTB register, all port-B pins are configured as output. Instead of writing ‘0xFF’, we can write ‘0b11111111’ or ‘255’.

‘DDRB |= 0xFF;’, ‘DDRB |= 0b11111111;’, ‘DDRB |= 255’ are same.

In the ‘while (1)’ loop, the ATmega328P will blink the led and waits for 500ms then, turn off the led and waits for 500ms. There are 8 pins in port-B and the LED that is connected to the least significant pin (PINB0) is used. To turn on the LED, we need to write ‘1’ to the PINB0 pin and to turn off the LED, we need to write ‘1’ to the PINB0 pin. These delay function is used for delaying next operation. Thus, LED blinks every 500ms.

undefined

Figure 6: Output of the First Example

undefined

Figure 7: Oscilloscope Output for First Example

According to the oscilloscope result, the LED blinks every 500ms. The high duration is 500ms and low duration is 500ms in PINB0 pin.

 

Home