Serial Communications with the ATtiny84

ATtiny TX

In a previous post, I talked about serial communications with an ATmega168. But that chip has USART – hardware support for serial communications. But what about the tinyAVRs? As continuation of my last post on setting up the ATtiny84 for programming, this time, I will talk about sending data from an ATtiny84 to a computer using serial communications.

First, I recommend that you watch this fun and informative video on serial communications by Pete from Sparkfun, USA:

So, now that we have some idea about serial communications, let’s talk about implementing a transmit only (TX) for the ATtiny84. Here is our scheme:

Serial Comms

The above image shows the transmission of a byte (with value 0×95). The value is sent one bit at a time, starting with the least significant bit (LSB), every 1/9600 seconds, thus giving us a baud rate of 9600. The data format for a packet for the 9600 baud 8-N-1 serial connection is as follows:


(In the above, the 2 idle bits at the end are not strictly necessary.)

So how do we implement sending a bit every 1/9600 seconds? For this, we use the 16-bit timer (Timer1) of the Attiny84 in CTC mode. The value for the top of the counter is calculated as shown in the image above.

In the ISR for the timer, we keep track of the current data byte and the current bit being sent, and keep setting the output pin high/low as appropriate.

Here is the code that implements the above ideas.

The Makefile is the same as we used in the ATtiny84 introduction post:

This is the schematic for wiring it up:


Here is what the breadboard setup looks like:

ATtiny TX

And here is the output from CoolTerm. It was surprisingly easy to get this working. ;-)



On OS X, you can use the screen command to see the serial output. For example:

$ screen /dev/tty.usbserial-A7006Yqh 9600

2 thoughts on “Serial Communications with the ATtiny84”

  1. Very cool post. I’ve done this before with the exact same chip, except I do like your approach a lot better. I used the delay_us function instead of using the timer. Obviously the timer is better and more accurate. I do have a question and a suggestion. For the suggestion, perhaps you could use #define to create a constant for baud, and a second #define to calculate the number of ticks (where you could use F_CPU in the formula).

    For the question, after calling init_serial(), the timer interrupt runs for the rest of the program right? So every 1/9600 seconds your running program is interrupted, even if only briefly (whether or not you’re sending data), right? Would there be a way to turn off the interrupt whilst not sending data?

  2. Thanks very much for your comment.

    Yes, I agree – it would be good to have an option to define the baud rate. For my next project, I am going to get the ATtiny84 to talk to an ultrasonic sensor, and at that point, I’ll try to improve this section.

    Yes, the interrupt can be turned off by stopping the clock in the TCCR1B register. But we need to be also careful to reset the count TCNT1 to 0 before restarting it. But this interrupt has minimal overhead, and I am not sure, but not sending an idle (bit) every 1/9600 may disrupt the serial communications connection.

Add Comment Register

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>