Simple SD card interface for Arduino

In an earlier circuit I showed a simple way of  adding an SD card to an Arduino. That works well. Sadly because the Arduino is 5 Volts and the SD card needs 3,3 volt levels, a level adapter was used, consisting of resistors.
As said, it works well, but it is not really an elegant solution. It is better to use another chip (The 74HC125)  to do the level shifting, as shown in the figure below:
SD card2

To keep the circuit a bit simple, I have just drawn the buffer gates of this chip, but there are a couple of more pins that need to be connected: Pin 1,4, 7 and 10 Need to be connected to ground. Pin 14 (Vcc) needs to be connected to 3.3 V.

The reason why so many of the pins need to go to ground is because Pin 7 is the regular ground of the chip, but pin 1,4 and 10 are the negative control gates of the buffers that are used. The 74HC125 is a Quad bus buffer so you will have one buffer to spare. It might be wise to connect the input of that buffer (pin 12)  and it’s negative gate (pin 13) to 3.3 V as well to avoid unpredictable behaviour.


RS232 level converter for Arduino

The earlier circuit with an RS232 chip would have my preference  for connecting a self built Arduino to an RS232 port. However, if space is at a premium, a chip with 4 capacitors and a few resistors might just be too much. In that case a levelconverter made from discrete components might be a better choice.


Just to make clear: The TX and RX in the circuit refer to the microcontroller. The Tx signal from the Arduino gets fed to T2 and send to pin 2 of the DB9. That Pin 2 is the receive signal from the PC. The TX signal from the PC is available on Pin 3. This gets fed into T1 who then feeds it to the Rx of the Arduino.

There is a slightly fancier version available:

But the first circuit worked well for me.

Yet another circuit, looks as follows:

With regard to R5 that can be connected to TxD to borrow a negative voltage, but the circuit will only work half duplex then. It can also be connected to ground, which will probably work with most RS232 ports and that will allow Full duplex

One thing you have to keep in mind with these circuits: The RS232 does not trigger an automatic reset of your microcontroller anymore. If you still wish to have that, add another transistor, akin to what is build around T1 and attach that with it’s base side to the CTS and with its collector side to the Reset on the microcontroller, via a 100nF capacitor

Bluetooth for Arduino (or other)

Dealextreme offers a cheap Bluetooth module that can be used to add bluetooth to an Arduino/Atmel project.
Connecting it is really simple as you can see in the below circuit.
As it is on a 3.3 Volt supply, in connevting it to a generally 5 volt TTL UART, you need to keep a couple of things in mind:
Connecting the Tx line directly to the Rx line of the UART is no problem, but for the Tx line coming from the UART you need a voltage adapter that is formed by the 5k6 and 10k resistors.
In order to get the Bluetooth model to work properly, it needs a reset signal that is taken from the Vcc.
Pins that are not used should be left not connected. Though the module has 34 pins, you only really need to connect 8 pins to establish communication and 4 of those are connections to ground.


At first glance, soldering to the module may seem a bit daunting as it is real tiny. I decided to solder some small stiff wires to the cups that form the pins and stick these through some stripboard, raising the module a bit off of the stripboard. Another solution is to solder the module directly to the copperside of a PCB, but that needs some accurate etching. Just to make clear: Pin 3 and 4 don’t need to be connected to anything, but it might be handy to attach them to a 2 pin header that can be shorted in case that is needed.

Using the module is fairly simple: linvor
First establish if it actually works: after putting the circuit together, apply voltage supply and start up a bluetooth device such as a computer or a mobile phone and see if they can find it. It should come up as ‘linvor’  and asks for a pincode which is ‘1234’.

If you check the ‘services’  of the device it will report itself as a serial interface. The LED in the circuit is ON when there is a connection and it ‘blinks’ when there isn’t.
So if this all works, at least that is half of the worries done. Now you got to make sure if the serial interface is actually doing something. You can do that in various ways, but set your communication speed to 9600/8N1 Baud as that is the default baudrate of this chip:

  • Hook it up to a working arduino/atmel/pic controller and see if you can get connection (this one for instance). or
  • Hook it up to a computer’s serial port (but make sure you use a level adapter before you do that coz RS232 voltages will fry yr chip) and see if you can communicate (like sending AT commands). or
  • Connect the Rx and Tx of this circuit, establish a bluetooth connection through yr computer, use the Arduino IDE (select ‘no line ending) to send characters to the proper COM port and see if they get echoed. 

