|author||Jérémy Dufour||2008-01-04 22:46:59 +0100|
|committer||Jérémy Dufour||2008-01-04 22:46:59 +0100|
r75@Gally: djerem | 2008-01-04 22:45:34 +0100
* digital/avr - add training documentation (translation of the previous one from french to english).
Diffstat (limited to 'digital/avr/doc')
|-rw-r--r--||digital/avr/doc/training/avr_architecture.dia||bin||0 -> 1830 bytes|
2 files changed, 342 insertions, 0 deletions
diff --git a/digital/avr/doc/training/avr_architecture.dia b/digital/avr/doc/training/avr_architecture.diaBinary files differ
new file mode 100644
diff --git a/digital/avr/doc/training/training.txt b/digital/avr/doc/training/training.txt
new file mode 100644
@@ -0,0 +1,342 @@
+.. contents:: Table of Contents
+AVR chips are quite like PC but smaller. They have many advantages:
+ 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
+ they are compatible with open-source softwares;
+ 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
+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:
+ 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;
+ 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``.
+ it has got two functionalities:
+ * if we are in input mode, it can be used to enable a *pull-up*
+ * 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
+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
+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
+To solve this issue, we can use interrupts.
+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
+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).
+I can only advise you to have a look at the code in the SVN repository, in the
+<https://apbteam.org/browser/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
+The directory `trunk/digital/avr
+<https://apbteam.org/browser/trunk/digital/avr>`_ of the repository is organised in the
+ |-- 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
+ * Datasheets of the AVR component (available on the Atmel website);
+ * Documentation on the AVR libc:
+ * `AVRFreaks <http://www.avrfreaks.net/>`_ with many things on everything;
+Thanks to Ni for taking the time to give us this training while he was ill!