Showing posts with label Atmel. Show all posts
Showing posts with label Atmel. Show all posts

Saturday, September 21, 2019

Programming the ATmega328P Registers and Interrupts

Why Use Register Programming?


Figure 1. The registers of interest

Normally you wouldn't bother to use register programming for the Arduino family. The libraries provided with the Arduino IDE do all the heavy lifting and make it easy to program the microprocessor without knowing exactly how it works. This convenience and readability is not without a cost though and sometimes for reasons of speed, code size or power consumption you will need to get closer to the metal. An example of this is writing a flight controller for a drone. For a realtime application like this (depending on the Arduino model) you are probably going to need to directly access the I/O registers and interrupts.

I’m afraid this is a fairly tedious way to code! I will try to explain why we are selecting the values in the code, otherwise it looks like gibberish! The comment numbers (e.g. C1) are referenced in the explanation below.

Hello World AKA Blink


The hardware equivalent of Hello World is to blink a LED. To demonstrate what you can do with registers and interrupts we will start with that example. There are many different ways to write this code. The complete listing is shown below.


C1:: We are using Timer 0 which is an 8 bit timer with two independent Output Compare Units, and PWM support (see Figure 1). The PWM outputs are mapped to D5 and D6 but we don’t need these here. We want to detect when the counter reaches the value stored in the OCR0A Register. The Output Compare Registers (OCR0A and OCR0B) are compared with the Timer/Counter value and can be used to generate an Output Compare interrupt request. We can use this to toggle our LED.

Figure 2. TCCR0A & TCCR0B Registers 

The meaning of the TCCR0A & TCCR0B register bits are shown in Figure 2. You turn on the bits required in these registers to get a certain behaviour. To work out what does what, have a look at Figure 3.

Figure 3. Explanation of Register Bits

We want CTC mode 2. So the Waveform Generator Mode (WGM01) bit needs to be 1. That is:

TCCR0A = 0b00000010;

another way to write this is:

TCCR0A = (1 << WGM01);

C2:: The Timer/Counter can be clocked internally, via the pre-scaler, or by an external clock source on the T0 pin. We will use the pre-scaler set to 256. The clock source is selected by the Clock Select logic which is controlled by the Clock Select (CS) bits located in the Timer/Counter Control Register (TCCR0B). For TCCR0B to get a pre-scaler of 256, CS02 needs to be 1 (see Figure 3).

TCCR0B = 0b00000100;

or

TCCR0B = (1 << CS02);

C3:: Next we set the Output Compare Register. The number of ticks for a delay of 4ms is 250, so let's run with that.

OCR0A = 250;

C4:: When the timer/counter reaches the OCR0A number, an interrupt will be triggered by setting the OCIE1A flag in TIMSK1. We can do that by:

TIMSK0 = 0b00000010;

or

TIMSK1 = (1 << OCIE1A);

The specific interrupt vector that will be called for this CTC event is:

ISR(TIMER0_COMPA_vect)

As an aside, a list of the available AVR interrupt vectors can be found at: http://ee-classes.usc.edu/ee459/library/documents/avr_intr_vectors/

Figure 4. Port B Registers

C5:: I used digital output D13 since it is attached to the onboard LED and saves me wiring one up, but obviously you can use any output pin. Here we are using the Data Direction Register (DDR) to set D13 as an output (see Figure 4).

DDRB = 0b00100000;

C6:: We need to set the global interrupt flag to enable interrupts:

sei();

C7:: Finally, we need the Interrupt Service Routine which is called when an interrupt occurs. All we do here is toggle D13 which turns the LED on and off (very quickly)! With a LED toggling every 4ms, it just looks on all the time albeit a bit dimmer. We are effectively using PWM to dim the LED, but we want to be able to see the blinks so we use the extraTime variable to slow things down.

Saturday, April 8, 2017

STEMTera (Arduino Breadboard) Tutorial

What is the STEMTera?



STEMTera was the first project that I have supported on KickStarter and the experience has been overwhelmingly positive. So what is STEMTera?

At its simplest the STEMTera is a breadboard with an embedded Arduino UNO. Most shields will plug straight in. But it is more than just a simple Arduino prototyping platform, it also includes:
  • a LEGO® compatible bottom which allows you to mount it directly on your LEGO creation.
  • An ATmega32U2 microprocessor which is exposed, users can develop native USB projects with an extra 21 IO pins. These extra IO pins can work directly with the LUFA framework. More on this below.
  • Multiple IDE support including Atmel® Studio, Arduino IDE, AVR-GCC, AVR-GCC with LUFA, Scratch, etc.
  • Embedded LED's to indicate Power on, Tx, Rx and and one connected to D13 for your own use.
The Arduino functionality is the same as for an UNO, plug the USB port into your computer and away you go. The ATmega32U2 functionality is new and deserves a bit more explanation.

ATmega32U2


The newer Arduino Uno boards have two programmable microcontrollers: one is ATmega328, which is the Arduino processor that you usually upload your sketches to, and the second is the ATmega16U2, which is flashed to operate as a USB to Serial converter.

The ATmega16U2 chip on the Arduino board acts as a bridge between the computer's USB port and the main processor's serial port. Previous versions of the Uno and Mega2560 had an Atmega8U2. It runs firmware that can be updated through a special USB protocol called DFU (Device Firmware Update).

As part of the STEMTera KickStarter campaign there was a stretch target which if met would result in the ATmega16U2 being upgraded to the ATmega32U2. This target was met and so the upgrade was incorporated into the finished product. Even better, the ATmega32U2 pins have been brought out to the breadboard so that you can utilise them.

By updating the ATmega32U2 firmware, your STEMTera can appear as a different USB device (MIDI controller, HID, etc.).

DFU Programmers




To update the firmware on the STEMTera ATmega32U2 you will need a DFU Programmer.

Windows: Download Atmel's flip programmer.

Mac: Install MacPorts: Once MacPorts is installed, in a Terminal window, type

sudo port install dfu-programmer
NB: If you've never used sudo before, it will ask for your password. Use the password you login to your Mac with. sudo allows you to run commands as the administrator of the computer

Linux: from a command line type

sudo apt-get install dfu-programmer

Enter DFU mode


To enter program (DFU) mode you need to short the ATmega32U2 ICSP reset pin to ground until the red LED starts to flash.

Flash the chip


Windows: use flip to upload the hex file to your board

Mac & Linux: from a terminal window, change directories to get into the folder with the firmware. If you saved the firmware in your downloads folder on OSX, then you might type:

cd Downloads/
Once there, type:

sudo dfu-programmer atmega32u2 erase
When this command is done and you get a command prompt again, say you want to reflash the original Arduino firmware (Arduino-usbserial-uno.hex), then you would type:

sudo dfu-programmer atmega32u2 flash Arduino-usbserial-uno.hex
Finally:

sudo dfu-programmer atmega32u2 reset