• Aucun résultat trouvé

[PDF] Tutoriel carte Arduino Due pdf enjeux et pratique | Cours Arduino

N/A
N/A
Protected

Academic year: 2021

Partager "[PDF] Tutoriel carte Arduino Due pdf enjeux et pratique | Cours Arduino"

Copied!
32
0
0

Texte intégral

(1)

Programmation des périphériques

du microcontrôleur

SAM3X8E

(2)
(3)
(4)

SOMMAIRE

1

Syntaxe du C pour microcontrôleur... 2

1.1 Types spéciaux... 2

1.2 Structure de programme... 2

1.3 Constantes prédéfinies ... 2

2

Initialisations générales... 3

2.1 Démarrage de la carte ... 3

2.2 Initialisation des entrées/sorties console ... 3

2.3 Exemple ... 3

3

Allumage/Extinction des contrôleurs de périphériques ... 3

3.1 Allumer un contrôleur de périphérique... 3

3.2 Éteindre un contrôleur de périphérique... 4

4

Lignes d'entrées / sorties numériques... 4

4.1 Utilisation de lignes en sortie numérique... 4

4.1.1 Initialisation d’une ligne en sortie numérique ... 4

4.1.2 Modification de l’état d’une ligne en sortie numérique... 4

4.1.3 Exemple ... 5

4.2 Utilisation de lignes en entrée numérique... 5

4.2.1 Initialisation d’une ligne en entrée numérique ... 5

4.2.2 Consultation de l’état d’une ligne en entrée numérique ... 5

4.2.3 Exemple ... 5

4.2.4 Mise en place d’un filtrage sur les lignes en entrée numérique... 5

4.2.5 Exemple ... 6

4.2.6 Association de fonctions d’interruption à des lignes en entrée numérique ... 7

4.2.7 Suppression d’une fonction d’interruption associée à une ligne en entrée numérique... 7

4.2.8 Exemple ... 7

5

Timers ... 8

5.1 Principe de fonctionnement d’un Timer ... 8

5.1.1 Délais ou durées maximales ... 8

5.1.2 Calculs ... 8

5.2 Mise en marche d’un Timer ... 9

5.3 Timer en génération de délai... 9

5.3.1 Initialisation d’un Timer pour générer un délai ... 9

5.3.2 Savoir si le délai est terminé... 9

5.3.3 Exemple ... 9

5.4 Timer en mesure de durée... 10

5.4.1 Lignes numériques associées aux mesures de durée par Timer... 10

5.4.2 Initialisation d’un Timer pour mesurer une durée ... 10

5.4.3 Savoir si la mesure de durée est terminée... 11

5.4.4 Récupération de la durée mesurée ... 11

5.4.5 Exemple ... 11

5.5 Timer en déclenchement du convertisseur Analogique/Numérique ... 11

5.5.1 Initialisation d’un Timer pour déclencher le convertisseur Analogique/Numérique... 12

5.5.2 Exemple ... 12

5.6 Démarrage et arrêt d’un Timer... 12

5.7 Remise à zéro d’un Timer par une ligne d’entrée numérique... 13

5.7.1 Lignes numériques associées à la remise à zéro de Timer ... 13

5.7.2 Initialisation de la remise à zéro d’un Timer par ligne numérique... 13

5.7.3 Arrêt de la remise à zéro d’un Timer par ligne numérique... 13

5.7.4 Exemple ... 14

5.7.5 Savoir un Timer a été remis à zéro par sa ligne numérique... 14

(5)

5.10.1 Associer une fonction à un événement de Timer ... 15

5.10.2 Supprimer la fonction associée à un événement de Timer ... 15

5.10.3 Exemple... 15

6

Lignes d'entrées analogiques... 15

6.1 Lignes physiques... 16

6.2 Mise en marche et initialisation du convertisseur analogique/numérique ... 16

6.3 Déclenchement du convertisseur analogique/numérique... 16

6.4 Acquisition de données sur une ligne analogique ... 17

6.4.1 Choix de l’entrée ... 17

6.4.2 Mise en place d’une amplification sur une entrée analogique... 17

6.4.3 Test de fin de conversion... 17

6.4.4 Récupération de la valeur mesurée ... 18

6.4.5 Exemple ... 18

6.5 Mise en place de seuils sur une entrée analogique... 18

6.5.1 Choix de l’entrée ... 18

6.5.2 Amplification en entrée ... 18

6.5.3 Mise en place de conditions de seuils... 19

6.5.4 Test de condition sur les seuils ... 19

6.5.5 Récupération de la valeur mesurée ... 19

6.5.6 Exemple ... 19

6.6 Acquisition de données sur plusieurs lignes analogiques ... 19

6.6.1 Définition d’une liste d’entrées ... 20

6.6.2 Test de fin de conversion d’une liste d’entrées... 20

6.6.3 Récupération des valeurs mesurées ... 20

6.6.4 Exemple ... 20

6.7 Association de fonctions d’interruption au convertisseur analogique/numérique ... 21

6.7.1 Associer une fonction à un événement du convertisseur A/N ... 21

6.7.2 Supprimer la fonction associée à un événement du convertisseur A/N... 21

6.7.3 Exemple ... 21

7

Générateurs de signaux... 22

7.1 Principes de fonctionnement des générateurs de signaux ... 22

7.1.1 Précision et période ... 22

7.1.2 Calculs ... 23

7.2 Lignes physiques liées aux générateurs de signaux ... 23

7.3 Préparation d’un générateur de signal... 24

7.3.1 Mise en marche et initialisation d’un générateur de signal ... 24

7.3.2 Association de la ligne physique à une sortie de signal... 24

7.3.3 Exemple ... 24

7.4 Consultation de l’état d’un générateur de signal... 25

7.5 Modification du fonctionnement d’un générateur de signal ... 25

7.6 Horloges personnalisées... 25

7.6.1 Définition d’une horloge personnalisée... 25

7.6.2 Exemple ... 26

7.7 Association de fonctions d’interruption aux générateurs... 26

7.7.1 Associer une fonction à chaque fin de période d’un générateur... 26

7.7.2 Supprimer la fonction associée aux fins de périodes d’un générateur... 26

7.7.3 Exemple ... 27

8

Lignes de sorties analogiques ... 27

8.1 Lignes physiques... 27

8.2 Mise en marche et initialisation du convertisseur numérique/analogique ... 27

8.3 Utilisation des lignes de sorties analogiques... 27

8.3.1 Activation / désactivation d’une sortie ... 27

8.3.2 Génération d’une tension sur une sortie ... 28

8.3.3 Test de fin de conversion... 28

(6)

1 Syntaxe du C pour microcontrôleur

1.1 Types spéciaux

Aux types habituels du langage C viennent s’ajouter 2 types spécifiques au microcontrôleur : uint16_t : représente un entier naturel sur 16 bits (0 à 65535)

uint32_t : représente un entier naturel sur 32 bits (0 à 4 294 967 295)

1.2 Structure de programme

Les programmes pour le SAM3X8E devront respecter la structure suivante : #include <stdio.h>

#include "libTPIUT.h"

// Déclarations de constantes et de variables globales // Déclarations des prototypes des fonctions utilisées // (en particulier des fonctions d’interruption)

// Programme principal int main(void) {

initCarte();

configureConsole(); // Si l’on utilise la console

while(true) { // Traitements

} }

// Corps des fonctions utilisées correspondant aux prototypes ci dessus

1.3 Constantes prédéfinies

Les constantes suivantes sont définies dans le fichier "libTPIUT.h" :

FREQ_CPU fréquence en Hz de l'horloge du CPU = 84000000

FREQ_PERIPHS fréquence en Hz de l'horloge des périphériques = 84000000

FREQ_HORLOGE_LENTE fréquence en Hz de l'horloge "lente" = 32768

TENSION_ALIMENTATION tension en Volts d'alimentation de la carte = 3,3

NBR_MAX_INTERRUPTIONS nombre maximal de fonctions d'interruption que l'on peut

définir = 8

MIN_PRIORITE préemption minimale d'interruption = 15

MAX_PRIORITE préemption maximale d'interruption = 0

NB_PORTS nombre de contrôleurs de lignes (ports) = 4

NB_TIMERS nombre de Timers = 9

NB_GENE_SIGNAUX nombre de générateurs de signaux = 8

MAX_LIGNE_PORTA numéro maximum de ligne contrôlée par le port A = 29

MAX_LIGNE_PORTB numéro maximum de ligne contrôlée par le port B = 31

MAX_LIGNE_PORTC numéro maximum de ligne contrôlée par le port C = 30

MAX_LIGNE_PORTD numéro maximum de ligne contrôlée par le port D = 10

FILTRE_DELAI_MIN durée minimale de filtrage des lignes en ms = 1

(7)

