From ae998b07dd6ef535815a9d294fa3fe1cf324fa62 Mon Sep 17 00:00:00 2001 From: Jérémy Dufour Date: Fri, 4 Jan 2008 22:46:59 +0100 Subject: r75@Gally: djerem | 2008-01-04 22:45:34 +0100 * digital/avr - add training documentation (translation of the previous one from french to english). --- digital/avr/doc/training/avr_architecture.dia | Bin 0 -> 1830 bytes digital/avr/doc/training/training.txt | 342 ++++++++++++++++++++++++++ 2 files changed, 342 insertions(+) create mode 100644 digital/avr/doc/training/avr_architecture.dia create mode 100644 digital/avr/doc/training/training.txt (limited to 'digital/avr') diff --git a/digital/avr/doc/training/avr_architecture.dia b/digital/avr/doc/training/avr_architecture.dia new file mode 100644 index 00000000..ea02ff51 Binary files /dev/null and b/digital/avr/doc/training/avr_architecture.dia differ diff --git a/digital/avr/doc/training/training.txt b/digital/avr/doc/training/training.txt new file mode 100644 index 00000000..67aec433 --- /dev/null +++ b/digital/avr/doc/training/training.txt @@ -0,0 +1,342 @@ +============== +AVR Training +============== +:Author: djerem + +.. contents:: Table of Contents + + +Introduction +============ + +AVR chips are quite like PC but smaller. They have many advantages: + + simple + you just need to wire them and they work out of the box; no need to add + more components. You just need to program them to control their + input-output; + + open + they are compatible with open-source softwares; + + interface + we can made them work with tons of components. + +.. figure:: avr_architecture.png + :align: center + :alt: AVR architecture diagram + + Structural AVR diagram. + +AVR are powered with 5V. + +Two input pins of the AVR can be used to make it work with an external clock, +generally generated by a quartz. This way, you can increase both its speed and +accuracy. + +The communication between the AVR and the PC can be done with the serial port. + +**Be careful**, you need to convert the -12/+12V of the PC to the 0/5V of the AVR +(you can use a MAX232 component to achieve this). + + +Input and output +================ + +Input and output are regrouped by port, each one composed of 8 pins. Ports +management are thus done by 8 bits words. + +Each port disposes of 3 registers: each register have 8 bits and each bits +are mapped to a pin of the port. + +Here is a description of the 3 registers of each port: + + ``PIN`` + it is a *read* register, reflecting the current state of the port. It is + thus used to read the input and output state of the port. Of course, you + can only read it and never write to it; + + ``DDR`` + it used to to select the port *direction*: + + * input mode: it is set to ``0``. This is the default case; + + * output mode: it is set to ``1``. + + ``PORT`` + it has got two functionalities: + + * if we are in input mode, it can be used to enable a *pull-up* + mechanism; + + * if we are in output mode, it can be used to define the *state* of the + pin (higher or lower state). + +Here is a summary of the use of the ``PORT`` register: + ++---------+----------+------------------+ +| ``DDR`` | ``PORT`` | Result | ++=========+==========+==================+ +| 0 | 0 | No pull-up, | +| | | High impedance | ++---------+----------+------------------+ +| 0 | 1 | pull-up in use | ++---------+----------+------------------+ +| 1 | 0 | output state = 0 | ++---------+----------+------------------+ +| 1 | 1 | output state = 1 | ++---------+----------+------------------+ + + +Example of port A use +********************* + +With one led +~~~~~~~~~~~~ +A led is connected to the first pin of the A register (we called this pin +*A0*). We would like to make the led blinked. + +Here is the algorithm you should used:: + + // enable output mode for the pin A0 + DDRA = 1 + + // infinite loop + while (1) + { + + // Switch on the led by putting the A0 pin in higher state + PORTA = 1 + + // Wait a few moment (to be sure we have seen the led on) + Delay (tps) // The delay function already exist on the APBteam + // repository + + // Swith off the led by puttin the A0 pin in lower state + PORTA = 0 + + // Wait again + Delay (tps) + } + +Remember to protect your led with a resistor. + + +With two led +~~~~~~~~~~~~ + +Now, we would like to add a second led, connected to the pin *A3* and that +will light on when the first one is switched off and vice-versa. + +By using our previous algorithm, we just need to change the following code:: + + // We would like to put a 1 (high state) on the third bit + // So 2³ = 8 + DDRA = 1 -> DDRA = 8 + PORTA = 1 -> PORTA = 0 + PORTA = 0 -> PORTA = 8 + +The problem with this algorithm is that we will also change the other bits of +the ``PORTA``. For example, setting ``PORTA`` to 8 (00001000 in binary) will +make us loose the first bit we have previously set to 1. Consequence, we will +never switch on the first led (connected to the *A0* pin). Not really +useful... + +To prevent the change of the bits of the other pins of the port, we need to +use some logical function: + + to put a bit to 1 + you need to use a logical *or*. Here is a sample algorithm to change from + 1 to 0 the third bit of the ``PORTA`` register:: + + // ~8 correspond to the opposite of 8. In binary, it means the opposite + // of 00001000, that is to say 11110111. Only the third bit is set to 0 + // because it is the one we would like to change. + PORTA &= ~8 + + to put a bit to 0 + you need to use a logical *and* between the ``PIN`` register and an 8 bits + word with all bits set to 1 expect the bit you want to change. Here is a + sample algorithm to change the change from 0 to 1 the third bit of the + ``PORTA`` register:: + + PORTA |= 8 + +In fact, there is a macro ``BV_`` (defined in ``common/io.h``) which lets you +directly work with the desired bit of a byte. If we use this macro, the +previous code will become:: + + // 1 << 3 = 8 + PORTA &= ~_BV(3) + PORTA |= _BV(3) + +You can also work with multiple bits at the same time. For example, if you +want to change both second and third bit of the ``PORTA`` register to 1, you +can do the following:: + + // 2³ + 2² = 12 + PORTA |= 12 + // You can also use the BV_ macro: + PORTA |= _BV(2) + _BV(3) + +In fact, you should try to use the ``BV_`` macro as much as possible: it +usually make the code easier to read and understand. + + +Many devices ready to use in the AVR +==================================== + +AVR chip contains some ready to use devices. For example: + + * an analog/digital converter: it uses a specific register; + + * a serial port: it uses configuration, reception and emission registers; + + * an I2C/TWI port; + + * a watchdog timer to make the AVR restart when it crashes; + + * PWM; + + * ... + + +Polling mode versus interrupts +================================= + +Polling mode +************ + +The polling mode corresponds to the action of regularly check something to see +if there is change and take actions according to. For example, with the serial +port, you need to do something like:: + + If there is a bit arrived on the serial port? + If no: + Go on with the main program; + If yes: + I manage it now; + +We need to do this algorithm between each program instruction to be able to +manage data as they arrive. Expect the complexity of doing this every time, it +decrease the performance by losing time for the verification of data on the +serial port. + +To solve this issue, we can use interrupts. + + +Interruptions +************* + +Some pins of the AVR on specific ports can trigger some interrupts. For +example, when there is a logical state change on a pin, an interrupt is +triggered. It can be handle or not, depending on its level. + +Let's take our previous example with the serial port in polling mode and adapt +it for interrupts:: + + I am currently executing the instruction of my program, normally; + Coming from nowhere without a warning, an interrupt is triggered because a + has arrived on the serial port; + My program is stopped and sent to the handler of this interrupt: + I get the data received on the serial port and manage it; + When my interrupt handler is finished, I am going back to the place where I + have been stopped in my program; + +Interrupts are managed in a linear way: when two interrupts are triggered at +the same time or within a little time, there is no way to predict which one +has come first. + +Things to keep in mind for interrupts: + + volatile variables + they force the compiler to never optimize their access. This way, the AVR + need to get the value where it is stored and never caches it. + You need to use them every time you have a variable that it is used in the + interrupt handlers and in other functions of the program. It ensures you + the value you are working is the actual one, anywhere in your program; + + enable interrupts + in order to enable interrupts, you must use the function ``sei ()`` in + your code; + + disable interrupts + in order to disable interrupts, you must use the function ``cli ()`` in + your code; + + +.. I do not understand this part: + * Interrupteur en entrée + Il est possible de mettre un interrupteur en entrée sur les AVR. Mais lorsque + l'interrupteur est ouvert, il faut que la patte soit branchée. Elle ne peut + rester dans le vide. Pour cela, il suffit d'activer le mode ''pull-up'' de la + patte correspondante. Attention au rebond ! + + +AVR at APBTeam +============== + +AVR used +******** + +We use two kind of AVR, from Atmel: ATmega64 and ATmega128. The difference +between the tow is, expect the price, the size of the memory flash to store +the program (64k and 128k). + + +AVR code +******** + +I can only advise you to have a look at the code in the SVN repository, in the +directory `trunk/digital/avr +`_. You can find here some +documentations (this one for example), the code of the program of the +different card (IO, Asserv), a simulator to make the code work on PC and even +some examples. + +Repository organisation +~~~~~~~~~~~~~~~~~~~~~~~ +The directory `trunk/digital/avr +`_ of the repository is organised in the +following way:: + + |-- common + | >>> Some general defines to include in programs + |-- doc + | >>> Some documentations + |-- make + | >>> Makefile used for the build + `-- modules + | >>> Many modules ready to use + |-- adc + | >>> Analogic to digital convertion + |-- host + | >>> AVR simulator for PC + |-- math + | >>> floating point computatin, random number generation + |-- proto + | >>> Serial protocol management + |-- twi + | >>> I2C bus management + |-- uart + | >>> Serial bus management + `-- utils + >>> Some useful functions, like reset, delay, ... + +To create a project, have a look at the `build.txt +`_ document. + + +Resources +========= + + * Datasheets of the AVR component (available on the Atmel website); + * Documentation on the AVR libc: + http://www.nongnu.org/avr-libc/user-manual/index.html; + * `AVRFreaks `_ with many things on everything; + + +Acknowledgment +============== + +Thanks to Ni for taking the time to give us this training while he was ill! -- cgit v1.2.3