Table des matières:

Tutoriel Assembleur AVR 7 : 12 étapes
Tutoriel Assembleur AVR 7 : 12 étapes

Vidéo: Tutoriel Assembleur AVR 7 : 12 étapes

Vidéo: Tutoriel Assembleur AVR 7 : 12 étapes
Vidéo: Atmel Studio 7 et langage assembleur 2024, Juillet
Anonim
Tutoriel Assembleur AVR 7
Tutoriel Assembleur AVR 7

Bienvenue dans le didacticiel 7 !

Aujourd'hui, nous allons d'abord montrer comment nettoyer un clavier, puis comment utiliser les ports d'entrée analogiques pour communiquer avec le clavier. Nous le ferons en utilisant des interruptions et un seul fil comme entrée. Nous allons câbler le clavier pour que chaque pression de touche envoie une tension unique à l'entrée analogique qui nous permettra de distinguer par la tension quelle touche a été pressée. Ensuite, nous afficherons le numéro enfoncé dans notre analyseur de registre pour montrer que tout se passe comme il se doit. Il existe un certain nombre de pièges que vous pouvez rencontrer lorsque vous utilisez le convertisseur analogique-numérique (ADC) dans l'ATmega328p et nous allons donc prendre les choses en quelques étapes sur le chemin pour essayer de comprendre comment les éviter. Nous verrons également pourquoi l'utilisation du convertisseur analogique-numérique n'est pas la meilleure façon de contrôler un clavier même s'il utilise moins de ports sur votre microcontrôleur. Dans ce tutoriel, vous aurez besoin de:

  1. un clavier. Vous pouvez en acheter un ou vous pouvez faire ce que j'ai fait et en récupérer un.
  2. 2 en-têtes femelles pour le clavier (si vous en récupérez un)
  3. fils de connexion
  4. une planche à pain
  5. 4 résistances 1 Kohm
  6. 1 résistance de 15 Kohms
  7. 1 résistance de 3,3 Kohms
  8. 1 résistance de 180 ohms
  9. 1 résistance de 680 ohms
  10. un multimètre numérique
  11. votre analyseur du Tutoriel 5

Vous voudrez peut-être sauter les premières étapes si vous avez déjà un clavier et que vous n'avez pas besoin d'en récupérer un.

Voici un lien vers la collection complète de mes tutoriels d'assembleur AVR:

Étape 1: récupérer un clavier 1

Récupérer un clavier 1
Récupérer un clavier 1
Récupérer un clavier 1
Récupérer un clavier 1
Récupérer un clavier 1
Récupérer un clavier 1
Récupérer un clavier 1
Récupérer un clavier 1

Il y a longtemps, quand même vos grands-parents n'étaient que de simples enfants, les gens utilisaient ces appareils étranges, qui avaient de longs câbles branchés au mur, pour communiquer entre eux. Ils s'appelaient "téléphones" et étaient généralement des objets en plastique bon marché qui faisaient un bruit agaçant lorsque quelqu'un vous appelait (pas que les sonneries "Justin Bieber" d'aujourd'hui ne soient pas aussi ennuyeuses). Dans tous les cas, ces appareils avaient des claviers qui étaient très simplement câblés et sont donc faciles à récupérer et ils ont 2 touches supplémentaires sur eux ("recomposer" et "flash") des claviers que vous pouvez acheter que vous voudrez peut-être réutiliser comme "touches fléchées", "touches de menu", ou autre chose. Nous allons donc commencer par récupérer un clavier d'un ancien téléphone. Prenez d'abord le téléphone (j'utilise un GE comme indiqué sur les photos) et soulevez-le pour révéler le câblage. Ensuite, prenez un ciseau et retirez les petits boutons en plastique qui maintiennent le clavier et retirez le clavier.

Étape 2: récupérer un clavier 2

Récupérer un clavier 2
Récupérer un clavier 2
Récupérer un clavier 2
Récupérer un clavier 2
Récupérer un clavier 2
Récupérer un clavier 2

Maintenant, prenez une scie à PVC et coupez le plastique autour des trous de serrure, puis coupez autour du bord pour obtenir la bonne profondeur en laissant un clavier fin.

Remettez ensuite le clavier en place à l'aide des petites chevilles qui restent après avoir coupé les sommets lors de la dernière étape et utilisez un fer à souder pour simplement enfoncer le fer chaud dans chaque trou de cheville, ce qui fera fondre le plastique et l'étalera sur le bas du clavier formant de nouveaux "boutons" qui maintiendront le clavier en place comme avant.