NB_CANAUX_CAN nombre d'entrées du convertisseur A/N = 16

CAPT_TEMP n° de l'entrée du conv A/N reliée au capteur de température = 15

DELAI_MIN_CONVAN temps minimal de conversion du conv A/N en µs = 3

DELAI_MAX_CONVAN temps maximal de conversion du conv A/N en µs = 100

LG_MAX_SEQUENCE longueur maximale d'une liste de conversion A/N = 15

CPM_FILTRE_MAX nombre maximal de comparaisons de seuil successives pour déclencher un événement = 4

TENSION_MIN_CONVNA tension minimale en sortie du conv N/A en Volts = 0,55 TENSION_MAX_CONVNA tension maximale en sortie du conv N/A en Volts = 2,75

FREQ_MIN_HAB fréquence minimale programmable pour les horloges A et B des générateurs de signaux en Hz = 322

FREQ_MAX_HAB fréquence maximale programmable pour les horloges A et B des générateurs de signaux en Hz = 3000000

2 Initialisations générales

2.1 Démarrage de la carte

Le démarrage de la carte à microcontrôleur suppose un certain nombre d'initialisations. Elles sont faites par la fonction suivante qui doit être appelée dès le début du programme.

void initCarte()

2.2 Initialisation des entrées/sorties console

Les programmes peuvent utiliser des entrées sorties de type printf/scanf. Elles se font via la fenêtre de terminal d’Atmel Studio. Pour que ces entrées/sorties soient utilisables il faut initialiser le périphérique qui communique avec le terminal par la fonction suivante :

void configureConsole ()

2.3 Exemple

int main(void) {

initCarte();

configureConsole();

printf("C’est parti !\n");

while(true) {

// ce que fait le programme

} }

Remarque : lorsque la console est initialisée les lignes 8 et 9 du PortA sont inutilisables.

3 Allumage/Extinction des contrôleurs de périphériques

Afin de limiter la consommation du microcontrôleur, les contrôleurs de périphériques sont initialement éteints. Il conviendra donc de les allumer avant toute utilisation et il est possible de les éteindre s’ils ne doivent plus être utilisés.

3.1 Allumer un contrôleur de périphérique

La fonction suivante permet d’allumer un contrôleur de périphérique : void allumerPeriph(périphérique)

(8)

Le paramètre désigne le contrôleur à allumer. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD pour les contrôleurs de lignes ; Timer0 à Timer8 pour les Timers ; ConvAN pour le convertisseur analogique/numérique ; ConvNA pour le convertisseur numérique/analogique ; GeneSignal0 à GeneSignal7 pour les générateurs de signaux.

3.2 Éteindre un contrôleur de périphérique

La fonction suivante permet d’éteindre un contrôleur de périphérique : void eteindrePeriph(périphérique)

• Le paramètre désigne le contrôleur à éteindre. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD pour les contrôleurs de lignes ; Timer0 à Timer8 pour les Timers ; ConvAN pour le convertisseur analogique/numérique ; ConvNA pour le convertisseur numérique/analogique ; GeneSigna0 à GeneSignal7 pour les générateurs de signaux.

Remarque : lorsque la console est utilisée le PortA ne doit pas être éteint.

4 Lignes d'entrées / sorties numériques

Le SAM3X8E dispose de 104 lignes physiques d'entrée/sortie pilotées par 4 contrôleurs appelés "Ports" (PortA à PortD). Chaque ligne peut être indépendamment programmée comme entrée numérique (reliée à un capteur) ou comme sortie numérique (reliée à un actionneur). De plus, la plupart des lignes physiques peuvent être assignées à d’autres contrôleurs de périphériques du microcontrôleur qui les utilisent, selon le cas, comme entrée ou comme sortie.

4.1 Utilisation de lignes en sortie numérique

Une ligne en sortie numérique peut être mise au niveau 0 ou au niveau 1 pour piloter un actionneur de type numérique.

4.1.1 Initialisation d’une ligne en sortie numérique

La mise en marche du contrôleur de la ligne se fait par la fonction allumerPeriph (voir 3.1).

Pour indiquer au contrôleur qu’une ligne est utilisée en sortie numérique on utilise la fonction suivante :

void programmerLigne(port, numéro, mode)

• Le premier paramètre désigne le contrôleur (port) pilotant la ligne à programmer. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD

• Le deuxième paramètre désigne le numéro de la ligne à programmer. Il peut prendre les valeurs 0 à 29 pour le PortA, 0 à 31 pour le PortB, 0 à 30 pour le portC et 0 à 10 pour le PortD.

• Le troisième paramètre indique l’état initial choisi pour cette ligne. Il peut prendre les valeurs SORTIE0 ou SORTIE1 selon que la ligne doit initialement être à 0 ou à 1.

4.1.2 Modification de l’état d’une ligne en sortie numérique

La fonction suivante permet de modifier l’état d’une ligne programmée en sortie : void ecrireLigne(port, numéro, valeur)

• Le premier paramètre désigne le contrôleur (port) pilotant la ligne à modifier. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD

• Le deuxième paramètre désigne le numéro de la ligne à modifier. Il peut prendre les valeurs 0 à 29 pour le PortA, 0 à 31 pour le PortB, 0 à 30 pour le portC et 0 à 10 pour le PortD.

• Le dernier paramètre est le niveau auquel mettre cette ligne. Il ne peut prendre que la valeur 0 ou la valeur 1.

(9)

4.1.3 Exemple

Ligne 21 du port A utilisée en sortie initialement mise au niveau 0 :

allumerPeriph(PortA);

programmerLine(PortA, 21, SORTIE0);

Pour mettre la ligne à 1 :

ecrireLigne(PortA, 21, 1);

Pour mettre la ligne à 0 :

ecrireLigne(PortA, 21, 0);

4.2 Utilisation de lignes en entrée numérique

Une ligne en entrée numérique est connectée à un capteur numérique qui peut la mettre au niveau 0 ou au niveau 1. Une ligne en entrée numérique non connectée sera considérée comme au niveau 1.

4.2.1 Initialisation d’une ligne en entrée numérique

La mise en marche du contrôleur de la ligne se fait par la fonction allumerPeriph (voir 3.1).

Pour indiquer au contrôleur qu’une ligne est utilisée en entrée numérique on utilise la fonction suivante :

void programmerLigne(port, numéro, ENTREE)

• Le premier paramètre désigne le contrôleur (port) pilotant la ligne à programmer. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD

• Le deuxième paramètre désigne le numéro de la ligne à programmer. Il peut prendre les valeurs 0 à 29 pour le PortA, 0 à 31 pour le PortB, 0 à 30 pour le portC et 0 à 10 pour le PortD.

4.2.2 Consultation de l’état d’une ligne en entrée numérique

La fonction suivante permet de consulter le niveau actuel d’une ligne programmée en entrée : int lireLigne(port, numéro)

• Le premier paramètre désigne le contrôleur (port) pilotant la ligne à consulter. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD

• Le deuxième paramètre désigne le numéro de la ligne à consulter. Il peut prendre les valeurs 0 à 29 pour le PortA, 0 à 31 pour le PortB, 0 à 30 pour le portC et 0 à 10 pour le PortD.

• La fonction renvoie le niveau actuel de cette ligne qui ne peut être que 0 ou 1. Une ligne non connectée sera considérée comme au niveau 1.

4.2.3 Exemple

Ligne 21 du port A utilisée en entrée :

allumerPeriph(PortA);

programmerLine(PortA, 21, ENTREE);

Pour lire sa valeur :

int etat = lireLigne(PortA, 21); // etat vaut 0 ou 1

4.2.4 Mise en place d’un filtrage sur les lignes en entrée numérique

Il arrive parfois que certains capteurs numériques ne produisent pas immédiatement un état stable lorsque leur niveau de sortie change. Par exemple un capteur mécanique qui produit un niveau 1 lorsqu’il est activé peut connaître, au moment de son activation, une période plus ou moins longue pendant laquelle sa sortie oscille entre son état antérieur (0) et son état final (1). Ce phénomène est dû aux vibrations mécaniques du contact du capteur. Le SAM3X8E possède une fonction de filtrage permettant d’attendre que l’état stable de la ligne soit atteint. Ce filtrage correspond à un délai pendant

(10)

lequel l’état de la ligne est considéré comme inchangé. Le schéma suivant présente le principe de fonctionnement du filtrage mis en œuvre par les contrôleurs de lignes :

La fonction suivante permet de mettre en place un tel filtrage sur une ligne préalablement programmée en entrée (voir 4.2.1) :

void activerFiltrageLigne(port, numéro, délai)

• Le premier paramètre désigne le contrôleur (port) pilotant la ligne à filtrer. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD

• Le deuxième paramètre désigne le numéro de la ligne à filtrer. Il peut prendre les valeurs 0 à 29 pour le PortA, 0 à 31 pour le PortB, 0 à 30 pour le portC et 0 à 10 pour le PortD.

