Embedded Systems Design

Low Power and Embedded Systems - Workbook 2


In this workbook we will cover Serial communications using interrupts and the use of the Analogue to Digital Converter.

You may find that you only have time to complete Exercises 1 and 2 during the session. They are quite difficult, and you may need the help of the demonstrators. Exercise 3 takes time, but is more straightforward. Try to complete exercise 3 before the start of week 3. If you get stuck or there are parts you don't understand, then make some notes so you can ask for help from the demonstrators first thing in week 3.

Supporting material



Local copy: http://www.cl.cam.ac.uk/teaching/1314/P31/docs/atmega644p.pdf

Data sheet for the Atmel ATMEGA644P microcontroller used in these exercises. You will need to refer to this frequently. Within these workbooks it will often be referred to as 'the datasheet' The section numbers referred to in these workbooks refer to revision 8011Q of the datasheet dated 02/13. There are a number of devices with almost identical part numbers. They differ in their power consumption. The devices you will use may be marked ATMEGA644P or ATMEGA644PA.

Serial Lead


Specification for the Serial/USB lead used in Exercise 1.



Library USART functions for exercise 3.

Interrupt Vector Table


Table of interrupt vector names for ATMEL AVR series of microcontrollers.



Circuit diagram for connecting the temperature sensor.

mcp9700a datasheet

Latest: http://ww1.microchip.com/downloads/en/devicedoc/21942a.pdf Local copy: http://www.cl.cam.ac.uk/teaching/1314/P31/docs/mcp9700a.pdf

The manufacturers data sheet for the MCP9700A temperature sensor.

MCP1525 datasheet

Latest: http://ww1.microchip.com/downloads/en/devicedoc/21653b.pdf Local copy: http://www.cl.cam.ac.uk/teaching/1314/P31/docs/mcp1525.pdf

The manufacturers data sheet for the MCP1525 voltage reference.

An on-line version of this workbook is available at:


You should check this page regularly for announcements and errata. You might find it useful to refer to the on-line version of this workbook in order to follow any provided web links or to cut and paste example code.

A note on Register and other names



They are defined in the library headers included in the program, for example #include <avr/io.h>

The angle brackets <avr/io.h> instruct the compiler to search for the header files in the standard library header location /usr/lib/avr/include and subdirectories, which means the file io.h will be found at /usr/lib/avr/include/avr/io.h


Variable definitions

The ATMEGA644A microcontroller is an 8 bit device. Unless you specifically need a 16 bit (or wider) variable, you should define variables as 8 bits wide to save memory space.






Exercise 1 - Hello World via a serial data link


The ATMEGA644A microcontroller has two USARTs (Universal Synchronous and Asynchronous Receiver and Transmitter). For a full description of USART operation see section 16 of the datasheet.


Newer devices in the family may have more than one USART, so for reasons of compatibility these devices, which include the ATMEGA644A refer to the USART by number even if there is only one, so the USART would be referred to as USART0, and the register names also include the number for example UCSR0A.

The Exercise


  1. Serial communication relies on a reasonably accurate clock for the Baud rate. The internal oscillator would be accurate enough, but we will switch to using an external 8.000 MHz crystal as the clock source, which entails using the Full Swing Crystal Oscillator option for our microcontroller. We derive the Baud rate clock for serial communication from this clock source. We will use a baud rate of 19200 bits per second, which can be derived from an 8MHz clock accurately. At high baud rates, we would choose a crystal such as 7.3728 MHz to give a clock which can be divided more precisely to minimise the clock error. See Section 16.12 of the datasheet for more details.


Microcontroller Clock

Programming the fuses needs to be followed by a make program, a power cycle is not sufficient. You previously copied and renamed workbook1/exercise2/exercise2.c to workbook2/exercise1/exercise1.c You will need to change exercise2 to exercise1 in the Makefile in 4 places. If no change has been made to the program, then make program should cause the LED to flash 8 times as fast as it did in workbook 1.


USB connection


A datasheet for this device is available from http://www.cl.cam.ac.uk/teaching/1314/P31/docs/usbseriallead.pdf.

Also available is a lab made, right angled 6 way adaptor. On this adaptor the thin pins fit into the prototyping board, and the thicker, square pins connect to the USB lead.


Make sure you only fit the small pins in the prototyping board - the thick pins will damage the board, possibly giving you unreliable connections in future.
PC serial software


