Cet article est une ébauche à compléter, vous pouvez partager vos connaissances en le modifiant.
====== AVR ======
Les AVR (**A**dvanced **V**irtual **R**ISC ) d’[[Atmel]] sont de la famille des [[microcontrôleur|microcontrôleurs]] [[RISC]]. L’architecture a été conçue par deux étudiants de l’institut de technologie de Norvège (NTH : Norges Tekniske Høgskole).
Les AVR sont basés sur une architecture [[CPU]] [[Harvard]] modifiée. Ils disposent de 32 registres de travail de 8 bits.
Ils permettent d'approcher la vitesse d'une instruction par cycle d'horloge, soit par exemple près de 20 millions d'instructions par seconde avec une horloge à 20 MHz.
====== Gamme des microcontrôleurs ======
Les AVR sont divisés en familles ayant chacune ses spécificités.
* **tinyAVR** : Petit et pas cher
* **megaAVR** : Plus de périphériques, plus d'entrées sorties, plus d'options
* **XmegaAVR** : Nouvelle génération de microcontrôleur qui remplacera les megaAVR. Beaucoup plus de périphériques, consommation très réduite et nouvelles fonctionnalités (USB, cryptage, ADC 12bits etc ...)
===== Pourquoi choisir les AVR ? =====
* **La fréquence de fonctionnement :** A 16Mhz vous aurez ~16MIPS (**M**illions d'**I**nstructions **P**ar **S**econde), il n'y a pas de "micro-cycle" qui vous prédivise l'horloge. Exemple, certains micros fonctionnant à 20Mhz ont besoin de 4 "micro-cycles" pour exécuter un cycle réel. Ce qui ramène à 20/4=~5MIPS, soit, au moins, __3 fois plus lent__ qu'un AVR.\\
* **Simplicité d'utilisation des registres :** Les AVR ont 32 registres de travail. L'accès aux registres est direct, pas de bank ou de pages à présélectionner qui font augmenter le temps d'exécution, la taille et diminuer la lisibilité du code.\\
* **Instructions** : 130 Instructions ... de quoi faire un code compact\\
* **Oscillateur** : En plus des oscillateurs externes "standards" Quartz, RC etc, la série des ATmega intègre un oscillateur interne dont la fréquence est configurable entre 1 et 8 Mhz. Ce qui veut dire que votre micro est parfaitement opérationnel sans composant périphérique !\\
* **Ports** : Hormis le fait que chaque port peut être utilisé en entrée/sortie, chaque pin de chaque port possède une résistance de tirage activable ou non.\\
* **Interruptions** : Chaque interruption possède son propre vecteur d'interruption. Plus besoin de test pour savoir qui a déclenché quoi ...\\
* **Timer 8 et 16bits** : La prédivision sur tous les timers va jusqu'à 1024 donc vous avez la possibilité de faire des tempos longues sans rajouter de code supplémentaire. Vous avez un registre de comparaison sur tous les timers même le plus "petit."
Le reste je vous laisse le découvrir dans le tutorial qui suit ou dans le datasheet ;-)
===== Les ports d'entrée / sortie =====
**DDRx** : Registre qui impose **la direction** des ports.
ex: DDRA=0b11110000 ; les bits 0 à 3 du portA sont configurés en entrée et de 4 à 7 en sortie.
**PORTx** : Registre d'**écriture** des niveaux logiques sur le port x
ex: PORTA=0b11110000 ; Si le port est en sortie (voir DDRx), les bits 0 à 3 du portA passent à l’état bas et de 4 à 7 à l’état haut.
**PINx** : Registre de **lecture** des niveaux logiques sur le port x
==== Résistance de tirage ====
Chaque pin de chaque port possède une résistance de tirage activable en mettant la pin en question en entrée (Registre DDRx) et en mettant le niveau logique à 1 (PORTx)\\
ex : DDRA=0b10101010 et PORTA=0b11111111 ; Les résistances de tirage sont actives sur les pins 0,2,4,6 du port A. les autres pins sont en sortie et au niveau haut.
Le bit **PUD** (Pullup disable) du registre **SFIOR** permet de désactiver toutes les résistances de tirage sur tous les ports.
La résistance de tirage est comprise entre 20 et 50kΩ
==== Récapitulatif ====
^ DDRx ^ PORTx ^ Entrée/Sortie ^ Résistance de tirage ^ Description ^
| 0 | 0 | Entrée | Non | La pin est en entrée en haute impédance |
| 0 | 1 | Entrée | Oui | La pin est en entrée avec résistance de tirage |
| |||||
| 1 | 0 | Sortie | Non | La pin est en sortie et au niveau bas |
| 1 | 1 | Sortie | Non | La pin est en sortie et au niveau haut |
==== Lecture d'une pin ====
Entre la mise en entrée d'une pin et sa lecture il faut qu'au moins 1 cycle d'horloge s'écoule. Si vous souhaitez lire immédiatement la pin après l'avoir mise en entrée intercalez un nop entre la configuration de DDRx et la lecture de PINx. [[http://wiki.jelectronique.com/winavr/les_entrees_sorties|Voir l'exemple en C.]]
==== Pin non connecté ====
Il est recommandé d'activer la résistance interne, pour fixer un niveau logique à l’entrée, si elle n'est pas utilisée. Ca ne coûte rien et ça réduit la consommation. Ne la connectez pas à VCC ou GND en cas d'erreur de config vous risquez de court-circuiter la pin.
===== Interruptions externes =====
Les interruptions externes sont déclenchées sur un changement d’état des pins INT0, INT1 ou INT2.\\
Les interruptions peuvent être déclenchées sur un front descendant, montant ou un niveau bas. (INT2 ne peut être déclenchée que sur des fronts)
Le niveau apres un front doit être maintenu au moins pendant la durée d'un cycle d'horloge.
==== Configuration du déclenchement====
**MCUCR** :
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
^ SE ^ SM2 ^ SM1 ^ SM0 | ISC11 | ISC10 | ISC01 | ISC00 |
Bit 1 et 0 - ICS01 et ICS00 servent à configurer INT0.\\
Bit 3 et 2 - ICS11 et ICS10 servent à configurer INT1.
^ ISC11 ^ ISC10 ^ ^
^ ISC01 ^ ISC00 ^ Description ^
| 0 | 0 | Interruption sur niveau bas |
| 0 | 1 | Interruption sur front montant ET descendant |
| 1 | 0 | Interruption sur front descendant |
| 1 | 1 | Interruption sur front montant |
**MCUCSR** :
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
^ JTD | ISC2 ^ - ^ JTRF ^ WDRF ^ BORF ^ EXTRF ^ PORF ^
Bit 6 - ISC2
^ ISC2 ^ Description ^
| 0 | Interruption sur front descendant |
| 1 | Interruption sur front montant |
==== Choix de l'interruption ====
**GICR** :
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| INT1 | INT0 | INT2 ^ - ^ - ^ - ^ IVSEL ^ IVCE ^
L'interruption de INT1 est activée si INT1 (bit 7) est à 1\\
L'interruption de INT0 est activée si INT0 (bit 6) est à 1\\
L'interruption de INT2 est activée si INT2 (bit 5) est à 1\\
==== Interruption globale ====
L'interruption n'est activée que si le bit **I** (Interruption globale) du registre **SREG** est activé.\\
La moyen le plus simple de l'activer est d'utiliser la fonction **sei**
[[winavr:Interruption externe|Voir l'exemple en C : Utiliser les Interruptions externes]]
===== Timer =====
==== Introduction ====
Un timer est un compteur cadencé par une horloge.
L’horloge peut :
* être l’horloge système (quartz, oscillateur interne etc ...)
* être un signal arrivant sur une pin du [[microcontrôleur]].
* être divisée en fréquence
Le timer peut :
* déclencher une interruption arrivé à son maximum
* déclencher une interruption arrivé à une certaine valeur
* faire changer d’état une sortie du [[microcontrôleur]]
* être préchargé à une certaine valeur
Les applications possibles sont :
* la mesure de temps entre 2 évènements
* la génération de signaux, signal carré, PWM etc
* le déclenchement des évènements périodiques
==== Timer 0 (8 bit) ====
=== Source de l'horloge ===
Le timer peut être cadencé par un signal appliqué sur la pin T0 ou par l'horloge système.
----
=== T0 ===
Le signal appliqué sur T0 doit avoir une fréquence inférieure à la fréquence système / 2.5 et un rapport cyclique de 1/2.
== Configuration du déclenchement ==
**TCCR0** :
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| FOC0 | WGM00 | COM01 | COM00 | WGM01 | CS02 | CS01 | CS00 |
Bit 2,1 et 0 :
^ CS02 ^ CS01 ^ CS00 ^ Description ^
| 0 | 0 | 0 | Timer **désactivé** |
| 1 | 1 | 0 | Incrémentation du timer sur **front descendant** de T0 |
| 1 | 1 | 1 | Incrémentation du timer sur **front montant** de T0 |
----
=== Horloge système ===
L'horloge système (quartz, oscillateur RC interne etc) passe par un diviseur de fréquence appelé "prescaler". Ce prescaler permet de diviser la fréquence appliquée au compteur (timer) par 8,64,256 ou 1024.
== Diviseur de fréquence (Prescaler) ==
**TCCR0** :
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| FOC0 | WGM00 | COM01 | COM00 | WGM01 | CS02 | CS01 | CS00 |
Bit 2,1 et 0 :
^ CS02 ^ CS01 ^ CS00 ^ Description ^
| 0 | 0 | 0 | Timer **désactivé** |
| 0 | 0 | 1 | Fréquence système |
| 0 | 1 | 0 | Fréquence système/**8** |
| 0 | 1 | 1 | Fréquence système/**64** |
| 1 | 0 | 0 | Fréquence système/**256** |
| 1 | 0 | 1 | Fréquence système/**1024** |
----
=== Mode de fonctionnement ===
== Normal ==
Le compteur va s'incrémenter jusqu'à sa valeur max, soit en 8 bit 0xFF.\\ Arrivé à 0xFF, il recommencera à partir de 0x00 jusqu'à 0xFF et ainsi de suite.
**TCCR0** :
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| FOC0 | WGM00 | COM01 | COM00 | WGM01 | CS02 | CS01 | CS00 |
^ WGM01 ^ WGM00 ^ Description ^
| 0 | 0 | Timer en mode normal |
== CTC (Clear time on compare match) ==
Le compteur va s'incrémenter jusqu'à la valeur du registre OCR0.\\ Arrivé à la valeur de OCR0, il recommencera à partir de 0x00 jusqu'à la valeur de OCR0 et ainsi de suite. OCR0 définit donc la valeur max du compteur. OCR0 doit être inférieur à 0xFF.
{{:avr:timer_ctc.jpg|:avr:timer_ctc.jpg}}
**TCCR0** :
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| FOC0 | WGM00 | COM01 | COM00 | WGM01 | CS02 | CS01 | CS00 |
^ WGM01 ^ WGM00 ^ Description ^
| 1 | 0 | Timer en mode CTC |
== Fast PWM ==
FIXME
{{:avr:timer_fast_pwm.jpg|:avr:timer_fast_pwm.jpg}}
**TCCR0** :
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| FOC0 | WGM00 | COM01 | COM00 | WGM01 | CS02 | CS01 | CS00 |
^ WGM01 ^ WGM00 ^ Description ^
| 1 | 1 | Timer en mode Fast PWM |
== Phase Correct PWM ==
FIXME
{{:avr:timer_phase_correct_pwm.jpg|:avr:timer_phase_correct_pwm.jpg}}
**TCCR0** :
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| FOC0 | WGM00 | COM01 | COM00 | WGM01 | CS02 | CS01 | CS00 |
^ WGM01 ^ WGM00 ^ Description ^
| 0 | 1 | Timer en mode Phase Correct PWM |
----
=== Interruption ===
FIXME
----
=== Sortie OC0 ===
FIXME
===== USART =====
USART : **U**niversal **S**ynchronous and **A**synchronous serial **R**eceiver and **T**ransmitter, liaison série synchrone et asynchrone.
Vous verrez souvent parlez d'UART plutôt que d'USART, sachez que l'USART imbrique toutes les fonctionnalités de l'UART.
===== TWI (I2C) =====
FIXME
===== Comparateur analogique =====
FIXME
===== CAN =====
FIXME
===== Programmateur / Debuggage =====
Il existe plusieurs méthodes de programmation :
==== Programmation ISP (In System Programming)====
C'est la méthode de programmation la plus courante et la plus simple. Vous pouvez réaliser un programmateur pour quelques euros. \\
Cette méthode de programmation permet de programmer directement un microcontrôleur dans son système; càd qu'il n'est pas nécessaire de déconnecter le micro de son système pour le reprogrammer.
Programmateurs supportant ce mode de programmation : STK500, [[:projets:dongle_avr_2:dongle_avr_2|Dongle AVR ISP 2]]
==== Programmation - Debuggage JTAG (Joint Test Action Group) ====
Le JTAG n'est pas vraiment un programmateur mais plutôt un système de debuggage. Il permet de voir l'évolution de votre micro (registres, mémoire etc) et d'influer sur eux en temps réel et en fonction de l'exécution de votre programme. Le debuggage permet les mêmes méthodes d'exécution qu'en simulation : pas à pas, point d'arrêt etc
Programmateurs supportant ce mode de programmation : JTAGICE, [[http://www.jelectronique.com/JTAG.php|Programmateur JTAG clone]] --> **Lien rompu !** :-\
==== Programmation Bootloader ====
Le bootloader est un petit programme, programmé dans votre [[microcontrôleur]], capable d'écrire dans la mémoire flash un programme provenant d’une source externe comme l'UART (Généralement connecté au port série d’un ordinateur).
Ce mode de programmation est surtout utilisé pour les [[microcontrôleur|microcontrôleurs]] ne supportant pas le programmation in situ (dans le système), ce qui ne pas le cas des [[AVR]]. Donc à part pour une application bien spécifique, il n’y a pas d’intérêt à l’utiliser. (Ou on peut l'utiliser pour faire des mise à jour firmware via une interface USB ou série ce qui évite de devoir ouvrir l'apareil et donc ainsi le client fait sa mise à jour.)
Programmateurs supportant ce mode de programmation : Il faut juste programmer le bootloader avec un programmateur quelconque. Ensuite plus aucun programmateur n'est plus nécessaire.
==== Programmation Haute tension ====
La programmation haute tension (12V) est rarement utilisées vu qu’elle ne permet pas la programmation in situ, par contre elle permet de reprogrammer un micro dont les fuses bits ont été mal programmé et qui entraîne un disfonctionnement de la programmation ISP.
Programmateur supportant ce mode de programmation : STK500
==== Pour la programmation des ATmega 128, 64 et 103 ====
Les ATmega128,64 et 103 n'utilisent pas les pattes MISO et MOSI pour la programmation ISP mais les pattes RXD0 et TXD0. \\
Une solution pour utiliser l'UART0 et la programmation est d'utiliser un montage de ce type :\\
[[http://www.embedit.de/phpkit/include.php?path=content/articles.php&contentid=76]] --> **Lien rompu !** :-\
* Mode programmation
Lors de la programmation la patte RESET est forcée à 0, la patte /SHDN passe aussi 0 et force les sorties du MAX3222 à passer en haute impédance.\\
La programmation peut se faire sans aucun risque de court circuit.
* Mode UART0
RESET n'étant pas forcée à 0, RESET passe à VCC par l'intermédiaire de R2. Le MAX3232 est activé.
Sinon vous pouvez aussi utiliser un simple multiplexeur.
===== Brochage =====
==== DIP des AVR les plus utilisés ====
|{{:avr:atmega8_dil.jpg|:avr:atmega8_dil.jpg}}|{{:avr:atmega16_dil.jpg|:avr:atmega16_dil.jpg}}|
^ ATmega 8 ^ ATmega 16 ^
|{{:avr:atmega32_dil.gif|:avr:atmega32_dil.gif}}|{{:avr:atmega8535_dil.jpg|:avr:atmega8535_dil.jpg}}|
^ ATmega 32 ^ ATmega 8535 ^
===== Liens externes =====
* [[http://www.atmel.com/products/avr/|Site officiel]]
* [[http://www.atmel.com/dyn/products/app_notes.asp?family_id=607|Notes d'applications]]
*[[http://www.silicium628.fr/electron/atmega/atmega.htm | Des conseils pour débuter avec les ATmega ]]