J'aime récupérer les trois haut-parleurs et peut-être les autres choses comme les commutateurs et autres qui sont sur la carte. Cependant, cette fois, je ne vais pas nettoyer les interrupteurs et tout ça parce que nous avons d'autres objectifs pour le moment. En outre, il y a un circuit intégré linéaire TA31002 qui est une sonnerie de téléphone. La fiche technique est facile à trouver et à télécharger en ligne, donnant le brochage et les fonctionnalités. Je vais donc le laisser soudé à la carte pour le moment et jouer avec plus tard. J'aimerais le brancher à un oscilloscope et voir quels signaux sympas je peux en tirer. Peut-être même en faire une sonnette. Qui sait.

Quoi qu'il en soit, une fois que vous avez fini de détruire le téléphone et de récupérer les pièces, nous finirons de fabriquer notre clavier.

Étape 3: récupérer un clavier 3

Récupérer un clavier 3
Récupérer un clavier 3
Récupérer un clavier 3
Récupérer un clavier 3
Récupérer un clavier 3
Récupérer un clavier 3

Utilisez une mèche à dessouder et retirez les câbles plats du bas du clavier en vous assurant que les trous de la carte de circuit imprimé sont dégagés, puis fixez deux embases femelles sur la carte où se trouvent les trous. Vous devrez probablement couper vos en-têtes pour qu'ils soient des en-têtes à 4 broches.

Maintenant que les en-têtes sont attachés, vous pouvez le connecter à une planche à pain, prendre un multimètre et tester les touches en collant le multimètre sur des broches aléatoires et en mesurant la résistance. Cela vous permettra de tracer les clés. Il est difficile de voir comment les touches sont câblées aux sorties en regardant le circuit, mais si vous utilisez un multimètre, vous pouvez le brancher sur deux broches quelconques, puis appuyez sur les boutons jusqu'à ce que vous voyiez un numéro à l'écran au lieu d'un circuit ouvert. Ce sera le brochage de cette clé.

Mappez toutes les clés sur les broches de sortie de cette manière.

Étape 4: câbler le clavier

Câbler le clavier
Câbler le clavier
Câbler le clavier
Câbler le clavier

Suivez maintenant le schéma de câblage et connectez le clavier à votre maquette.

Comment cela va fonctionner est que nous allons mettre 5V sur le côté gauche et le côté droit va à GND. La première broche à droite du schéma va dans la première de nos broches analogiques sur le microcontrôleur Atmega328p. Lorsqu'aucun bouton n'est enfoncé, le signal sera de 0 V, et lorsque chacun des différents boutons est enfoncé, l'entrée vers le port analogique se situera entre 0 V et 5 V avec une quantité différente selon la touche qui a été enfoncée. Nous avons choisi les valeurs de résistance de sorte que chaque chemin contienne une résistance différente du reste. Le port analogique du microcontrôleur prend un signal analogique et le divise en 1024 canaux différents entre 0V et 5V. Cela signifie que chaque canal a une largeur 5V/1024 = 0,005 V/canal = 5 mV/canal. Ainsi, le port analogique peut distinguer les tensions d'entrée tant qu'elles diffèrent de plus de 5 mV. Dans notre cas, nous avons choisi des valeurs de résistance de sorte que deux pressions de touche enverront un signal de tension qui diffère de plus que cela afin que le microcontrôleur puisse facilement décider quelle touche a été enfoncée. Le gros problème est que l'ensemble du système est très bruyant, nous devrons donc choisir une plage de tensions à mapper à chaque pression de bouton - mais nous y reviendrons un peu plus tard.

Notez que nous sommes en mesure de contrôler un clavier à 14 boutons en utilisant une seule ligne d'entrée vers le contrôleur. C'est l'un des aspects utiles des entrées analogiques.

Maintenant, notre première tentative pour contrôler le clavier sera de faire en sorte qu'une pression sur une touche provoque une interruption, le sous-programme d'interruption lira le port d'entrée analogique et décidera quelle touche a été enfoncée, puis il enverra ce numéro à notre sous-programme d'analyseur de registre qui affichera le valeur clé en binaire sur nos 8 LED que nous avons mis en place dans le Tutoriel 5.

Étape 5: câblez le clavier à votre analyseur

Connectez le clavier à votre analyseur
Connectez le clavier à votre analyseur
Connectez le clavier à votre analyseur
Connectez le clavier à votre analyseur

Les images montrent comment nous voulons connecter le clavier au microcontrôleur afin que nous puissions voir la sortie sur l'écran de notre analyseur. Essentiellement, nous connectons simplement la sortie du clavier à la broche 0 du PortC, également appelée ADC0 sur l'ATmega328P.