The programmer and the USB serial device both use the FT232 serial chip, so there is no way to distinguish the two when they are plugged in. If you always plug the programmer in first, and the serial lead second, then the programmer should be /dev/ttyUSB0 and the serial lead /dev/ttyUSB1 Leave them plugged in to the computer, and if you need to unplug them, do so at the development board end, so they retain their ttyUSB port numbers. It is possible sometimes for the serial ports to lock up, and in this case the only solution is to unplug at the computer and replug. If you suspect the serial port is misbehaving, typing dmesg may tell you more.

Microcontroller software

Refer to section 16 of the datasheet, and write a function to initialise the USART. You will need to refer to section 16.12 to set the correct values for baud rate and framing format, i.e. 19200 Baud, with 8 data bits, no parity and 1 stop bit. This format is written in the style 19200,N,8,1. Turn off double speed. You can assign a value to UBRR0 which is a 16 bit register in one go - the compiler will do the correct thing. When calculating the throughput, note that there is also 1 start bit and 1 stop bit, so transmitting a byte takes 10 bit times.

You will need to set the following registers

void USART0_init(void) {
	UBRR0	=							// Set baud rate to 19200
	UCSR0A	=							// Turn off double speed		
	UCSR0B	=							// Enable Receiver and Tranmsitter.
	UCSR0C	=							// Asynchronous mode, 8 data bits, 1 stop bit, clock polarity = 0 



Section 16.7.1 of the datasheet also has a function to transmit a byte, which you can incorporate in your program.


  • Test for the presence of the 8 MHz clock on PB1
  • If you see graphical characters, then it is likely the baud rate is wrong by a factor of 2, or the clock isn't accurately set.

Exercise 2 - Caeser Cipher Loopback





There are three steps to setting up the interrupt:


    The compiler takes care of the housekeeping part of the interrupt call, e.g. saving hardware register contents and return addresses.


    ISR(USART0_RX_vect) {
    // TODO add code to process the byte received in UDR0


  2. Changing the UCSR0B register so that an interrupt is generated when the correct condition occurs - in this case a byte is received on the serial input.


Note when testing:



Also note that the LED flashing is carried out by the main() portion of the code, and the serial receive and transmit is carried out entirely in the interrupt code. The 1Hz flashing will now be less accurate because the _delay_ms() functions take no account of the time spent in the interrupt routine. This will be addressed in a later workbook.

Exercise 3 - Reading a value from the Analogue to Digital converter

The objective of this exercise is to connect an MCP9700A temperature sensor to one of the analogue inputs on the ATMEGA644A, read the resulting analogue voltage using the built in Analogue to Digital Converter, and transmit the result as a decimal number using the serial interface once every second.

This builds upon the code already written for Exercise 2.

You will need to refer to section 20 of the datasheet for details of the Analogue to Digital converter (ADC). The microcontroller has one 10 bit ADC, which can be programmed to select its input from one of eight IO pins. The 10 bit result can be presented left adjusted or right adjusted in two bytes.


The ADC requires a clock in the frequency range 0-200kHz to function. This is derived from the master CPU clock, currently 8MHz (called clkio).

The ADC also requires a reference voltage, which must be higher than the highest input voltage to be applied. The ADC reference voltage can be derived internally or externally supplied. For this exercise we will use an external voltage reference IC, the MCP1525 to generate our reference voltage of 2.5V.


Listing for USART0_transmit and USART0_transmit_uint8

// Transmit an 8 bit value as a single character via serial

void USART0_transmit( unsigned char data ) {


// Transmit an unsigned 8 bit value via serial as a series of 
//   up to three decimal characters
//   eg 0xFF sent as 255

void USART0_transmit_uint8(uint8_t val) {
	unsigned char buf[3];
	int8_t ptr;
		val /= 10;

Exercise 3 - Debugging

Things to consider when testing



  3. If the result is always zero, does the MCP9700A have a positive supply, and is a capacitor fitted from the output to GND ? You can check the output voltage of the MCP9700A with a scope or multimeter.

    If the result is always high, does the voltage reference have a suitable supply, and is the Aref input at the correct voltage. ?

    Are you reading the correct input ?

    Holding the temperature sensor should make the reading rise.

Reading for next week

The next workbook will use the timers in the microcontroller. Read through sections 12 to 14 of the datasheet to get an overview of the timer capabilities. Don't worry about the detail at this stage - workbook 3 will cover it.

Copyright Ian Wassell and Brian Jones 2009-2013