• Le dernier paramètre indique la durée (en ms) pendant laquelle l’état de la ligne doit être considéré comme étant instable. Sa valeur est comprise entre 0 et 250. Les valeurs généralement utilisées pour un capteur mécanique se situent entre 25 et 50 ms, mais, le plus souvent, seule l’expérimentation « en vrai » peut permettre de déterminer la valeur adéquate. Une valeur plus élevée que nécessaire fonctionnera toujours mais retardera d’autant la prise en compte d’un changement d’état, tandis qu’une valeur trop faible provoquera parfois la lecture de fausses valeurs de l’état de la ligne.

La fonction suivante permet de supprimer le filtrage sur une ligne programmée en entrée : void desactiverFiltrageLigne(port, numéro)

• Le premier paramètre désigne le contrôleur (port) pilotant la ligne à cesser de filtrer. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD

• Le deuxième paramètre désigne le numéro de la ligne à cesser de filtrer. Il peut prendre les valeurs 0 à 29 pour le PortA, 0 à 31 pour le PortB, 0 à 30 pour le PortC et 0 à 10 pour le PortD.

4.2.5 Exemple

Ligne 2 du port A utilisée en entrée avec filtrage (30 ms) :

allumerPeriph(PortA);

programmerLine(PortA, 2, ENTREE);

activerFiltrageLigne(PortA, 2, 30);

Pour lire sa valeur (après filtrage) :

(11)

4.2.6 Association de fonctions d’interruption à des lignes en entrée

numérique

Lorsque le changement d’état d’une ligne en entrée doit être détecté alors que le processeur est occupé à autre chose ou lorsque ce changement d’état se produit rarement ou encore lorsqu’il correspond à un événement urgent, on utilise le mécanisme d’interruption. Ce mécanisme permet d’associer à l’événement de changement d’état de la ligne une fonction (fonction d’interruption) qui sera automatiquement exécutée dès le changement d’état de la ligne.

La fonction suivante permet d’associer une fonction d’interruption au changement d’état d’une ligne programmée en entrée :

void autoriserITLigne(port, numéro, changement, priorité, fonction)

• Le premier paramètre désigne le contrôleur (port) pilotant la ligne devant déclencher une interruption. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD.

• Le deuxième paramètre désigne le numéro de la ligne devant déclencher une interruption. Il peut prendre les valeurs 0 à 29 pour le PortA, 0 à 31 pour le PortB, 0 à 30 pour le portC et 0 à 10 pour le PortD.

• Le troisième paramètre indique quel changement d’état de la ligne provoquera l’exécution de la fonction d’interruption. Il peut prendre les valeurs : FRONT_MONTANT s’il s’agit du passage de l’état 0 à l’état 1, FRONT_DESCENDANT s’il s’agit du passage de l’état 1 à l’état 0 ou FRONT_TOUS s’il s’agit d’un changement d’état quelconque.

Le quatrième paramètre correspond au niveau de préemption de l’interruption. Il doit être le même pour toutes les lignes pilotées par le même contrôleur (port). Cette valeur est comprise entre 0 et 15 (0 correspond à la préemption la plus élevée).

• Le dernier paramètre est le nom de la fonction à exécuter lorsque le changement d’état de la ligne se produit. Cette fonction ne renvoie aucune valeur (void) et n’accepte aucun paramètre.

4.2.7 Suppression d’une fonction d’interruption associée à une ligne

en entrée numérique

La fonction suivante permet d’enlever la fonction d’interruption associée au changement d’état d’une ligne programmée en entrée :

void interdireITLigne(port, numéro)

• Le premier paramètre désigne le contrôleur (port) pilotant la ligne ne devant plus déclencher de fonction d’interruption. Il peut prendre les valeurs : PortA , PortB , PortC ou PortD.

• Le deuxième paramètre désigne le numéro de la ligne ne devant plus déclencher de fonction d’interruption. Il peut prendre les valeurs 0 à 29 pour le PortA, 0 à 31 pour le PortB, 0 à 30 pour le portC et 0 à 10 pour le PortD.

4.2.8 Exemple

Ligne 2 du port A utilisée pour exécuter une fonction d’interruption de préemption 13 lors des passages de l’état 0 à l’état 1 de la ligne :

allumerPeriph(PortA);

programmerLine(PortA, 2, ENTREE);

autoriserITLigne(PortA, 2, FRONT_MONTANT, 13, changement);