If any of these 3 work you are set to go.

The firmware
Though many of these models may look exactly the same (and in fact could be the same), they still may have different firmware. The Dealextreme module has linvor 1.5 firmware, als known as HC6. Other models may have HC5 firmware.
The HC5 firmware has a very limited AT instruction set:

It can check the settings, it can change the baudrate and parity and it can change the PIN code and the name:

Command Response Note
AT OK Just a check
AT+VERSION Linvor1.5 Firmware version
AT+BAUDx OKx Sets Baudrate
1 for 1200 baud
2 for 2400 baud
3 for 4800 baud
4 for 9600 baud
5 for 19200 baud
6 for 38400 baud
7 for 57600 baud
8 for 115200 baud
9 for 230400 baud
A for 460800 baud
B for 921600 baud
C for 1328400 baud
AT+NAMEstring OKsetname Set device name, 20 characters max
AT+PINxxxx OKsetpin Set PINcode. 1234 bij default
AT+Px OKsetparity Set the parity
N for None
E for even
O for Odd


With the HC6 firmware, there should be no LF or CR after the command. The module will interpret the command that is given within 1 second. As therefore you have 1 second to type the command, it might be better to cut and paste it from e.g. Notepad. Now how to get into AT setting is simple for the HC5 firmware. If the module has not paired with another bluetooth transceiver, it is in AT mode. You may need to connect the CTS and RTS pins and you may need to type ‘$$$’ first

HC5 Firmware
If you have a model with HC5 firmware, you need to do a bit more to get it in AT mode:

This firmware provides 2 ways to activate AT mode :

The first way:

  • set low level on PIN34
  • Supply power to the module
  • set high level on PIN34

Then the module will enter on AT mode with your configured baud rate (default : 9600 8N1)

The second way :

  • set high level on PIN34,
  • Supply power to the module

The module will ALWAYS enter in AT mode with a 38400 baud rate (8N1).
The second way is useful if you don’t remember your configured baud rate.
AT mode can be reached only when PIN34 is high.

Moreover sending AT commands is different from the HC06 firmware (Linvor). In HC05 firmware you have to send CR and LF after each command.

Sme useful AT commands :

  • AT\r\n AT test command should respond OK\r\n
  • AT+ROLE=1\r\n Set master mode
  • AT+ROLE=0\r\n Set slave mode
  • AT+VERSION?\r\n Get the firmware version
  • AT+UART=115200,1,2\r\n Set the baud rate to 115200
  • AT+PIO=10,1\r\n Set PIO10 to high level

Further information can be found in this documentation.



Simple Arduino

Arduino BasicAn arduino in its simplest form is an ATMEGA chip with bootloader, a crystal, 2 capacitors and reset switch. An LED on pin 13 and of course some possibilities to make easy connections are ‘nice to have’.

A simple circuit is found to the right. It is a small adaptation from Iñigo Zuluaga, who is a master in designing nifty circuits with a paper ‘silk screen’. Other people have done similar things like in the paperduino project van Guillherme Martins or the oomlaut arduino and also here.

The circuit is quite easy. Programs can be uploaded with either one of the many USB or serial connector boards or cables

The simple arduino, connected to a serial level converter

Serial connection for your Arduino / Atmega

A connection between a computer and a self build Arduino (or other microcontroller) is easy to make with a MAX232 chip. The figure below is an almost classic design. It is according to the october 2002 revision of the datasheet: C4 is connected between pin2 and earth, while in other designs it is connected between pin 2 and Vcc (kathode on Vcc). This circuit just worked for me. I guessed that if pin 2 has a higher potential than Vcc, it also has a higher potential than ground. In some circuits you will also find it connected between pin 2 and 6

In principle you could do with only 2 signals (Tx and Rd), but I have added a reset that is connected to the RTS signal on the subD connector (Via the Max232 of course) MAX232

Just for some clarification: Normally with a serial communication set up, the Tx signal of one device, is connected to the Rd pin of the other device. In this circuit, that is taken care of on the SubD connector: Pin 3 is the Tx signal, that goes to the RdIn (pin 8)  of the chip. It is converted in voltage in the chip, then goes to RdOut on pin 9. That pin –though called Rd-  then goes to the Rd pin on the Arduino/Atmega/Pic. The connection between Tx and Rd already has been made, no need to switch that again.
Same for the Tx signal of the microprocessor: It attaches to pin10 on the Max232, is converted and appears on pin 7 of the chip and then is brought to the Rd pin on the SubD connector. The DB9 plug in th epicture is a female plug looked at from the solder side.
If for any reason one would prefer to use an old SubD25 serial connector, the table below shows the corresponding pins between the two. To make things a bit confusing both pin 2 and 3 have exactly opposite functions on these connectors.

