Sunteți pe pagina 1din 5

Atmel AT90USB12xx PWM and Input Capture Tutorial

(Written by Scott Miller, v0.1, September 23, 2006)

Table of Contents
1.0 Introduction............................................................................................................. 1
2.0 Hardware Interfacing to an I/O Port ....................................................................... 1
3.0 Introduction to PWM with the AT90USB12xx ...................................................... 2
4.0 Introduction to Input Capture with the AT90USB12xx ......................................... 3
5.0 Hints on Using the Sonar and Thinking of Design ................................................. 4

1.0 Introduction
The purpose of this document is to provide some direction on using advanced I/O
features such that you should be able to use any I/O features you require with the help of
the Hardware Manual upon completion. This document will focus on Pulse Width
Modulation (PWM) and Input Capture features, as well as an introduction to interrupts
and hardware interfacing with the AT90USB’s I/O ports.

2.0 Hardware Interfacing to an I/O Port


The AT90USB has 6 ports (A-F) available for use. They each have 10 pins, 8 of which
are for I/O, one (1) for VDD, and one (1) for ground. Each port is configured like the
following:

Figure 1: Port Pin Configuration

The order of ports on the AT90USB is a little counter intuitive. The following diagram
shows the order of ports on the device:
Figure 2: Port Locations on the AT90USB

As for using the ports, experimentation has proven that these ports will only work when
their power and ground pins are connected in some fashion to the devices they are driving.
When attempting to use the L293D H-Bridge (see the Hardware Interfacing Primer) DC
motor circuit, the AT90USB’s PWM output wasn’t working (nor were any of the ports
for that matter). Once the VDD and ground from PORTB were used to drive the external
circuitry (except for the motor) the circuit worked fine. In short, to properly use each I/O
port the VDD and ground must be somehow connected to the external devices. I speculate
this is for power saving functions, as well as to protect the port when the processor
decides there is nothing attached.

Since then, Input Capture and PWM have been tested and work just fine on the
AT90USB demo board.

3.0 Introduction to PWM with the AT90USB12xx


The AT90USB has 6 output ports for PWM (2 per timer) and many modes these can use
for different kinds of PWM (different maximum bits used, inverting or non-inverting,
symmetrical waveforms or not, etc.). We will be using asymmetrical (fast) PWM in the
non-inverting mode for controlling these DC motors. Selecting these alternate functions
can be done for any I/O port by setting certain bits in certain registers. The Hardware
Manual describes all of these registers in detail for each desired function.

Dr. Cheng has posted notes on his Wiki giving suggestions on how to start getting PWM
going. This is an excellent resource as it suggests different registers to become aware of
and quick calculations to determine you the speed and resolution of your PWM output.

Using TIMER0 included in the AT90USB (8-bit timer), the following example code
should give you a hand with how to get the timer working and select your duty cycle for
your pulse width modulation. If you want to use the timer, but not use pulse width
modulation (for example, for simply polling for a count and, say, cycling the onboard
LEDs, simply change the COM0A and COM0B registers to ‘0’ instead of ‘1’. For
TIMER0, PORTB7 is the OCRA (first PWM) output.

Please refer to the Hardware Manual for more information.


PWM_Timer.c

#include <avr/io.h>

int main (int argv, char *argc[])


{
/******************************************************
* Begin initializing PWM on Timer0 *
******************************************************/

DDRB = 0x80; //Set Timer0A PWM output as an output


DDRD = 0x01; //Set Timer0B PWM output as an output
TCCR0A = (_BV(WGM00)) | (_BV(WGM01)) | (_BV(COM0A1))
| (_BV(COM0B1)); //Set the Timer0 to PWM Fast Mode
//Set the Timer0 for non-inverting mode
TCCR0B = (_BV(CS00)); //Set the Timer on with no prescaler
OCR0A = 0x0f; //Register for determining how long
the duty cycle will be

/*********************************************************
* End initialization of Timer0 for PWM. Timer is now *
* running and PWM is working. To change the speed of the *
* motor, change the value of the OCR0A or OCR0B *
* registers
*
*********************************************************/
for (;;)
{
// Used for testing (keep the program running)
}

return 0;
}

4.0 Introduction to Input Capture with the


AT90USB12xx
To interface with the provided SRF04 sonar unit, any pins can be used on any port as
digital I/O. Any output pin can be selected as an output to send a “start pulse” to the
sonar device. Using polling, any pin could also be used as input from the sonar unit to
receive the distance pulse and the clock cycles can be counted to find the pulse width. I
won’t provide code for this as it uses simple I/O only.

As a more useful input method, we can use the input capture function of one of either
TIMER1 or TIMER3. These pins can be set to sense either a positive or negative edge of
a signal. When the desired edge is detected, a register ICRx (16-bit) saves the count of
the timer at the moment the edge was detected. Additionally, an interrupt can be raised to
signal the processor when the pulse edge has been detected. Sample code using this
technique is listed below.
IPC_LED.c

#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>

int main(int argc, char *argv[])


{
DDRD = 0xef; //Set the Input Capture for Timer1 to input PORTD4
DDRD = 0x00;
TIMSK1 = (_BV(ICIE1)); //Enable ICP1 interrupts

TCCR1B = (_BV(ICNC1)) | (_BV(ICES1)) | (_BV(CS10));


//Enable the noise canceller and set the Edge Trigger
//to trigger on a positive event. Set the clock to Fclk

sei(); //enable interrupts

for(;;)
{
//run program forever
}

return 0;
}

ISR (TIMER1_CAPT_vect)
{
PORTD ^= _BV(PORTD7) ^ _BV(PORTD6) ^_BV(PORTD5);
//PORTD4 is the ICP
}

To test this code on your boards, take the ground and VDD leads from PORTA (the ones
with wires soldered in them); we will use them to simulate positive and negative clock
edges on the Input Capture Pin 1 ICP1 (PORTD4). Run and execute the code supplied.
Touch the ground lead from PORTA (PORTA1) to pin PORTD4. Now remove the
ground and touch the VDD lead to this pin (PORTA0). Three (3) LEDs should cycle on. If
you repeat this process (touch the ground and then VDD leads to this port) the LEDs
should cycle off. This is a simple ICP/Interrupt driven code sample.

5.0 Hints on Using the Sonar and Thinking of Design


The above code and suggestions should be enough to get your all started with the PWM
and the IPC design for the DC motor and sonar, respectively. With the basics down, keep
in mind the specs you are working with for each. The motor will have to be tested with
the sonar in order to find what pulse width will keep your blimp at your desired height.
With regards to the sonar, you will have to ensure your pulses and timing match the
following specifications:
Figure 3: SRF04 Timing Specifications

As for the input capture algorithm needed to accurately time the width (period) of the
echo pulse, I have prepared code for this. As you should think about this for the lab
yourselves, I will supply it later in the week if need be. For now, however, the ISR
routine I have used has the following algorithm:

/******************************************************
* Pulse Detection Algorithm *
*******************************************************
* Detect +ve edge *
* ISR: if Edge Detector = +VE: set to -ve, reset clock*
* Detect -ve edge *
* ISR: if Edge Detector = -VE: set to +ve, get ICR1H/L*
* (length of pulse) *
******************************************************/

Keep in mind with these timing specifications what period you can cover with a clock set
to Fosc (no prescaler). This sonar will time out at 36ms if no signal is receive (out of
range of echo). At 8MHz, a 16bit counter can time up to 8ms maximum.

With this code and the use of the Hardware Manual, you should all be set to finish this
lab. Code can be provided near the deadline if need be (but keep in mind, it will not be
complete so do not count on the code).

Good luck!

S-ar putea să vă placă și