void changement() {

// traitement déclenché chaque fois que la ligne passe à 1

(12)

5 Timers

Le SAM3X8E possède 8 Timers permettant : De générer des délais répétitifs ou non De mesurer des durées

De déclencher le convertisseur analogique/numérique dans un délai donné ou à un rythme donné (délai répétitif).

5.1 Principe de fonctionnement d’un Timer

Le délai ou la durée sont définis par un entier correspondant à un nombre de tops d’horloge comptés par le Timer. L’horloge utilisée pour ce comptage est obtenue par division de fréquence à partir de l’horloge du processeur (84MHz) ou par utilisation d’une horloge fixe de fréquence 32768Hz.

5.1.1 Délais ou durées maximales

En fonction de l’horloge choisie pour le comptage, les délais ou les durées maximum pouvant être atteints sont donnés dans le tableau suivant :

Division ou

Horloge Temps entre 2 tops

Délai ou durée maximum en mode INC

Délai ou durée maximum en mode INC_DEC

Par 2 1/42 μs 102,26 s (1 min 42 s) 204,52 s (3 min 24 s) Par 8 2/21 μs 409,04 s (6 min 49 s) 818,08 s (13 min 38 s) Par 32 8/21 μs 1636,17 s (27 min 16 s) 3272,35 s (54 min 32 s) Par 128 32/21 μs 6544,71 s (1h 49 min) 13089,42 s (3h 38 min) 32768Hz 15625/512 μs 131072 s (1 jour 12h 24 min) 262144 s (3 jours 49 min)

5.1.2 Calculs

Pour générer un délai de durée θ il faut d’abord choisir un facteur de division de la fréquence de l’horloge du processeur ou opter pour l’horloge à 32768Hz de façon à pouvoir atteindre cette valeur θ. Puis on calculera le nombre de tops d’horloge correspondant exactement à θ.

Pour mesurer une durée il faut en connaître la valeur maximale θ puis choisir un facteur de division de la fréquence de l’horloge du processeur ou opter pour l’horloge à 32768Hz de façon à ne pas dépasser cette valeur θ. Lors d’une mesure, on pourra calculer la durée exacte à partir du nombre de tops d’horloge que le Timer a comptés.

Choix du facteur de division ou de l’horloge

On souhaite généralement obtenir la précision maximale. Pour ce faire il conviendra de choisir le facteur de division de fréquence de l’horloge du processeur ou d’opter pour l’horloge à 32 768Hz de façon à obtenir un temps entre 2 tops minimal (pour la précision) mais suffisant.

Par exemple pour un délai de 4 minutes on choisira une division de la fréquence de l’horloge du processeur par 8 puisque la division par 2 ne permet pas d’atteindre 4 minutes et qu’une division par 32 ou 128 ou le choix de l’horloge à 32768Hz correspondraient à un temps entre 2 tops plus grand (donc à une moins bonne précision).

Calcul du nombre de tops d’horloge correspondant au délai ou au temps

Avec le choix précédent le temps séparant 2 tops d’horloge est de 2/21μs (voir 2ème colonne du tableau ci-dessus).

Un délai de 4 minutes (240s soit 240.106μs) correspond au comptage de :

21 2

10

240 6 = 2 520 000 000 tops se produisant à ce rythme.

Lors d’une mesure de temps, si le Timer a compté N tops d’horloge c’est que le temps mesuré est de N * 2/21 μs. De par le choix d’une division d’horloge par 8, la durée maximale pouvant être mesurée est de 6 minutes et 49 secondes.

(13)

5.2 Mise en marche d’un Timer

La mise en marche d’un Timer se fait par la fonction allumerPeriph (voir 3.1).

5.3 Timer en génération de délai

Les Timers sont souvent utilisés pour générer des délais soit pour simplement attendre qu’une opération soit terminée, soit pour ne déclencher une opération qu’après un temps donné ou à un rythme donné, soit pour vérifier qu’une opération se fasse dans un délai donné.

5.3.1 Initialisation d’un Timer pour générer un délai

La fonction permettant de programmer un Timer pour générer un délai est la suivante : void timerModeDelai(timer, division, limite, répétition, direction)

Le premier paramètre désigne le Timer utilisé. Sa valeur peut être : Timer0 à Timer8.

• Le deuxième paramètre définit la division de fréquence appliquée à l’horloge du processeur (dont la fréquence est de 84MHz). Les valeurs possibles sont HDIV2, HDIV8, HDIV32 ou HDIV128 pour une division par 2 , 8 , 32 ou 128. Ce paramètre peut également prendre la valeur H_32768 pour que l’horloge utilisée par le Timer ait une fréquence de 32768 Hz (soit 215 Hz).

• Le troisième paramètre définit la limite de comptage des tops d’horloge et donc la durée (voir dernier paramètre). Sa valeur est un entier compris entre 1 et LIMITE_TIMER_MAX (c’est à dire entre 1 et 4 294 967 295). Si une valeur numérique est utilisée pour ce paramètre elle doit être suivie de UL pour éviter qu’elle ne soit interprétée par le compilateur C comme un nombre signé. Ainsi on écrira, par exemple, 42000000UL et non 42000000.

• Le quatrième paramètre indique si le délai ne doit être généré qu’une seule fois ou doit l’être de façon répétitive. La valeur NON_REPETITIF indique que, dès que le Timer a atteint le délai choisi, il s’arrête tandis que la valeur REPETITIF indique que, dès que le Timer a atteint le délai choisi, il repart pour un nouveau délai de durée identique.

• Le dernier paramètre définit la façon dont sont comptés les tops d’horloge. Il peut prendre les valeurs suivantes :

o INC : le Timer compte les tops d’horloge en partant de 0 et en faisant +1 à chaque top. Le délai est atteint lorsqu’est atteinte la valeur définie par le 2ème paramètre.

o INC_DEC : le Timer compte les tops d’horloge en partant de 0 et en faisant +1 à chaque top. Lorsque la valeur définie par le 2ème paramètre est atteinte, il continue à compter les tops d’horloge mais en faisant -1 à chaque top. Le délai est atteint lorsque la valeur 0 est atteinte. Pour une même valeur du 2ème paramètre le délai sera donc le double de celui obtenu en mode INC.

5.3.2 Savoir si le délai est terminé

La fonction suivante permet de savoir si un Timer a atteint la valeur limite de comptage : bool testerEtatTimer(timer, LIMITE )

Le paramètre désigne le Timer consulté. Sa valeur peut être: Timer0 à Timer8.

La valeur renvoyée est true si le délai généré par le Timer est terminé et false dans le cas contraire (soit le délai n’a pas commencé soit il n’est pas fini).

5.3.3 Exemple

Timer 5 utilisé pour générer un délai répétitif de 1 seconde :

allumerPeriph(Timer5);

timerModeDelai(Timer5, HDIV2, 42000000UL, REPETITIF, INC);

Pour lancer le délai (à faire une seule fois puisque le délai est répétitif) :

(14)

Pour arrêter le délai (on pourra le relancer par lancerTimer) :

arreterTimer(Timer5);

Pour savoir si le délai est terminé :

if (testerEtatTimer(Timer5, LIMITE)) { ....

5.4 Timer en mesure de durée

Une mesure d’une durée correspond à mesurer le temps qui sépare 2 changements d’états successifs d’une ligne en entrée numérique. A chaque Timer est associée une ligne numérique physique dont il peut mesurer le temps entre changements d’état. Dès que la mesure est effectuée le Timer s’arrête, il devra donc être relancé si l’on souhaite faire une nouvelle mesure.

5.4.1 Lignes numériques associées aux mesures de durée par Timer

Les lignes d’entrées numériques associées aux différents Timers sont indiquées dans le tableau suivant :

Timer Port Ligne Timer0 PortB 25 Timer1 PortA 2 Timer2 PortA 5 Timer3 PortB 0 Timer4 PortB 2 Timer5 PortB 4 Timer6 PortC 25 Timer7 PortC 28 Timer8 PortD 7

Le contrôleur qui les pilote doit être allumé (voir 3.1). Elles doivent ensuite être programmées de façon à être liées au Timer de la façon suivante :

programmerLigne(port, numéro, FONCTIONB) Selon le Timer choisi :

• Le premier paramètre est celui indiqué dans la colonne "Port" du tableau ci dessus.

• Le deuxième paramètre est celui indiqué dans la colonne "Ligne" du tableau ci dessus.

5.4.2 Initialisation d’un Timer pour mesurer une durée

La fonction permettant de programmer un Timer pour une mesure de durée est la suivante : void timerModeMesure(timer, division, limite, mesure)

Le premier paramètre désigne le Timer utilisé. Sa valeur peut être : Timer0 à Timer8.

• Le deuxième paramètre définit la division de fréquence appliquée à l’horloge du processeur (dont la fréquence est de 84MHz). Les valeurs possibles sont HDIV2, HDIV8, HDIV32 ou HDIV128 pour une division par 2 , 8 , 32 ou 128. Ce paramètre peut également prendre la valeur H_32768 pour que l’horloge utilisée par le Timer ait une fréquence de 32768 Hz (soit 215 Hz).

• Le troisième paramètre définit la limite de comptage des tops d’horloge donc la durée maximale mesurable. Sa valeur doit être supérieure à la durée maximale pouvant se produire sur la ligne d’entrée numérique de façon à ne pas être dépassée. C’est un entier compris entre 1 et LIMITE_TIMER_MAX (c’est à dire entre 1 et 4 294 967 295). Si une valeur numérique est utilisée pour ce paramètre elle doit être suivie de UL pour éviter qu’elle ne soit interprétée par le compilateur C comme un nombre signé. Ainsi on écrira, par exemple, 42000000UL et non 42000000.

(15)

o DE_0_A_1 : Le Timer mesure le temps qui sépare le prochain passage à 0 de sa ligne d’entrée numérique au passage à 1 suivant de cette ligne.

o DE_1_A_0 : Le Timer mesure le temps qui sépare le prochain passage à 1 de sa ligne d’entrée numérique au passage à 0 suivant de cette ligne.

o DE_0_A_0 : Le Timer mesure le temps qui sépare les 2 prochains passages à 0 successifs de sa ligne d’entrée numérique.

o DE_1_A_1 : Le Timer mesure le temps qui sépare les 2 prochains passages à 1 successifs de sa ligne d’entrée numérique.

5.4.3 Savoir si la mesure de durée est terminée

La fonction suivante permet de savoir si un Timer a terminé une mesure de temps : bool testerEtatTimer(timer, MESURE )

Le paramètre désigne le Timer consulté. Sa valeur peut être: Timer0 à Timer8.

La valeur renvoyée est true si la mesure de temps est terminée et false dans le cas contraire (soit elle n’a pas commencé soit elle n’est pas encore finie).

5.4.4 Récupération de la durée mesurée

Lorsqu’une mesure de durée est terminée (voir 5.4.2), la fonction suivante permet d’un récupérer la valeur (cette valeur correspond au nombre de tops d’horloges comptabilisés au cours de la mesure) :

uint32_t lireMesureTimer(timer)

Le paramètre désigne le Timer ayant effectué la mesure. Sa valeur peut être : Timer0 à Timer8.

• La valeur renvoyée est le nombre de tops d’horloge du Timer comptabilisés pendant la mesure.

5.4.5 Exemple

Timer 0 utilisé pour mesurer la durée pendant laquelle la ligne 25 du port B reste à 0 (l’horloge du Timer est à 42MHz et la limite de durée est mise au maximum) :

Rq : Le Timer s'arrête à la fin de la mesure. Pour faire une autre mesure il faudra le relancer.

allumerPeriph(Timer0);

timerModeMesure(Timer0, HDIV2, LIMITE_TIMER_MAX, DE_0_A_1);

allumerPeriph(PortB);

programmerLine(PortB, 25, FONCTIONB);

Pour démarrer la mesure :

lancerTimer(Timer0);

Pour savoir si la mesure a eu lieu :

if (testerEtatTimer(Timer0, MESURE))

Pour récupérer la mesure quand elle a eu lieu : uint32_t duree = lireMesureTimer(Timer0);

5.5 Timer en déclenchement du convertisseur

Analogique/Numérique

Les mesures faites sur les entrées analogiques par le convertisseur analogique/numérique peuvent être démarrées par programme ou être effectuées en boucle (voir 6.3). Toutefois il est souvent nécessaire d’effectuer ces mesures à un rythme régulier ne correspondant pas à l’un de ceux obtenus avec le mode continu du convertisseur. Dans ce cas on utilisera un Timer pour déclencher une conversion soit au bout d’un délai donné soit à un rythme donné.

(16)

5.5.1 Initialisation d’un Timer pour déclencher le convertisseur

Analogique/Numérique

La fonction permettant de programmer un Timer pour déclencher le convertisseur Analogique/Numérique est la suivante :

void timerModeDeclenchement(timer, division, limite, répétition)

Le premier paramètre désigne le Timer utilisé. Sa valeur ne peut être que : Timer0, Timer1 ou Timer2.

• Le deuxième paramètre définit la division de fréquence appliquée à l’horloge du processeur (dont la fréquence est de 84MHz). Les valeurs possibles sont HDIV2, HDIV8, HDIV32 ou HDIV128 pour une division par 2 , 8 , 32 ou 128. Ce paramètre peut également prendre la valeur H_32768 pour que l’horloge utilisée par le Timer ait une fréquence de 32768 Hz (soit 215 Hz).

• Le troisième paramètre définit la limite de comptage des tops d’horloge donc le délai ou le rythme de déclenchement. Sa valeur est un entier compris entre 1 et LIMITE_TIMER_MAX (c’est à dire entre 1 et 4 294 967 295). Si une valeur numérique est utilisée pour ce paramètre elle doit être suivie de UL pour éviter qu’elle ne soit interprétée par le compilateur C comme un nombre signé. Ainsi on écrira, par exemple, 42000000UL et non 42000000.

• Le quatrième paramètre indique si le délai de déclenchement ne doit être généré qu’une seule fois ou doit l’être de façon répétitive. La valeur NON_REPETITIF indique que dès que le Timer a atteint le délai il déclenche le convertisseur puis s’arrête tandis que la valeur REPETITIF indique que le Timer déclenche le convertisseur au rythme régulier de ce délai.

5.5.2 Exemple

Conversion Analogique/Numérique sur l'entrée 3 (ligne 6 du port A) pilotée par le Timer 0 (toutes les 100 µs) :

allumerPeriph(Timer0);

timerModeDeclenchement(Timer0, HDIV2, 42*100, REPETITIF);

allumerPeriph(ConvAN);

initConvAN(4, RES12BITS);

declenchementConvAN(TIMER0);

choisirEntreeConvAN(3);

lancerTimer(Timer0);

5.6 Démarrage et arrêt d’un Timer

Un Timer en mode génération de délai ou déclenchement du convertisseur doit être démarré : Une seule fois s’il est en mode REPETITF

Pour chaque délai ou déclenchement s’il est en mode NON_REPETITF Un Timer en mode mesure de temps doit être démarré à chaque mesure.

La fonction suivante permet de remettre à zéro un Timer et de le démarrer : void lancerTimer(timer)

Le paramètre désigne le Timer démarré. Sa valeur peut être: Timer0 à Timer8.

Un Timer, quel que soit son mode de fonctionnement peut être arrêté à tout moment par la fonction suivante :

void arreterTimer(timer)

(17)

5.7 Remise à zéro d’un Timer par une ligne d’entrée numérique

A chaque Timer est associée une ligne de commande numérique physique permettant de le remettre à zéro lors d’un changement d’état de cette ligne. Cette remise à zéro peut se produire à tout moment même si le Timer est en cours de comptage.

5.7.1 Lignes numériques associées à la remise à zéro de Timer

Les lignes d’entrées numériques associées à la remise à zéro des différents Timers sont indiquées dans le tableau suivant :

Timer Port Ligne Mode Timer0 PortB 27 FONCTIONB Timer1 PortA 3 FONCTIONA Timer2 PortA 56 FONCTIONA Timer3 PortB 1 FONCTIONB Timer4 PortB 3 FONCTIONB Timer5 PortB 5 FONCTIONB Timer6 PortC 26 FONCTIONB Timer7 PortC 29 FONCTIONB Timer8 PortD 8 FONCTIONB

Le contrôleur qui les pilote doit être allumé (voir 3.1). Elles doivent ensuite être programmées de façon à être liées au Timer de la façon suivante :

programmerLigne(port, numéro, mode) Selon le Timer choisi :

• Le premier paramètre est celui indiqué dans la colonne "Port" du tableau ci dessus.

• Le deuxième paramètre est celui indiqué dans la colonne "Ligne" du tableau ci dessus.

• Le dernier paramètre est celui indiqué dans la colonne "Mode" du tableau ci dessus.

5.7.2 Initialisation de la remise à zéro d’un Timer par ligne numérique

La fonction suivante permet d’indiquer comment un Timer est remis à zéro par la ligne de commande numérique qui lui est associée :

void activerRazExterne(timer, front)

• Le premier paramètre désigne le Timer devant être remis à zéro par la ligne numérique. Sa valeur peut être: Timer0 à Timer8.

• Le second paramètre indique quel changement d’état de la ligne provoquera la remise à zéro. Il peut prendre les valeurs : FRONT_MONTANT s’il s’agit du passage de l’état 0 à l’état 1, FRONT_DESCENDANT s’il s’agit du passage de l’état 1 à l’état 0 et FRONT_TOUS s’il s’agit d’un changement d’état quelconque de la ligne.

5.7.3 Arrêt de la remise à zéro d’un Timer par ligne numérique

La fonction suivante permet d’invalider la remise à zéro d’un Timer par la ligne numérique qui lui est associée :

void desactiverRazExterne(timer)

• Le paramètre désigne le Timer ne devant plus être remis à zéro par sa ligne numérique. Sa valeur peut être: Timer0 à Timer8.

(18)

5.7.4 Exemple

Timer 0 (précédemment initialisé en délai ou en mesure - voir 5.3 ou 5.4) remis à 0 par tous les fronts de la ligne 27 du port B :

allumerPeriph(PortB);

programmerLine(PortB, 27, FONCTIONB);

activerRazExterne(Timer0, FRONT_TOUS);

Pour désactiver la ràz du timer par la ligne 27 du port B :

desactiverRazExterne(Timer0);

5.7.5 Savoir un Timer a été remis à zéro par sa ligne numérique

La fonction suivante permet de savoir si un Timer a été remis à zéro par sa ligne numérique : bool testerEtatTimer(timer, RAZ )

Le paramètre désigne le Timer consulté. Sa valeur peut être: Timer0 à Timer8.

La valeur renvoyée est true si le Timer a été remis à zéro par sa ligne numérique et false dans le cas contraire.

5.8 Consultation de l’état d’un Timer

Plusieurs fonctions permettent de consulter l’état d’un Timer même lorsqu’il est en cours de fonctionnement.

La fonction suivante renvoie la fréquence en Hertz de l’horloge actuellement utilisée par un Timer, cette valeur dépend, évidemment, de son initialisation (voir 5.3 ou 5.4 ou 5.5) :

uint32_t frequenceTimer(timer)

Le paramètre désigne le Timer consulté. Sa valeur peut être: Timer0 à Timer8.

La fonction suivante renvoie la limite de comptage actuelle d’un Timer, cette valeur dépend, évidemment, de son initialisation (voir 5.3 ou 5.4 ou 5.5) ou de sa modification ultérieure (voir 5.9):

uint32_t lireLimiteTimer(timer)

Le paramètre désigne le Timer consulté. Sa valeur peut être: Timer0 à Timer8.

La fonction suivante renvoie la valeur de comptage actuelle d’un Timer. Cette fonction peut être appelée même si le Timer est en cours de comptage (bien entendu la valeur renvoyée sera celle à laquelle il en est au moment de l’appel) :

uint32_t lireTimer(timer)

Le paramètre désigne le Timer consulté. Sa valeur peut être: Timer0 à Timer8.

5.9 Modification de la limite de comptage d’un Timer

La fonction suivante permet de modifier la limite de comptage actuelle d’un Timer : void modifierLimiteTimer(timer, limite)

Le premier paramètre désigne le Timer modifié. Sa valeur peut être: Timer0 à Timer8.

(19)

5.10 Association de fonctions d’interruption aux Timers

5.10.1

Associer une fonction à un événement de Timer

On peut associer à chaque fin de délai, à chaque mesure ainsi qu’à chaque remise à zéro par ligne numérique d’un Timer une fonction qui sera automatiquement exécutée. Ceci est obtenu par la fonction suivante :

void autoriserITTimer(timer, cause, priorité, fonction)

• Le premier paramètre désigne le Timer aux événements duquel doit être associée la fonction d’interruption. Sa valeur peut être: Timer0 à Timer8.

• Le deuxième paramètre indique quel événement provoquera l’exécution de la fonction associée. Il peut prendre les valeurs : LIMITE s’il s’agit de la fin d’un délai, MESURE s’il s’agit de la fin d’une mesure de temps et RAZ s’il s’agit de la remise à zéro par ligne numérique.

• Le troisième paramètre correspond à la préemption de l’interruption. Cette valeur est comprise entre 0 et 15 (0 correspond à la préemption la plus élevée).

• Le dernier paramètre est le nom de la fonction à exécuter lorsque l’événement se produit. Cette fonction ne renvoie aucune valeur (void) et n’accepte aucun paramètre.

5.10.2

Supprimer la fonction associée à un événement de Timer

La fonction suivante permet d’enlever la fonction d’interruption associée à un événement de Timer : void interdireITTimer(timer, cause)

• Le premier paramètre désigne le Timer aux événements duquel ne doit plus être associée de fonction d’interruption. Sa valeur peut être: Timer0 à Timer8.

• Le deuxième paramètre indique quel événement ne devra plus déclencher d’exécution de fonction d’interruption. Il peut prendre les valeurs : LIMITE, MESURE ou RAZ.

5.10.3

Exemple

Timer 5 utilisé pour générer un délai répétitif de 1 seconde associé à une fonction d’interruption :

allumerPeriph(Timer5);

timerModeDelai(Timer5, HDIV2, 42000000UL, REPETITIF, INC);

autoriserITTimer(Timer5, LIMITE, 2, itSeconde);

void itSeconde() { ...

}

6 Lignes d'entrées analogiques

Le SAM3X8E dispose de 15 lignes physiques d'entrées analogiques pouvant être connectées à des capteurs analogiques fournissant une information sous la forme d’une tension électrique variant entre 0 et 3,3V.

La lecture d’une information sur une ligne d’entrée analogique se fait au moyen d’un contrôleur spécial (convertisseur analogique/numérique) qui transforme la tension présente sur la ligne d’entrée en une valeur entière proportionnelle à cette tension et comprise entre 0 et 1023 ou entre 0 et 4095 selon le mode de fonctionnement choisi (voir 6.2).

(20)

6.1 Lignes physiques

Le convertisseur analogique/numérique possède 16 entrées : les 15 1ères entrées sont reliées à 8 lignes physiques associées au port A et à 7 lignes physiques associées au port B tandis que la 16ème entrée est reliée à un capteur de température interne :

Entrée du

convertisseur Port Ligne

Entrée du

convertisseur Port Ligne

0 PortA 2 8 PortB 12 1 PortA 3 9 PortB 13 2 PortA 5 10 PortB 17 3 PortA 6 11 PortB 18 4 PortA 22 12 PortB 19 5 PortA 23 13 PortB 20 6 PortA 24 14 PortB 21

7 PortA 16 15 Capteur de température

6.2 Mise en marche et initialisation du convertisseur

analogique/numérique

La mise en marche du convertisseur analogique/numérique se fait par la fonction allumerPeriph (voir 3.1). Son initialisation se fait par la fonction suivante :

void initConvAN(durée, résolution)

• Le premier paramètre définit le temps donné au convertisseur analogique/numérique pour transformer la tension présente sur l’entrée en un entier. Sa valeur se situe entre 3 et 100 et exprime ce temps de conversion en μs. Une valeur élevée donnera une mesure plus précise qu’une valeur faible mais nécessitera une attente plus longue.

• Le second paramètre correspond à la résolution de conversion. Si sa valeur est RES10BITS la mesure produira un entier entre 0 et 1023 (résolution 3,3mV), si sa valeur est RES12BITS la mesure produira un entier entre 0 et 4095 (résolution 0,8mV).

6.3 Déclenchement du convertisseur analogique/numérique

Les mesures effectuées par le convertisseur analogique/numérique peuvent être déclenchées par programme ou par un Timer (voir 5.5) ou s’effectuer en continu. Le mode de déclenchement est défini par la fonction :

void declenchementConvAN(mode)

• Le paramètre peut prendre les valeurs suivantes :

o PROG : Le déclenchement est fait par l’appel de la fonction lancerConversionAN, le convertisseur fait une mesure puis s’arrête.

o PROG_CONTINU : Le déclenchement est fait par l’appel de la fonction lancerConversionAN, après quoi le convertisseur effectue des mesures successives à vitesse maximale (définie par le paramètre durée de la fonction initConvAN voir 6.2).

o TIMER0 , TIMER1 ou TIMER2 : le déclenchement est piloté par le Timer désigné, le convertisseur fait une mesure puis s’arrête jusqu’à être relancé par ce Timer (voir 5.5). Lorsque le mode de déclenchement choisi est PROG le démarrage du convertisseur analogique/numérique est obtenu par la fonction :

void lancerConversionAN()

En mode PROG cette fonction doit être réappelée avant toute mesure, en mode PROG_CONTINU ou TIMER0 ou TIMER1 ou TIMER2 elle n’est pas utilisée.

(21)

6.4 Acquisition de données sur une ligne analogique

6.4.1 Choix de l’entrée

Le choix de l’entrée du convertisseur analogique/numérique sur laquelle se feront les prochaines mesures est fait par la fonction :

void choisirEntreeConvAN(numéro)

• Le paramètre indique le numéro de l’entrée du convertisseur analogique/numérique sur laquelle se feront les prochaines mesures. Il peut prendre les valeurs 0 à 15 pour les entrées reliées à des lignes physiques ou la valeur CAPT_TEMP pour le capteur de température. La correspondance entre ces numéros et les lignes physique est décrite en 6.1.

Une entrée utilisée par le convertisseur analogique/numérique peut être désactivée si on ne souhaite plus l’utiliser comme entrée analogique mais comme entrée ou sortie numérique (voir 0). Lorsque l’on choisit une nouvelle entrée par la fonction choisirEntreeConvAN, l’entrée précédemment choisie est automatiquement désactivée et il est inutile de le faire. La fonction permettant de désactiver une entrée est la suivante :

void desactiverEntreeConvAN(numéro)

• Le paramètre indique le numéro de l’entrée du convertisseur analogique/numérique à désactiver. Il peut prendre les valeurs 0 à 15 pour les entrées reliées à des lignes physiques ou la valeur CAPT_TEMP pour le capteur de température.

6.4.2 Mise en place d’une amplification sur une entrée analogique

Lorsque la valeur de la tension présente sur une ligne physique est faible, il est possible de l’amplifier avant de la transmettre à l’entrée du convertisseur analogique/numérique. Ceci est obtenu par la fonction :

void amplificationEntreeConvAN(numéro, amplification)

• Le premier paramètre indique le numéro de l’entrée du convertisseur analogique/numérique à amplifier. Il ne peut prendre que les valeurs 0 à 15 (l’amplification n’est pas applicable au capteur de température car sa valeur de sortie peut atteindre 3,3V).

• Le second paramètre peut prendre les valeurs :

o G_1 : pour ne pas amplifier l’entrée (la tension sur la ligne physique doit alors être comprise entre 0 et 3,3V).

o G_2 : pour multiplier la tension d’entrée par 2 (la tension sur la ligne physique doit alors être comprise entre 0 et 1,65V).

o G_4 : pour multiplier la tension d’entrée par 4 (la tension sur la ligne physique doit alors être comprise entre 0 et 0,825V).

6.4.3 Test de fin de conversion

Lorsqu’une mesure a été lancée (voir 6.3), il faut laisser au convertisseur analogique/numérique le temps de transformer la tension présente sur l’entrée sélectionnée en une valeur numérique. Cette opération a une durée définie lors de l’initialisation du convertisseur analogique/numérique (voir 6.2). La fonction suivante permet de savoir si la mesure est terminée :

bool testerEtatConvAN(indicateur)

• Le paramètre indique le numéro de l’entrée du convertisseur analogique/numérique dont on veut savoir si la valeur est actuellement disponible. Ce paramètre prend les valeurs FIN_CONV0 à FIN_CONV14 pour les lignes physiques d’entrée analogique ou la valeur FIN_CONVTEMP pour le capteur de température.

(22)

6.4.4 Récupération de la valeur mesurée

Lorsqu’une mesure est disponible (voir 6.4.3) elle peut être récupérée par l’une des fonctions suivantes :

uint32_t lireValeurConvAN(numéro) float lireTensionConvAN(numéro)

float lireTemperature()

• Le paramètre indique le numéro de l’entrée du convertisseur analogique/numérique dont on souhaite récupérer la valeur. Il peut prendre les valeurs 0 à 15 pour les entrées reliées à des lignes physiques ou la valeur CAPT_TEMP pour le capteur de température.

La première fonction renvoie la mesure sous la forme d’un entier compris entre 0 et 1023 ou 0 et 4095 selon la précision choisie lors de l’initialisation du convertisseur analogique/numérique (voir 6.2). Cet entier est, bien entendu, proportionnel à la tension présente sur l’entrée lors de la mesure après son éventuelle amplification.

La deuxième fonction renvoie la mesure en volts sous la forme d’un réel. La valeur renvoyée tient compte de l’amplification éventuellement mise en œuvre sur l’entrée.

La troisième fonction n’est utilisable que si la mesure a été faite sur le capteur de température interne. Elle renvoie la température mesurée en degrés Celsius.

6.4.5 Exemple

Conversion Analogique/Numérique sur l'entrée 3 (ligne 6 du port A) pilotée par programme :

allumerPeriph(ConvAN);

initConvAN(4, RES12BITS);

declenchementConvAN(PROG);

choisirEntreeConvAN(3);

Pour lancer chaque nouvelle mesure :

lancerConversionAN();

Pour attendre que la conversion soit terminée : while (! testerEtatConvAN(FIN_CONV3)) {}

Pour récupérer la valeur mesurée sur cette entrée : int mesure = lireValeurConvAN(3);

ou

float volts = lireTensionConvAN(3);

Pour mettre en place une amplification par 2 sur cette entrée :

amplificationEntreeConvAN(3, G_2);

6.5 Mise en place de seuils sur une entrée analogique

Dans certains cas on ne s’intéresse à la tension présente sur une entrée que lorsqu’elle dépasse certaines limites. Il est possible d’associer une limite maximale et minimale à une entrée et de demander au convertisseur de signaler des événements lorsque la mesure obtenue remplit certaines conditions relatives à ces valeurs de seuils.

6.5.1 Choix de l’entrée

Il se fait de la façon décrite en 6.4.1.

6.5.2 Amplification en entrée

(23)

6.5.3 Mise en place de conditions de seuils

La mise en place de conditions de seuils sur une entrée analogique est obtenue par la fonction suivante :

void activerSeuilsConvAN(numéro, contrôle, nombre, bas, haut)

• Le premier paramètre indique le numéro de l’entrée du convertisseur analogique/numérique à laquelle appliquer les seuils. Il peut prendre les valeurs 0 à 15 pour les entrées reliées à des lignes physiques ou la valeur CAPT_TEMP pour le capteur de température. La correspondance entre ces numéros et les lignes physique est décrite en 6.1.

• Le deuxième paramètre indique le type de contrôle de seuils à mettre en place. Les valeurs possibles sont :

o INF si l’on s’intéresse au cas où la mesure est inférieure au seuil bas

o SUP si l’on s’intéresse au cas où la mesure est supérieure au seuil haut

o DANS si l’on s’intéresse au cas où la mesure se situe entre le seuil bas et le seuil haut

o HORS si l’on s’intéresse au cas où la mesure se situe au dessous du seuil bas ou au dessus du seuil haut

• Le troisième paramètre indique le nombre de fois successives où la condition définie par le deuxième paramètre doit être remplie lors de mesures successives. Sa valeur est un entier entre 1 et 4.

• Le quatrième paramètre définit le seuil bas. C’est un entier compris entre 0 et 1023 ou 0 et 4095 selon la précision définie lors de l’initialisation du convertisseur (voir 6.2).

• Le dernier paramètre définit le seuil haut. C’est un entier compris entre 0 et 1023 ou 0 et 4095 selon la précision définie lors de l’initialisation du convertisseur (voir 6.2).

6.5.4 Test de condition sur les seuils

La fonction suivante permet de savoir si la condition exprimée lors de la définition de seuils est remplie :

bool testerEtatConvAN(SEUILS)

• La valeur renvoyée est true si la condition est remplie et false sinon.

6.5.5 Récupération de la valeur mesurée

Lorsque la condition de seuils est remplie il est possible de récupérer la dernière mesure par l’une des fonctions décrites en 6.4.4

6.5.6 Exemple

Conversion Analogique/Numérique en mode continu sur l'entrée 0 avec détection de la sortie de l'intervalle [1000, 2000] sur 2 mesures successives :

initConvAN(80, RES12BITS);

choisirEntreeConvAN(0);

activerSeuilsConvAN(0, HORS, 2, 1000, 2000);

declenchementConvAN(PROG_CONTINU);

Pour attendre que 2 mesures successives soient hors de l'intervalle : while (! testerEtatConvAN(SEUILS)) {}

6.6 Acquisition de données sur plusieurs lignes analogiques

Il est parfois nécessaire d’obtenir les valeurs présentes sur plusieurs lignes physiques d’entrées analogiques. Le convertisseur analogique/numérique ne peut effectuer qu’une seule conversion à la fois mais il peut effectuer des conversions successives en changeant automatiquement d’entrée à chaque conversion selon une séquence définie.

(24)

6.6.1 Définition d’une liste d’entrées

Pour donner au convertisseur analogique/numérique une liste d’entrées correspondant à des lignes physiques à mesurer l’une après l’autre on utilise la fonction :

void listeEntreesConvAN(nombre, …)

• Le premier paramètre indique le nombre d’entrées constituant la liste. Il peut prendre des valeurs entre 1 et 14.

• Les paramètres suivants sont les numéros des entrées constituant cette liste, leur nombre doit égal à celui indiqué par le premier paramètre. Les valeurs de ces paramètres sont des entiers entre 0 et 14, toutes ces valeurs doivent être différentes (on ne peut pas convertir plusieurs fois la même entrée dans une liste). Lorsque la conversion sera lancée (voir 6.3) chacune de ces entrées sera mesurée à tour de rôle dans l’ordre défini par ces paramètres. Le temps séparant deux mesures successives est celui défini lors de l’initialisation du convertisseur (voir 6.2).

6.6.2 Test de fin de conversion d’une liste d’entrées

Lorsqu’une salve de mesures a été lancée (voir 6.3), il faut laisser au convertisseur analogique/numérique le temps de transformer les tensions présentes sur chacune des entrées de la liste en valeurs numériques. Cette opération prend, pour chaque entrée de la liste, le temps défini lors de l’initialisation du convertisseur analogique/numérique (voir 6.2). La fonction suivante permet de savoir si la totalité des mesures est disponible :

bool testerEtatConvAN(FIN_SEQUENCE)

• La valeur renvoyée est true si la totalité des mesures est disponible et false sinon.

6.6.3 Récupération des valeurs mesurées

Lorsque la totalité des mesures demandées est disponible (voir 6.6.2) elles peuvent être récupérées par l’une des fonctions suivantes :

int lireListeValeursConverties(table) int lireTensionsConverties(table)

• Le paramètre est un tableau qui recevra les mesures effectuées. La taille de ce tableau doit correspondre à celle de la liste définie (voir 6.6.1).

o Le paramètre de la première fonction est un tableau d’uint16_t. Chaque entrée de ce tableau recevra, dans l’ordre de la liste, la mesure correspondante sous la forme d’un entier compris entre 0 et 1023 ou entre 0 et 4095 selon la précision choisie lors de l’initialisation du convertisseur analogique/numérique (voir 6.2). Ces entiers sont, bien entendu, proportionnels aux tensions présentes sur les entrées lors de la mesure. La valeur de retour de cette fonction est le nombre de mesures effectuées.

o Le paramètre de la seconde fonction est un tableau de réels (float). Chaque entrée de ce tableau recevra, dans l’ordre de la liste, la mesure correspondante en Volts sous la forme d’un réel. La valeur de retour de cette fonction est le nombre de mesures effectuées.

6.6.4 Exemple

Conversion Analogique/Numérique sur les entrées 1 puis 7 puis 0 pilotée par le Timer 0 (toutes les 4s) :

allumerPeriph(Timer0);

timerModeDeclenchement(Timer0, HDIV2, 4*42000000UL, REPETITIF);

allumerPeriph(ConvAN);

(25)

declenchementConvAN(TIMER0);

lancerTimer(Timer0);

Pour attendre que les 3 valeurs soient disponibles : while (! testerEtatConvAN(FIN_SEQUENCE)) {}

Pour récupérer les 3 valeurs : uint32_t tableValeurs[3];

int taille = lireListeTensionsConverties(tableValeurs);

Pour récupérer les 3 valeurs en Volts : float tableTensions[3];

int taille = lireListeTensionsConverties(tableTensions);

6.7 Association de fonctions d’interruption au convertisseur

analogique/numérique

On peut associer à chaque fin de mesure sur une ou sur plusieurs entrées ainsi qu’à chaque obtention d’une condition de seuils une fonction qui sera automatiquement exécutée

6.7.1 Associer une fonction à un événement du convertisseur A/N

L’association d’une fonction d’interruption à un événement du convertisseur analogique/numérique est obtenue par la fonction suivante :

void autoriserITConvAN(cause, priorité, fonction)

• Le premier paramètre indique quel événement provoquera l’exécution de la fonction associée. Il peut prendre les valeurs : FIN_CONV0 à FIN_CONV14 s’il s’agit de la fin d’une mesure sur une entrée liée à une ligne physique, FIN_CONVTEMP s’il s’agit de la fin d’une mesure de température, FIN_SEQUENCE s’il s’agit de la fin de toutes les mesures d’une liste d’entrées et SEUILS s’il s’agit de la vérification d’une condition de seuils sur une entrée.

• Le deuxième paramètre correspond à la préemption de l’interruption. Cette valeur est comprise entre 0 et 15 (0 correspond à la préemption la plus élevée).

• Le dernier paramètre est le nom de la fonction à exécuter lorsque l’événement se produit. Cette fonction ne renvoie aucune valeur (void) et n’accepte aucun paramètre.

La récupération des mesures peut être faite, dans la fonction d’interruption, en utilisant les fonctions décrites, selon le cas, en 6.4.4 ou en 6.6.3.

6.7.2 Supprimer la fonction associée à un événement du convertisseur

A/N

La fonction suivante permet d’enlever la fonction d’interruption associée à un événement du convertisseur :

void interdireITConvAN(cause)

• Le paramètre indique quel événement ne devra plus déclencher d’exécution de fonction d’interruption. Il peut prendre les valeurs : FIN_CONV0 à FIN_CONV14, FIN_CONVTEMP, FIN_SEQUENCE ou SEUILS.

6.7.3 Exemple

Conversion Analogique/Numérique en mode continu sur l'entrée 0 (amplifiée par 2) avec déclenchement d’une fonction d’interruption de préemption 4 lors de la détection de la sortie d’une seule mesure de l'intervalle [1000, 2000] :

(26)

choisirEntreeConvAN(0);

amplificationEntreeConvAN(0, G_2);

declenchementConvAN(PROG_CONTINU);

activerSeuilsConvAN(0, HORS, 1, 1000, 2000);

Puisque l’on est en mode continu, il suffira de lancer une seule fois les conversions par :

demarrerConvAN();

Pour associer une fonction d’interruption de préemption 4 quand la valeur est hors de l'intervalle :

autoriserITConvAN(SEUILS, 4, seuilDepasse);

void seuilDepasse() {

int mesure = lireValeurConvAN(0);

}

7 Générateurs de signaux

Le SAM3X8E possède 8 générateurs de signaux permettant de piloter certains types d’actionneurs comme des servomoteurs. De tels actionneurs sont commandés par une ligne numérique qui change d’état (passe de 0 à 1 et de 1 à 0) à un rythme régulier (période) mais dont la durée de chacun des 2 états est variable. Par exemple, pour une période de 20 ms, si la ligne reste à 0 pendant 18 ms et à 1 pendant 2 ms (soit 10% du temps) l’actionneur réagit de façon différente du cas où la ligne resterait à 0 pendant 9 ms et à 1 pendant 1 ms (soit seulement 5% du temps).

Les générateurs de signaux sont des dispositifs permettant de générer de tels signaux sur des lignes en sortie numérique en choisissant leur période et en faisant varier la durée de l’état 1 (et donc de l’état 0).

7.1 Principes de fonctionnement des générateurs de signaux

La période ainsi que la durée de l’un des états de la ligne numérique sont définis par des entiers (compris entre 0 et 65535) correspondant à un nombre de tops d’horloge comptés par le générateur de signal. L’horloge utilisée pour ce comptage peut être obtenue de deux façons :

o En divisant la fréquence de l’horloge du processeur (84MHz) par 2k avec k entier entre 0 et 10.

o Par construction d’une horloge de fréquence libre choisie entre 332 Hz et 3 MHz.

7.1.1 Précision et période

En fonction de l’horloge choisie pour le comptage, les périodes maximales du signal généré sont indiquées dans le tableau suivant :

Division ou Horloge Temps entre 2 tops Période maximale (Fréquence minimale)

Par 1 1/84 µs 0,78 ms (1 282 Hz) Par 2 1/42 µs 1,56 ms (641 Hz) Par 4 1/21 µs 3,12 ms (320 Hz) Par 8 2/21 µs 6,24 ms (160 Hz) Par 16 4/21 µs 12,48 ms (80 Hz) Par 32 8/21 µs 24,96 ms (40 Hz) Par 64 16/21 µs 49,93 ms (20 Hz) Par 128 32/21 µs 99,86 ms (10 Hz) Par 256 64/21 µs 199,72 ms (5 Hz) Par 512 128/21 µs 399,45 ms (2,5 Hz) Par 1024 256/21 µs 798,88 ms (1 ,25 Hz) Horloge personnalisée 1/3 µs à 3,1 ms 21,84 ms à 203,5 s (45 Hz) à (0,005 Hz)

(27)

7.1.2 Calculs

Pour générer un signal de période θ il faut d’abord choisir un facteur de division de la fréquence de l’horloge du processeur ou opter pour une horloge personnalisée de façon à pouvoir atteindre cette valeur θ. Puis on calculera le nombre de tops d’horloge correspondant exactement à θ ainsi que le nombre de tops d’horloges correspondant à la durée l’un des 2 états de la ligne en sortie numérique (par exemple celle de l’état 1).

Choix du facteur de division ou de l’horloge

On souhaite généralement obtenir la précision maximale. Pour ce faire il conviendra de choisir le facteur de division de la fréquence de l’horloge du processeur de façon à obtenir un temps entre 2 tops minimal (2ème colonne du tableau ci-dessus) mais suffisant (3ème colonne du tableau ci-dessus).

L’utilisation d’une horloge personnalisée peut, dans certains cas, permettre d’obtenir une meilleure précision.

Par exemple pour une période de 20 ms on choisira une division de la fréquence de l’horloge du processeur par 32 puisque les valeurs précédentes ne permettent pas d’atteindre 20 ms (voir 3ème colonne du tableau ci-dessus) et que les valeurs suivantes correspondraient à un temps entre 2 tops plus grand donc à une moins bonne précision (voir 2ème colonne du tableau ci-dessus).

Calcul du nombre de tops d’horloge correspondant à la période et aux états de la ligne

Avec le choix précédent (division par 32) le temps séparant 2 tops d’horloge est de 8/21μs (voir 2ème colonne du tableau ci-dessus).

Une période de 20 ms (20.103μs) correspond donc au comptage de : 21 8

10

20 3

= 52500 tops. Si, par exemple, la ligne doit rester à 1 pendant 1,5 ms (1,5 103μs), cette durée correspondra au

comptage de 21 8 10 5 ,

1 3= 3937 tops (le résultat n’étant pas un entier on l’arrondit à l’entier le

plus proche) et la ligne sera à 0 pendant 52500 - 3937 = 48563 tops d’horloge.

7.2 Lignes physiques liées aux générateurs de signaux

Chaque générateur de signal produit 2 signaux de sortie (sortie directe et sortie inverse) l’un étant toujours l’inverse de l’autre (c’est à dire que quand la sortie directe est dans l’état 0 la sortie inverse est dans l’état 1). Une ou plusieurs lignes physiques peuvent être associées à ces signaux comme indiqué dans le tableau suivant :

Sortie Directe Sortie Inverse Générateur

Port Ligne Fonction Port Ligne Fonction

PortA 8 FONCTIONB PortA 21 FONCTIONB PortB 12 FONCTIONB PortB 16 FONCTIONB GeneSignal0

PortC 3 FONCTIONB PortC 2 FONCTIONB PortA 19 FONCTIONB PortA 12 FONCTIONB PortB 13 FONCTIONB PortB 17 FONCTIONB GeneSignal1

PortC 5 FONCTIONB PortC 4 FONCTIONB PortA 13 FONCTIONB PortA 20 FONCTIONB PortB 14 FONCTIONB PortB 18 FONCTIONB GeneSignal2

PortC 7 FONCTIONB PortC 6 FONCTIONB PortA 9 FONCTIONB PortA 0 FONCTIONB PortB 15 FONCTIONB PortB 19 FONCTIONB GeneSignal3

PortC 9 FONCTIONB PortC 8 FONCTIONB GeneSignal4 PortC 20 FONCTIONB PortC 21 FONCTIONB GeneSignal5 PortC 19 FONCTIONB PortC 22 FONCTIONB GeneSignal6 PortC 18 FONCTIONB PortC 23 FONCTIONB

Références

Documents relatifs

Le livret d’explication des ouvrages s’ouvre ainsi sur la section peinture ; les conseils et avertissements prononcés lors de l’ouverture du Salon et lors de la

Saisir la façon dont est prise en charge aujourd’hui l’architecture produite en situation coloniale par les acteurs du patrimoine invite à élargir la focale d’analyse

F or ea h neighbor entry in the neighbor table, whose link status is not uni-dire tional, a new route entry is re orded in the routing table where destination and next-hop addresses

Cependant, par sa dimension, par sa situation urbaine, par la publicité nationale qui a été donnée à cette opération, modeste en taille (114 logements), mais

When a read request for line X accesses the L2 cache, if this is a miss or a prefetched hit (i.e., the prefetch bit is set), and if X and X + D lie in the same memory page, a

expliquait en disant qu’en cas d’obligation naturelle, le « paiement est une renonciation de fait aux exceptions sans lesquelles l’action eût été admise ;

mystique taoïste développée dans le Dao De Jing.. Mais ce souffle est souvent imperceptible et inaudible pour le commun des mortels. Tout comme Élie sur le mont Horeb, il faut tout

Based on this information and using the theory of quantitative games, we lift most of the linear-time–branching-time spectrum of van Glabbeek [24] to the quantitative setting, while