Cependant, il y a quelques choses supplémentaires. Nous allons également câbler un bouton au PD2. C'est à dire. prenez un fil de votre rail 5V à un bouton et de l'autre côté du bouton à PD2, et enfin, nous voulons déconnecter la broche AREF de notre rail 5V et la laisser déconnectée à la place. Nous pourrions insérer un condensateur de découplage de 0,1 microfarad si nous le voulions. Il s'agit d'un condensateur céramique avec un 104 écrit dessus. Les deux premiers chiffres sont le nombre et le dernier chiffre est la puissance de 10 que nous multiplions par pour obtenir une réponse en picofarads (pico signifie 10^-12), donc 104 signifie 10 x 10^4 picofarads, ce qui est le même que 100 nanofarads (nano signifie 10^-9), ce qui équivaut à 0,1 microfarads (micro signifie 10^-6). Quoi qu'il en soit, tout cela ne fait que stabiliser la broche AREF lorsque nous pouvons l'utiliser comme broche de référence.

Nous voulons également une résistance de 1 Mohm entre PD2 et la masse. Nous allons définir PD2 comme broche de sortie à 0V et nous déclencherons sur un front positif sur cette broche. Nous voulons que le bord disparaisse immédiatement lorsque nous relâchons le bouton, nous insérons donc cette résistance "pull down".

La raison pour laquelle nous voulons le bouton est que nous voulons déclencher notre convertisseur analogique-numérique à partir de la broche INT0 de la puce, qui est également PD2. Finalement, nous aimerions que la pression sur la touche déclenche à la fois l'ADC et fournisse également l'entrée à convertir sans avoir de bouton séparé, mais en raison de la façon dont fonctionne le chronométrage, nous commencerons par avoir un bouton séparé pour déclencher l'ADC et une fois que nous aurons tout repassé les bugs et sommes convaincus que tout fonctionne correctement, alors nous allons nous attaquer aux problèmes de bruit et de synchronisation qui viennent avec le déclenchement de la même pression sur le bouton que nous voulons lire.

Donc, pour l'instant, la façon dont cela fonctionne est de maintenir une touche enfoncée, puis d'appuyer sur le bouton pour déclencher l'ADC, puis de relâcher et, espérons-le, la valeur binaire du bouton que nous avons enfoncé apparaîtra sur l'analyseur.

Alors écrivons du code qui accomplira cela.

Étape 6: quels interrupteurs à bascule devons-nous définir ?

Quels interrupteurs à bascule devrions-nous définir ?
Quels interrupteurs à bascule devrions-nous définir ?