DB9 Signal DB25
1 DCD 8
2 Rd 3
3 Tx 2
4 DTR 20
5 SGnd 7
6 DSR 6
7 RTS 4
8 CTS 5
9 Ri 22

The LED’s and  resistors R3 and R4 are not really necessary, they just give a visual indication of the transmitting signals, choose a nice color.

R1 and R2 are in fact also not necessary, but they offer some form of protection should you wire up wrong (like connecting to the wrong pin on your microprocessor)

RS232 naar TTL op stripboard

Once the circuit is build, then first test it before you attach it to your Arduino. The easiest way to test it is to temporarily connect the Tx and Rd pin (so the ends of R1 and R2) with eachother. Apply 5 volts to the chip and connect your serial cable.

Open up the Arduino IDE, select the proper COM port under ‘Tools’, open up the serial monitor and type in some characters and click ‘Send’. The characters should be echo-ed back.

For me this worked with all baud-rates.

Then disconnect the temporary connection you just made and connect Tx and Rd to the corresponding pins on your board/chip.

If that has the bootloader installed, you should be able to upload a program to your board with this serial connection.

Worked like a charm

The finished circuit on stripboard. I opted for a 25DB connector rather than a 9DB connector because that fitted the serial cable I had. Don’t be confused by the double row of headers. Again, that is all I had but a single row would suffice
The serial interface, connected to a simple arduino board

Note: Many ‘modern’ computers that  still have a serial connector do in fact already not work with the high voltages that we know from true RS232 and then the MAX232 might not be needed, but one could use a levelshifter as e.g. Sparkfun is selling ($6.95) and try to build that yourself. It is not a big circuit, but in my idea, usung the MAX232 is just easier and the RS232Shifter board is actually a bit of a hack and does not seem as reliable.

Lots of RS232 info here. and here

Another one here, and here, and here, and here, and here, and here (Thai)

Max 232


Timer interrupts

This article will discuss AVR and Arduino timers and how to use them in Arduino projects or custom AVR circuits.

What is a timer?

Like in real life, in microcontrollers a timer is something you set to trigger an alert at a certain point in the future. When that point arrives, that alert interrupts the microprocessor, reminding it to do something, like run a specific piece of code.

Timers, like external interrupts, run independently from your main program. Rather than running a loop or repeatedly calling millis(), you can let a timer do that work for you while your code does other things.

So suppose you have a device that needs to do something –like blink an LED every 5 seconds. If you are not using timers but just conventional code techniques, you’d have to set a variable with the next time the LED should blink, then check constantly to see if that time had arrived. With a timer interrupt, you can set up the interrupt, then turn on the timer. The LED will blink perfectly on time, regardless of what your main program was just doing

How do timers work?

Timers work by incrementing a counter variable known as a counter register. The counter register can count to a certain value, depending on its size (usually 8 bits or 16 bits). The timer increments this counter one step at a time until it reaches its maximum value, at which point the counter overflows, and resets back to zero. The timer normally sets a flag bit to let you know an overflow has occurred. This flag can be checked manually, or you can have the timer trigger an interrupt as soon as the flag is set. And as with any other interrupt, you can specify an Interrupt Service Routine (ISR) to run your own code when the timer overflows. The ISR will automatically reset the overflow flag, so using interrupts is usually your best option for simplicity and speed.

To increment the counter value at regular intervals, the timer must have a clock source.  The clockprovides a consistent signal.  Every time the timer detects this signal, it increases its counter by one.

Since timers are dependent on the clock source, the smallest measurable unit of time will be the period of the clock.  If you provide a 16 MHz clock signal to a timer, the timer resolution (or timer period) is:

T = 1 / f  (f is the clock frequency)
T = 1 /(16* 10^6)
T = (0.0625 * 10^-6) s

The timer resolution thus is 0.0625 millionth of a second.

For 8 MHz this would be 0.125 millionth of a second

and for 1 MHz exactly one millionth of a second

You can supply an external clock source for use with timers, but usually the chip’s internal clock is used as the clock source. The 16 MHz crystal that is usually part of a setup for an Atmega328 can be considered as part of the internal clock.

Different timers

In the standard Arduino variants or the 8-bit AVR chips, there are several timers at your disposal.

The ATmega8, ATmega168 and ATmega328 have three timers: Timer0, Timer1, and Timer2. They also have a watchdog timer, which can be used as a safeguard or a software reset mechanism. The Mega series has 3 additional timers.


Timer0 is an 8-bit timer, meaning its counter register can record a maximum value of 255 (the same as an unsigned 8-bit byte). Timer0 is used by native Arduino timing functions such as delay() and millis(), so unless you know what you are doing, timer 0 is best left alone.


Timer1 is a 16-bit timer, with a maximum counter value of 65535 (an unsigned 16-bit integer). The Arduino Servo library uses this timer, so keep that in mind if you use this timer in your projects.


Timer2 is an 8-bit timer that is very similar to Timer0. It is used by the Arduino tone() function.

Timer3, Timer4, Timer5

The AVR ATmega1280 and ATmega2560 (found in the Arduino Mega variants) have an additional three timers.  These are all 16-bit timers, and function similarly to Timer1.

Configuring the timer register

In order to use these timers the built-in timer registers on the AVR chip that store timer settings need to be configured.  There are a number of registers per timer.  Two of these registers –the Timer/Counter Control Registers- hold setup values, and are called TCCRxA and TCCRxB, where x is the timer number (TCCR1A and TCCR1B, etc.).   Each register holds 8 bits, and each bit stores a configuration value.  The ATmega328 datasheet specifies those as follows:

Bit 7 6 5 4 3 2 1 0 TCCR1A
0x80 COM1A1 COM1A0 COM1B1 COM1B0 WGM11 WGM10
Initial Value 0 0 0 0 0 0 0 0
Bit 7 6 5 4 3 2 1 0 TCCR1B
0x81 ICNC1 ICES1 WGM13 WGM12 CS12 CS11 CS10
ReadWrite R/W R/W R R/W R/W R/W R/W R/w
Initial Value 0 0 0 0 0 0 0 0

The most important settings are the last three bits in TCCR1B, CS12, CS11, and CS10.  These determine the timer clock setting.  By setting these bits in various combinations, you can make the timer run at different speeds.  This table shows the required settings:

Clock Select bit description
CS12 CS11 CS10 Description
0 0 0 No clock source (Timer/Counter stopped)
0 0 1 clki/o/1 (No prescaling)
0 1 0 clki/o/8 (From Prescaler)
0 1 1 clki/o/64 (From Prescaler)
1 0 0 clki/o/256 (From Prescaler)
1 0 1 clki/o/1024 (From Prescaler)
1 1 0 External clock source on T1 pin. Clock on falling edge
1 1 1 External clock source on T1 pin. Clock on rising edge

By default, these bits are set to zero.  Suppose you want to have Timer1 run at clock speed, with one count per clock cycle.  When it overflows, you want to run an Interrupt Service Routine (ISR) that toggles a LED tied to pin 13 on or off. Below you will find the Arduino code for this example, for completeness I use avr-libc routines wherever they don’t make things overly complicated.

First, initialize the timer:

// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 13

void setup()
// initialize Timer1
cli();         // disable global interrupts
TCCR1A = 0;    // set entire TCCR1A register to 0
TCCR1B = 0;    // set entire TCCR1B register to 0 
               // (as we do not know the initial  values) 

// enable Timer1 overflow interrupt:
TIMSK1 | = (1 << TOIE1); //Atmega8 has no TIMSK1 but a TIMSK register

// Set CS10 bit so timer runs at clock speed: (no prescaling)
TCCR1B |= (1 << CS10); // Sets bit CS10 in TCCR1B
// This is achieved by shifting binary 1 (0b00000001) // to the left by CS10 bits. This is then bitwise // OR-ed into the current value of TCCR1B, which effectively set // this one bit high. Similar: TCCR1B |= _BV(CS10); // enable global interrupts: sei(); }

The register TIMSK1 is the Timer/Counter1 Interrupt Mask Register. It controls which interrupts the timer can trigger. Setting the TOIE1 bit (=Timer1 Overflow Interrupt Enable) tells the timer to trigger an interrupt when the timer overflows. It can also be set to other bits to trigger other interrupts. More on that later.

When you set the CS10 bit, the timer is running, and since an overflow interrupt is enabled, it will call the ISR(TIMER1_OVF_vect) whenever the timer overflows.

Next define the ISR:


digitalWrite(LEDPIN, !digitalRead(LEDPIN));
// or use: PORTB ^= _BV(PB5);// PB5 =pin 19 is digitalpin 13

Now you can define loop() and the LED will toggle on and off regardless of what’s happening in the main program. To turn the timer off, set TCCR1B = 0 at any time.

How fast will the LED blink with this code?

Timer1 is set to interrupt on an overflow, so if you are using an ATmega328 with a 16MHz clock. Since Timer1 is 16 bits, it can hold a maximum value of (2^16 – 1), or 65535. At 16MHz, we’ll go through one clock cycle every 1/(16*10^6) seconds, or 6.25*10-8 s. That means 65535 timer counts will pass in (65535 * 6.25*10-8s) and the ISR will trigger in  about 0.0041 seconds. Then again and again, every four thousandths of a second after that. That is too fast to see it blink. If anything, we’ve created an extremely fast PWM signal for the LED that’s running at a 50% duty cycle, so it may appear to be constantly on but dimmer than normal. An experiment like this shows the amazing power of microprocessors – even an inexpensive 8-bit chip can process information far faster than we can detect.

Timer prescaling and preloading

To control this you can also set the timer to use a prescaler, which allows you to divide your clock signal by various powers of two, thereby increasing your timer period.  For example, if you want the LED blink at one second intervals. In the TCCR1B register, there are three CS bits to set a better timer resolution.  If you set CS10 and CS12 using:

TCCR1B |= (1 << CS10); and TCCR1B |= (1 << CS12);, the clock source is divided by 1024. This gives a timer resolution of 1/(16*10⁶ / 1024), or 0.000064 seconds (15625 Hz). Now the timer will overflow every (65535 * 6.4*10-5s), or 4.194s.

If you would set only CS12 using TCCR1B |=(1<<CS12); (or just TCCR1B=4), the clock source is divided by 256. This gives a timer resolution of 1/(16*10⁶/256), or 0.000016 sec (62500 Hz) and the timer will overflow every (65535 *0.000016=) 1.04856 sec.

Suppose you do not want an 1.04856 sec interval but a 1 sec interval. It is clear to see that if the counter wasn’t 65535 but 62500 (being equal to the frequency), the timer would be set at 1sec. The counter thus is 65535-62500=3035 too high. To have more precise 1 second timer we need to change only one thing – timer’s start value saved by  TCNT1 register (Timer Counter ). We do this with TCNT1=0x0BDB; BDB being the hex value of 3035. A Value of 34286 for instance would give 0.5 sec ((65535-34286)/62500)

The code looks as follows:

// avr-libc library includes
#include <avr/io.h> //  can be omitted
#include <avr/interrupt.h> // can be omitted
#define LEDPIN 13
/* or use
DDRB = DDRB | B00100000;  // this sets pin 5  as output                       // without changing the value of the other
                         // pins 
void setup()

// initialize Timer1
cli();         // disable global interrupts
TCCR1A = 0;    // set entire TCCR1A register to 0
TCCR1B = 0;    // set entire TCCR1A register to 0

// enable Timer1 overflow interrupt:
TIMSK1 |= (1 << TOIE1);
// Preload with value 3036
//use 64886 for 100Hz
//use 64286 for 50 Hz
//use 34286 for 2 Hz
// Set CS10 bit so timer runs at clock speed: (no prescaling)
TCCR1B |= (1 << CS12); // Sets bit CS12 in TCCR1B
// This is achieved by shifting binary 1 (0b00000001)
// to the left by CS12 bits. This is then bitwise
// OR-ed into the current value of TCCR1B, which effectively set
// this one bit high. Similar: TCCR1B |= _BV(CS12);
//  or: TCCR1B= 0x04;

// enable global interrupts:

digitalWrite(LEDPIN, !digitalRead(LEDPIN));
TCNT1=0x0BDC; // reload the timer preload

void loop() {}


But there’s another mode of operation for AVR timers. This mode is called Clear Timer on Compare Match, or CTC. Instead of counting until an overflow occurs, the timer compares its count to a value that was previously stored in a register. When the count matches that value, the timer can either set a flag or trigger an interrupt, just like the overflow case.

To use CTC, you need to figure out how many counts you need to get to a one second interval. Assuming we keep the 1024 prescaler as before, we’ll calculate as follows:

(target time) = (timer resolution) * (# timer counts + 1)

and rearrange to get


(# timer counts + 1) = (target time) / (timer resolution)
(# timer counts + 1) = (1 s) / (6.4e-5 s)
(# timer counts + 1) = 15625
(# timer counts) = 15625 - 1 = 15624

You have to add the extra +1 to the number of timer counts because in CTC mode, when the timer matches the desired count it will reset itself to zero. This takes one clock cycle to perform, so that needs to be factored into the calculations. In many cases, one timer tick isn’t a huge deal, but if you have a time-critical application it can make all the difference in the world.

Now the setup() function to configure the timer for these settings is as follows:

void setup()

pinMode(LEDPIN, OUTPUT); // you have to define the LEDPIN as say 13
                         // or so earllier in yr program
// initialize Timer1
cli();          // disable global interrupts
TCCR1A = 0;     // set entire TCCR1A register to 0
TCCR1B = 0;     // same for TCCR1B

// set compare match register to desired timer count:
OCR1A = 15624;

// turn on CTC mode:
TCCR1B |= (1 << WGM12);

// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);

// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
sei();          // enable global interrupts

And you need to replace the overflow ISR with a compare match version:


digitalWrite(LEDPIN, !digitalRead(LEDPIN));

The LED will now blink on and off at precisely one second intervals. And you are free to do anything you want in loop(). As long as you don’t change the timer settings, it won’t interfere with the interrupts. With different mode and prescaler settings, there’s no limit to how you use timers.

Here’s the complete example in case you’d like to use it as a starting point for your own project.

// Arduino timer CTC interrupt example
// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 13
void setup()
// initialize Timer1
cli();          // disable global interrupts
TCCR1A = 0;     // set entire TCCR1A register to 0
TCCR1B = 0;     // same for TCCR1B

// set compare match register to desired timer count:
OCR1A = 15624;

// turn on CTC mode:
TCCR1B |= (1 << WGM12);

// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);

// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);

// enable global interrupts:

void loop()
// main program

digitalWrite(LEDPIN, !digitalRead(LEDPIN));

Remember that you can use the built-in ISRs to extend timer functionality. For example, if you wanted to read a sensor every 10 seconds, there’s no timer set-up that can go this long without overflowing. However, you can use the ISR to increment a counter variable in your program once per second, then read the sensor when the variable hits 10. Using the same CTC setup as in our previous example, the ISR would look something like this:


if(seconds == 10)
seconds = 0;

For a variable to be modified within an ISR, it is good custom to declare it as volatile. In this case, you need to declare volatile byte seconds; or similar at the start of the program.

A word on the Atmega8

The Atmega8 seems to give people problems with use of the timers, one reason is that it doesn’t have a TIMSK1 register (in fact it doesnt have a TIMSKn register), it does have a TIMSK register though that is shared amongst the 3 timers. As I do not have an Atmega8 (like the early Arduino NG) I can not test it, but if you encounter problems, the following programs will help:

// this code sets up counter0 with interrupts enabled on an Atmega8
// beware, it may generate  errors in Arduino IDE 
// as 'milis' uses timer0 
#include <avr/io.h>
#include <avr/io.h>

void setup()
DDRD &= ~(1 << DDD4); // Clear the PD4 pin
// PD0 is now an input

PORTD |= (1 << PORTD4); // turn On the Pull-up
// PD4 is now an input with pull-up enabled

TIMSK |= (1 << TOIE0); // enable timer interrupt

TCCR0 |= (1 << CS02) | (1 << CS01) | (1 << CS00);
// Turn on the counter, Clock on Rise

void loop()
// Stuff

// interrupt just fired, do stuff

A 1 sec flasher using the timer 1 CTC mode for the Atmega 8 would look like this:


void setup()
/* or use:
DDRB = DDRB | B00100000;  // this sets pin 5  as output
                       // without changing the value of the other pins 
// Disable interrupts while loading registers
// Set the registers
TCCR1A = 0; //Timer Counter Control register
// Set mode
TCCR1B = (1 << WGM12); // turn on CTC mode
// Set prescale values (1024). (Could be done in same statement
// as setting the WGM12 bit.)
TCCR1B |= (1 << CS12) | (1 << CS10);
//Enable timer compare interrupt===> TIMSK1 for ATmega328, 
//TIMSK for ATmega8
TIMSK |= (1 << OCIE1A);
// Set OCR1A
OCR1A = 15624;
// Enable global interrupts
void loop(){}
   digitalWrite(13, !digitalRead(13));
   //PORTB ^= _BV(PB5); // as digitalWrite(13,x) is an Arduino 
   //function, direct writing to the port may be preferable

It is obvious that this is very akin to the CTC program presented earlier for the Atmega328 and in fact will work on the Atmega238 as well by renaming ‘TIMSK’ to ‘TIMSK1’

Other Atmega chips:

TCCR0 should be TCCR0A in ATmega164P/324P/644


The Attiny series has timer interrupts too. This code sets up a 50uS timer in CTC mode on the Attiny85 (pag 79 datasheet)

TCCR0A = (1 << WGM01);   //CTC mode. set WGM01
TCCR0B = (2 << CS00);    //divide by 8  sets 
OCR0A = F_CPU/8 * 0.000050 - 1;    // 50us compare value
TIMSK |= (1<<OCIE0A);              //set interrupt

                                   // code of choice!

I wrote a follow up with some practical examples.

More on timers here








pwm generation by timers

here (Atmega8)

Atmega8 Datasheet

Atmega328 Datasheet

Arduino hardware interrupt

What is an interrupt?

On a very basic level, an interrupt is an signal that interrupts the current processor activity. It may be triggered by an external event (change in pin state) or an internal event (a timer or a software signal).  Once triggered, an interrupt pauses the current activity and causes the program to execute a different function.  This function is called an interrupt handler or an interrupt service routine (ISR).  Once the function is completed, the program returns to what it was doing before the interrupt was triggered.


If you’re new to the world of software development, you might wonder why all this complication is necessary just to respond to external events.  After all, you can check the state of external pins at any time, or create your own timers.

You certainly can do all of these things in your main code, but interrupts give you a key advantage – they are asynchronous.  An asynchronous event is something that occurs outside of the regular flow of your program – it can happen at any time, no matter what your code is crunching on at the moment.  This means that rather than manually checking whether your desired event has happened, you can let your AVR do the checking for you.

Let’s use a real-world example.  Imagine you’re sitting on your couch, enjoying a frosty brew and watching a movie after a long day.  Life is good.  There’s only one problem: you’re waiting for an incredibly important package to arrive, and you need it as soon as possible.  If you were a normal AVR program or Arduino sketch, you’d have to repeatedly stop your movie, get up, and go check the mailbox every 5 minutes to make sure you knew when the package was there.

Instead, imagine if the package was sent Fedex or UPS with delivery confirmation.  Now, the delivery man will go to your front door and ring the doorbell as soon as he arrives. That’s your interrupt trigger.  Once you get the trigger, you can pause your movie and go deal with the package.  That’s your interrupt service routine.  As soon as you’re done, you can pick up the film where you left off, with no extra time wasted. That’s the power of interrupts.

The AVR chips used in most Arduinos are not capable of parallel processing, i.e. they can’t do multiple things at once.  Using asynchronous processing via interrupts enables us to maximize the efficiency of our code, so we don’t waste any precious clock cycles on polling loops or waiting for things to occur.  Interrupts are also good for applications that require precise timing, because we know we’ll catch our event the moment it occurs, and won’t accidentally miss anything.

Types of Interrupts

There are two main types of interrupts:

  • Hardware interrupts, which occur in response to an external event, such as an input pin going high or low
  • Software interrupts, which occur in response to an instruction sent in software

8-bit AVR processors, like the ones that power most Arduino boards, aren’t capable of software interrupts. So we’ll focus on hardware for now.  Most tutorials out there talk about handling external interrupts like pin state changes.  If you’re using an Arduino, that’s the only type of interrupt the Arduino “language” supports, using the attachInterrupt() function.  That’s fine, but there’s a whole different category of hardware interrupts that rely on the AVR’s built in timers, which can be incredibly useful.  We’ll cover external interrupts in this tutorial, then go over timer interrupts in a follow-up tutorial, since there’s enough information to warrant splitting things up.

How to get an interrupt to do what we want – Interrupt Service Routines

Every AVR processor has a list of interrupt sources, or vectors, which include the type of events that can trigger an interrupt.  When interrupts are enabled and one of these events occur, the code will jump to a specific location in program memory – the interrupt vector.  By writing an ISR and then placing a link to it at the interrupt vector’s memory location, we can tell our code to do something specific when an interrupt is triggered.

Let’s implement this using a simple example: detecting when a pushbutton has been pressed, and performing an action based on that press.

Implementing an interrupt in a program

In order to successfully use an interrupt, we’ll need to do three things:

  1. Set the AVR’s Global Enable Interrupts bit in Status Register
  2. Set the interrupt enable bit for our specific interrupt vector (each vector has it’s own on/off switch)
  3. Write an ISR and attach it to our target interrupt vector

Starting with the first step, we’ll include the interrupt library from avr-libc, then use an avr-libc function to set our global interrupt enable bit.  Next, we need to enable the interrupt we want.  Most 8-bit AVR’s like the ATMega328 have 2 hardware interrupts, INT0 and INT1.  If you’re using a standard Arduino board, these are tied to digital pins 2 and 3, respectively.  Let’s enable INT0 so we can detect an input change on pin 2 from a button or switch.

#include <avr/interrupt.h> //Not really needed for Arduino
void setup(void){sei();  // Enable global interrupts
EIMSK |= (1 << INT0);    // Enable external interrupt INT0

Next, we need to set the sensing method of our interrupt.  For a pin change interrupt, we have four options: rising edge, falling edge, any logical state change, or a low level on the pin.  The default for INT0 and INT1 is to trigger on the pin being low level; you can use the datasheet to read more about how to set each method.  Let’s use falling edge for this example, just to show how it’s done.

EICRA |= (1 << ISC01);    // Trigger INT0 on falling edge

Finally, we’ll define an ISR that performs our desired task.  Every ISR is defined as:

// Perform task here

where {vector} is the name of our chosen interrupt vector.  Again, the names of these vectors are defined in the processor datasheet; here, the one we want is INT0.  For this example, we’ll use the ISR to toggle the built-in LED on pin 13. With our LED code added, here’s how it looks all together:

#include <avr/interrupt.h> //not really needed for arduino 
void setup(void)
  pinMode(2, INPUT);
  digitalWrite(2, HIGH); // Enable pull-up resistor
  sei();                 // Enable global interrupts
  EIMSK |= (1 << INT0);  // Enable external interrupt INT0
  EICRA |= (1 << ISC01); // Trigger INT0 on falling edge
void loop(void)
// Interrupt Service Routine attached to INT0 vector
 digitalWrite(13,!digitalRead(13));// Toggle LED on pin 13

Note that we can use the program’s main loop() to do anything we want in the meantime, and it won’t affect the functionality of our LED toggle.

Arduino interrupt functionality

There’s an alternative way to implement INT0 and INT1 using the Arduino programming “language”. I put “language” in quotes because although that’s how the Arduino website refers to it, it’s more like a wrapper around avr-libc to make certain things easier. But that’s an article for another day. For our example, we could use the attachInterrupt() function to enable the same interrupt in setup():

attachInterrupt(0, pin2ISR, FALLING);

In this case, we define our own custom ISR (pin2ISR) and pass it as an argument. pin2ISR() would simply take the place of ISR(EXT_INT0_vect). This is often a bit simpler than using the raw avr-libc functions, and it does abstract away any difference in chip models. However, the AVR methods described earlier can be used with any interrupt vector, while attachInterrupt() only works with external interrupts.

Putting it all together

There are a few final things to keep in mind when implementing interrupts.
First, keep in mind that whatever you use your ISR for, it’s good practice to keep it short, because while the ISR is executing, it’s holding up the rest of your program. If you have lots of interrupts, this can slow things to a crawl. Also, by “the rest of your program”, we do mean everything: Arduino functions like millis() won’t increment, and delay() won’t work within an ISR.
Next, if you want to modify any variables within your ISR, you’ll need to make them global variables and mark them as volatile to ensure that your ISR has proper access to them. For example, instead of globally declaring

int myInterruptVar;

you would declare

volatile int myInterruptVar;

Finally, interrupts are normally globally disabled inside of any ISR (this is why delay() and millis() don’t work). This means that if more interrupt events occur before your ISR has completed, your program won’t catch them. This is another reason to keep ISRs short.

Wrapping up

That’s about it for the basics. If you’re ready to keep going, check out my followup article on timer interrupts. It builds on the concepts discussed here and helps you use the AVR’s built-in timers to do useful things. In the meantime, implement this example and dive into the Atmel datasheets to discover other interrupt vectors. They sky’s the limit!

PCInt and PCChangeInt libraries mentioned on the Arduino site here: with samples here: which gives you flexibility to use any pin for an interrupt.

A common example of where you use interrupts is using quadrature encoders on motors.   As the motor spins two signals come in from the encoders which can be captured with interrupts to determine direction, speed, and amount of rotation of your motors.

Sample code can be found here:
See also: Newbies guide on timers