Pensons d'abord à la façon dont nous allons coder cela afin que le contrôleur puisse lire l'entrée du clavier et la transformer en une valeur numérique correspondant au bouton qui a été enfoncé. Nous allons utiliser le convertisseur analogique-numérique (ADC) qui est intégré à l'Atmega328p. Nous utiliserons AREF comme tension de référence et la sortie de notre clavier sera connectée à PortC0 ou PC0. Notez que cette broche est également appelée ADC0 pour Analog-to-Digital Converter 0. Ce pourrait être une bonne idée pour vous de lire la section 12.4 sur les interruptions pour l'ATmega328P et également le chapitre 24 sur le convertisseur analogique-numérique avant d'obtenir commencé ou au moins avoir ces sections prêtes pour référence. Afin de configurer le microcontrôleur afin qu'il sache quoi faire avec un signal d'entrée analogique et comment interagir avec notre programme, nous devons d'abord définir quelques-uns des différents ADC bits de registre associés. Ceux-ci sont essentiellement équivalents aux anciens interrupteurs à bascule sur les premiers ordinateurs. Soit vous allumez ou éteignez un interrupteur, soit encore plus en arrière, vous branchez des câbles entre une prise et une autre afin que les électrons atteignant cette fourche sur la route trouvent une porte fermée et une autre ouverte, la forçant à emprunter un chemin différent dans le labyrinthe de circuits et ainsi effectuer une tâche logique différente. Lors du codage en langage assembleur, nous avons un accès proche à ces fonctions du microcontrôleur, ce qui est l'une des choses intéressantes à faire en premier lieu. C'est plus "pratique" et beaucoup moins se passe "dans les coulisses" pour ainsi dire. Ne pensez donc pas à régler ces registres comme une tâche fastidieuse. C'est ce qui rend le langage assembleur intéressant ! Nous gagnons une relation très personnelle avec le fonctionnement interne et la logique de la puce et nous la faisons faire exactement ce que nous voulons qu'elle fasse - ni plus ni moins. Pas de cycles d'horloge gaspillés. Voici donc une liste des commutateurs que nous devons régler:

  1. Désactivez le bit de réduction de puissance ADC, PRADC, qui est le bit 0 du registre PRR, car si ce bit est activé, il arrêtera l'ADC. Le registre de réduction de puissance est essentiellement un moyen de couper diverses choses qui utilisent de l'énergie lorsque vous n'en avez pas besoin. Puisque nous utilisons l'ADC, nous voulons nous assurer qu'il n'est pas désactivé de cette manière. (Voir PRADC à la page 46)
  2. Sélectionnez le canal d'entrée analogique à ADC0 en désactivant MUX3…0 dans le registre de sélection du multiplexeur ADC (ADMUX) (voir tableau 24-4 page 249) ceux-ci sont déjà désactivés par défaut, nous n'avons donc pas vraiment besoin de le faire. Cependant, je l'inclus car si vous utilisez un port autre que ADC0, vous devrez basculer ces commutateurs en conséquence. Diverses combinaisons de MUX3, MUX2, MUX1, MUX0 vous permettent d'utiliser l'un des ports analogiques comme entrée et vous pouvez également les modifier à la volée si vous souhaitez regarder un tas de signaux analogiques différents à la fois.
  3. Désactivez les bits REFS0 et REFS1 dans le registre ADMUX afin que nous utilisions AREF comme tension de référence plutôt que comme référence interne (Voir page 248).
  4. Activez le bit ADLAR dans ADMUX pour que le résultat soit "ajusté à gauche", nous discuterons de ce choix à l'étape suivante.
  5. Définissez le bit ADC0D dans le registre de désactivation d'entrée numérique (DIDR0) pour désactiver l'entrée numérique sur PC0. Nous utilisons ce port pour l'entrée analogique, nous pourrions donc aussi bien désactiver l'entrée numérique pour cela.
  6. Réglez ISC0 et ISC1 dans le registre de contrôle d'interruption externe A (EICRA) pour indiquer que nous voulons déclencher sur le front montant d'un signal de tension vers la broche INT0 (PD2), voir page 71.
  7. Effacez les bits INT0 et INT1 dans le registre de masque d'interruption externe (EIMSK) pour indiquer que nous n'utilisons pas d'interruptions sur cette broche. Si nous devions activer les interruptions sur cette broche, nous aurions besoin d'un gestionnaire d'interruptions à l'adresse 0x0002, mais à la place, nous le configurons de sorte qu'un signal sur cette broche déclenche la conversion ADC, dont l'achèvement est géré par l'interruption complète de la conversion ADC à adresse 0x002A. Voir page 72.
  8. Réglez le bit d'activation de l'ADC (ADEN) (bit 7) dans le registre de contrôle et d'état ADC (ADCSRA) pour activer l'ADC. Voir page 249.
  9. Nous pourrions démarrer une seule conversion en définissant le bit de conversion de démarrage ADC (ADSC) à chaque fois que nous voulions lire le signal analogique, cependant, pour l'instant, nous préférerions qu'il soit lu automatiquement chaque fois que quelqu'un appuie sur le bouton, donc à la place, nous allons activer l'ADC Bit d'activation du déclenchement automatique (ADATE) dans le registre ADCSRA afin que le déclenchement se fasse automatiquement.
  10. Nous avons également défini les bits ADPS2..0 (les bits AD Prescalar) sur 111 afin que l'horloge ADC soit l'horloge CPU divisée par un facteur de 128.
  11. Nous sélectionnerons la source du déclenchement ADC pour être PD2 qui est également appelé INT0 (External Interrupt Request 0). Nous faisons cela en basculant les différents bits dans le registre ADCSRB (Voir Tableau 24-6 à la page 251). Nous voyons par le tableau que nous voulons désactiver ADTS0, ADTS1 activé et ADTS2 désactivé afin que l'ADC se déclenche sur cette broche. Notez que si nous voulions échantillonner en continu le port analogique comme si nous lisions un signal analogique continu (comme un échantillonnage sonore ou quelque chose du genre), nous le définirions en mode de fonctionnement libre. La méthode que nous utilisons pour définir le déclenchement sur PD2 déclenche une lecture ADC du port analogique PC0 sans provoquer d'interruption. L'interruption surviendra lorsque la conversion sera terminée.
  12. Activez le bit d'activation d'interruption ADC (ADIE) dans le registre ADCSRA de sorte que lorsque la conversion analogique-numérique est terminée, il génère une interruption pour laquelle nous pouvons écrire un gestionnaire d'interruption et la placer sur.org 0x002A.
  13. Définissez le bit I dans SREG pour activer les interruptions.

Exercice 1: Assurez-vous de lire les sections pertinentes de la fiche technique pour chacun des paramètres ci-dessus afin de comprendre ce qui se passe et ce qui se passerait si nous les modifiions en paramètres alternatifs.

Étape 7: écrivez le gestionnaire d'interruption

Dans la dernière étape, nous avons vu que nous l'avons configuré pour qu'un front montant détecté sur PD2 déclenche une conversion analogique-numérique sur PC0 et lorsque cette conversion est terminée, une interruption ADC Conversion Complete est déclenchée. Maintenant, nous voulons faire quelque chose avec cette interruption. Si vous examinez le Tableau 12-6 à la page 65, vous verrez une liste des interruptions possibles. Nous avons déjà vu l'interruption RESET à l'adresse 0x0000 et l'interruption Timer/Counter0 Overflow à l'adresse 0x0020 dans les didacticiels précédents. Maintenant, nous voulons regarder l'interruption ADC que nous voyons par le tableau est à l'adresse 0x002A. Ainsi, au début de notre code en langage assembleur, nous aurons besoin d'une ligne indiquant:

.org 0x002Arjmp ADC_int

qui sautera à notre gestionnaire d'interruption étiqueté ADC_int chaque fois que l'ADC aura terminé une conversion. Alors, comment devrions-nous écrire notre gestionnaire d'interruptions ? La façon dont fonctionne l'ADC consiste à effectuer le calcul suivant:

ADC = Vin x 1024 / Vref

Voyons donc ce qui se passe si j'appuie sur le bouton "renuméroter" du clavier. Dans ce cas, la tension sur PC0 passera à une certaine valeur, disons 1,52 V, et puisque Vref est à 5 V, nous aurons:

CAN = (1,52 V) x 1024 / 5 V = 311,296

et donc il apparaîtrait comme un 311. Si nous voulions reconvertir cela en une tension, nous inverserions simplement le calcul. Cependant, nous n'aurons pas besoin de le faire car nous ne sommes pas intéressés par les tensions réelles simplement pour les distinguer. Lorsque la conversion est terminée, le résultat est stocké dans un nombre de 10 bits placé dans les registres ADCH et ADCL et nous l'avons fait "ajuster à gauche", ce qui signifie que les 10 bits commencent au bit 7 de ADCH et descendent jusqu'à bit 6 de l'ADCL (il y a 16 bits au total dans ces deux registres et nous n'en utilisons que 10, soit 1024 canaux). Nous pourrions avoir le résultat "ajusté à droite" si nous le voulions en effaçant le bit ADLAR dans le registre ADMUX. ne sont probablement que du bruit, nous distinguerons donc les touches en utilisant uniquement les 8 chiffres supérieurs. registre, convertissez ce nombre en une valeur de clavier, puis envoyez cette valeur aux LED de notre analyseur de registre afin que nous puissions vérifier que le fait d'appuyer sur un "9" par exemple entraînera l'allumage des LED correspondant à "00001001". loin, nous devons d'abord voir ce qui apparaît dans ADCH lorsque nous appuyons sur les différents boutons. Écrivons donc un simple gestionnaire d'interruptions qui envoie simplement le contenu de ADCH à l'écran de l'analyseur. Voici donc ce dont nous avons besoin:

ADC_int:lds analyzer, ADCH;charge la valeur de ADCH dans nos analyseursbi EIFR, 0; effacer l'indicateur d'interruption externe afin qu'il soit prêt à recommencer

À présent, vous devriez être en mesure de copier simplement le code de notre analyseur dans le didacticiel 5 et d'ajouter cette interruption et les paramètres de basculement et de l'exécuter. Exercice 2: Écrivez le code et exécutez-le. Assurez-vous que l'ADCH s'affiche sur l'écran de votre analyseur. Essayez d'appuyer plusieurs fois sur la même touche. Obtenez-vous toujours la même valeur en ADCH ?

Étape 8: mapper les valeurs des touches

Cartographier les valeurs des touches
Cartographier les valeurs des touches

Ce que nous devons faire maintenant, c'est convertir les valeurs dans ADCH en nombres correspondant à la touche qui a été enfoncée. Pour ce faire, nous écrivons le contenu de ADCH pour chaque pression de touche, puis nous le convertissons en un nombre décimal comme je l'ai fait sur l'image. Dans notre routine de gestion des interruptions, nous considérerons toute une plage de valeurs comme correspondant à chaque pression de touche afin que l'ADC mappe tout ce qui se trouve dans cette plage à une pression de touche donnée.

Exercice 3: faites ce mappng, puis réécrivez votre routine d'interruption ADC.

Voici ce que j'ai obtenu pour le mien (le vôtre sera très probablement différent). Notez que je l'ai configuré avec une plage de valeurs pour chaque pression de touche.

ADC_int:; Analyseur clr de gestionnaire d'interruption externe; se préparer pour les nouveaux nombres buttonH, ADCH; ADC se met à jour lorsque ADCH est lu clccpi buttonH, 240brlo PC+3; si ADCH est plus gros alors c'est un analyseur 1ldi, 1; donc chargez l'analyseur avec un retour 1rjmp; et retour clccpi boutonH, 230; si ADCH est plus gros alors un analyseur 2brlo PC+3ldi, 2rjmp retour clccpi boutonH, 217brlo PC+3ldi analyseur, 3rjmp retour bouton clccpiH, 203brlo PC+3ldi analyseur, 4rjmp retour bouton clccpiH, 187brlo PC+3ldi analyseur, 5rjmp, retour clccpi boutonH 155brlo PC+3ldi analyseur, 6rjmp retour clccpi boutonH, 127brlo PC+3ldi analyseur, 255; nous allons définir le flash comme tout le bouton clccpi de retour onrjmpH, 115brlo PC + analyseur 3ldi, bouton 7rjmp retour clccpiH, 94brlo PC + analyseur 3ldi, 8rjmp retour bouton clccpiH, 62brlo PC + analyseur 3ldi, 9rjmp retour bouton clccpiH, 37brlo PC + analyseur 3ldi, 0b11110000; l'astérisque est la moitié supérieure onrjmp return clccpi buttonH, 28brlo PC+3ldi analyzer, 0rjmp return clccpi buttonH, 17brlo PC+3ldi analyseur, 0b00001111; le signe dièse est la moitié inférieure onrjmp return clccpi buttonH, 5brlo PC+3ldi analyzer, 0b11000011; la recomposition est top 2 bottom 2rjmp return analyseur ldi, 0b11011011; sinon une erreur s'est produite return:reti

Étape 9: Code et vidéo pour la version 1

J'ai joint mon code pour cette première version du pilote de clavier. Dans celui-ci, vous devez appuyer sur la touche puis sur le bouton pour que l'ADC lise l'entrée du clavier. Ce que nous préférerions, ce serait l'absence de bouton, mais le signal pour effectuer la conversion provient de la touche elle-même. Exercice 3: Assemblez et téléchargez ce code et essayez-le. Vous devrez peut-être modifier les différents seuils de conversion pour qu'ils correspondent à vos tensions de pression de touche, car ils diffèrent probablement des miens. Que se passe-t-il si vous essayez d'utiliser une entrée du clavier à la fois pour l'ADC0 et pour la broche d'interruption externe au lieu de passer par un bouton ? Je joindrai également une vidéo du fonctionnement de cette première version de notre pilote de touche. Vous remarquerez que dans mon code, il y a une section initialisant le pointeur de pile. Il existe différents registres que nous pouvons vouloir pousser et extraire de la pile lorsque nous manipulons des variables et autres et il y a aussi des registres que nous pouvons vouloir sauvegarder et restaurer plus tard. Par exemple, SREG est un registre qui n'est pas conservé entre les interruptions, de sorte que les divers indicateurs définis et effacés à la suite d'opérations peuvent être modifiés si une interruption se produit au milieu de quelque chose. Il est donc préférable d'insérer SREG dans la pile au début d'un gestionnaire d'interruption, puis de le retirer à la fin du gestionnaire d'interruption. Je l'ai placé dans le code pour montrer comment il est initialisé et pour anticiper comment nous en aurons besoin plus tard, mais comme nous ne nous soucions pas de ce qui arrive à SREG pendant les interruptions dans notre code, je n'ai pas utilisé la pile pour cela. Remarquez également que j'ai utilisé l'opération de décalage pour définir divers bits dans les registres lors de l'initialisation. Par exemple dans la ligne:

température ldi, (1<> st EICRA, temp

La commande "<<" dans la première ligne de code ci-dessus est une opération de décalage. Il prend essentiellement le nombre binaire 1, qui est 0b00000001 et le décale vers la gauche du montant du nombre ISC01. C'est la position du bit nommé ISC01 dans le registre EICRA. Étant donné que ISC01 est le bit 1, le numéro 1 est décalé vers la position 1 à gauche pour devenir 0b0000010. De même, le second, ISC00, est le bit 0 de EICRA et donc le décalage du nombre 1 est de zéro position vers la gauche. Si vous regardez à nouveau le fichier m328Pdef.inc que vous avez téléchargé dans le premier tutoriel et que vous utilisez evrr depuis, vous verrez qu'il ne s'agit que d'une longue liste d'instructions ".equ". Vous constaterez que ISC01 est égal à 1. L'assembleur remplace chaque instance par 1 avant même de commencer à assembler quoi que ce soit. Ce ne sont que des noms pour les bits de registre pour nous aider, les humains, à lire et à écrire du code. Maintenant, la ligne verticale entre les deux opérations de décalage ci-dessus est une opération "ou" logique. Voici l'équation:

0b0000010 | 0b00000001 = 0b00000011

et c'est ce que nous chargeons (en utilisant "ldi") dans temp. La raison pour laquelle les gens utilisent cette méthode pour charger des valeurs dans un registre est qu'elle permet d'utiliser le nom du bit au lieu d'un simple nombre, ce qui rend le code beaucoup plus facile à lire. Nous avons également utilisé deux autres techniques. Nous utilisons les instructions "ori" et "andi". Ceux-ci nous permettent respectivement de SET et de CLEAR sans changer aucun des autres bits d'un registre. Par exemple, lorsque j'ai utilisé

ori temp, (1

ce "ou" s temp avec 0b0000001 qui met un 1 dans le bit zéro et laisse tout le reste inchangé. Aussi quand nous avons écrit

andi temp, 0b11111110

cela change le bit zéro de temp à 0 et laisse tout le reste inchangé.

Exercice 4: Vous devez parcourir le code et vous assurer que vous comprenez chaque ligne. Vous trouverez peut-être intéressant de trouver de meilleures méthodes pour faire les choses et d'écrire un meilleur programme. Il existe une centaine de façons de coder les choses et je suis assez confiant que vous pouvez trouver une bien meilleure façon que la mienne. Vous pouvez également trouver (à Dieu ne plaise !) des erreurs et des omissions. Dans ce cas, j'aimerais bien en entendre parler afin qu'ils puissent être corrigés.

Bon, voyons maintenant si nous pouvons nous débarrasser de ce bouton superflu…

Étape 10: Coder pour la version 2

Le moyen le plus simple de se débarrasser du bouton est simplement de le supprimer complètement, d'oublier l'entrée de PB2 et de simplement basculer l'ADC en "Mode de fonctionnement libre".

En d'autres termes, modifiez simplement le registre ADCSRB de sorte que ADTS2, ADTS1 et ADTS0 soient tous des zéros.

Réglez ensuite le bit ADSC dans ADCSRA sur 1 qui lancera la première conversion.

Maintenant, téléchargez-le sur votre microcontrôleur et vous constaterez que le bon numéro s'affiche à l'écran pendant que vous appuyez sur le bouton et uniquement pendant que vous appuyez sur le bouton. C'est parce que l'ADC échantillonne en continu le port ADC0 et affiche la valeur. Lorsque vous retirez votre doigt du bouton, le « rebond du bouton » entraînera l'apparition très rapide de quelques valeurs aléatoires, puis il reviendra à l'entrée 0 V. Dans notre code, nous avons ce 0V apparaissant comme 0b11011011 (car la touche '0' utilise déjà la valeur d'affichage 0b00000000)

Ce n'est pas la solution que nous voulons cependant pour deux raisons. Premièrement, nous ne voulons pas avoir à maintenir le bouton enfoncé. Nous voulons appuyer une fois dessus et afficher le numéro (ou utilisé dans un nouveau code dans un tutoriel ultérieur). Deuxièmement, nous ne voulons pas continuellement échantillonner l'ADC0. Nous voulons qu'il prenne une seule lecture, le convertisse, puis se met en veille jusqu'à ce qu'une nouvelle pression de touche déclenche une nouvelle conversion. Le mode de fonctionnement libre est préférable si la seule chose que vous voulez que le microcontrôleur fasse est de lire en permanence une entrée analogique - comme si vous vouliez afficher les températures en temps réel ou quelque chose du genre.

Alors trouvons encore une autre solution…

Étape 11: Comment se débarrasser du bouton ? Version 3

Comment se débarrasser du bouton ? Version 3
Comment se débarrasser du bouton ? Version 3

Il existe de nombreuses façons de procéder. D'abord, nous pourrions ajouter du matériel pour se débarrasser du bouton. Par exemple, nous pouvons essayer de mettre un transistor dans le circuit à la ligne de sortie de la pression de touche afin qu'il prenne un petit filet du courant de la sortie et envoie une impulsion de 5 V à la broche d'interruption PD2.

Cependant, ce serait probablement au moins trop bruyant et au pire, cela ne laisserait pas assez de temps pour une lecture précise des touches, car la tension de sortie du clavier n'aurait pas le temps de se stabiliser avant que la lecture ADC ne soit capturée.

Nous préférons donc trouver une solution logicielle. Ce que nous aimerions faire, c'est ajouter une interruption sur la broche PD2 et écrire un gestionnaire d'interruption pour celle-ci qui appelle une seule lecture de la broche du clavier. En d'autres termes, nous nous débarrassons de l'interruption de déclenchement automatique de l'ADC et ajoutons une interruption externe qui appelle l'ADC à l'intérieur. De cette façon, le signal pour lire l'ADC arrive après que le signal PD2 s'est déjà produit et cela peut donner suffisamment de temps aux choses pour se stabiliser à une tension précise avant que la broche PC0 ne soit lue et convertie. Nous aurions toujours une interruption d'achèvement ADC qui afficherait le résultat sur l'écran de l'analyseur à la fin.

Avoir du sens ? Eh bien, faisons-le…

Jetez un œil au nouveau code ci-joint.

Vous voyez les changements suivants:

  1. Nous avons ajouté un rjmp à l'adresse.org 0x0002 pour gérer l'interruption externe INT0
  2. Nous avons modifié le registre EIMSK pour indiquer que nous voulons interrompre sur la broche INT0
  3. Nous avons modifié la broche ADATE dans le registre ADCSRA pour désactiver le déclenchement automatique
  4. Nous nous sommes débarrassés des paramètres ADCSRB car ils ne sont pas pertinents lorsque ADATE est désactivé
  5. Nous n'avons plus à réinitialiser l'indicateur de déclenchement externe puisque la routine d'interruption INT0 le fait automatiquement lorsqu'elle se termine - auparavant, nous n'avions pas de routine d'interruption, nous déclenchions simplement l'ADC à partir d'un signal sur cette broche, nous devions donc effacer ce drapeau à la main.

Maintenant, dans le gestionnaire d'interruption, nous appelons simplement une conversion unique à partir de l'ADC.

Exercice 5: Exécutez cette version et voyez ce qui se passe.

Étape 12: Code et vidéo pour la version de travail

Comme nous l'avons vu dans la dernière version, l'interruption du bouton ne fonctionne pas très bien car l'interruption est déclenchée sur un front montant vers la broche PD2 puis le gestionnaire d'interruption appelle la conversion ADC. Cependant, l'ADC obtient alors la lecture de la tension avant qu'elle ne se soit stabilisée et lit donc un non-sens.

Ce dont nous avons besoin, c'est d'introduire un délai entre l'interruption sur PD2 et la lecture ADC sur PC0. Pour ce faire, nous ajouterons un temporisateur/compteur, une interruption de débordement de compteur et une routine de délai. Heureusement, nous savons déjà comment faire cela à partir du didacticiel 3 ! Nous allons donc simplement copier et coller le code pertinent à partir de là.

J'ai donné le code résultant et une vidéo le montrant en fonctionnement.

Vous remarquerez que les lectures ne sont pas aussi précises qu'on pourrait l'espérer. Cela est probablement dû à un certain nombre de sources:

  1. nous tapons sur la sortie de tension du clavier pour déclencher sur PD2 ce qui affecte la lecture dans PC0.
  2. nous ne savons pas vraiment combien de temps attendre après le déclenchement pour obtenir la meilleure lecture.
  3. il faut quelques cycles pour que la conversion ADC se termine, ce qui signifie que nous ne pouvons pas tirer rapidement sur le clavier.
  4. il y a probablement du bruit dans le clavier lui-même.
  5. etc…

Ainsi, bien que nous ayons réussi à faire fonctionner le clavier et que nous puissions maintenant l'utiliser dans des applications en utilisant les valeurs des touches d'une autre manière au lieu de simplement les afficher sur l'écran de l'analyseur, ce n'est pas très précis et c'est très ennuyeux. C'est pourquoi je pense que la meilleure façon de câbler les claviers est simplement de coller chaque sortie du clavier dans un port différent et de décider quelle touche est enfoncée par quels ports voient une tension. C'est facile, très rapide et très précis.

En fait, il n'y a que deux raisons pour lesquelles on voudrait piloter un clavier comme nous l'avons fait ici:

  1. Il n'utilise que 2 des broches de notre microcontrôleur au lieu de 8.
  2. C'est un excellent projet de montrer différents aspects de l'ADC sur le microcontrôleur qui est différent des choses standard que vous pouvez y trouver comme les lectures de température, les potentiomètres tournants, etc. Je voulais un exemple de lectures uniques déclenchées et de déclenchement automatique de broche externe plutôt qu'un simple mode d'engloutissement du processeur.

Quoi qu'il en soit, voici quelques derniers exercices pour vous:

Exercice 6: réécrivez le gestionnaire d'interruption de conversion ADC complète pour utiliser une table de consultation. C'est à dire. Pour qu'il teste la valeur analogique avec le premier élément de la table et si elle est plus grande, elle revient de l'interruption, si ce n'est pas le cas, elle incrémente Z à l'élément suivant dans la table et revient au test. Cela raccourcira le code et nettoiera la routine d'interruption et la rendra plus agréable. (Je donnerai une solution possible à l'étape suivante) Exercice 7: Connectez votre clavier à 8 broches sur le microcontrôleur et écrivez le pilote simple pour celui-ci et découvrez à quel point il est plus agréable. Pouvez-vous penser à quelques façons d'améliorer le fonctionnement de notre méthode ?

C'est tout pour ce tuto. J'ai joint la version finale avec des pointeurs. Alors que nous nous rapprochons de notre objectif final, nous utiliserons à nouveau le clavier dans le didacticiel 9 pour montrer comment contrôler sept affichages de segment avec lui (et construire quelque chose d'intéressant qui utilise les touches supplémentaires du clavier du téléphone), puis nous allons passez plutôt au contrôle des choses en appuyant sur des boutons (puisque cette méthode correspond mieux au produit final que nous visons avec ces didacticiels) et nous allons simplement mettre le clavier de côté.

À la prochaine!

Conseillé: