Tutoriel d’assembleur AVR 4 (6 / 9 étapes)

Étape 6: Pointeurs et Tables de choix

Quelqu'un d'entre vous qui ont une expérience à l’aide de C ou C++ déjà ont l’expérience des pointeurs. Nous utiliserons la même chose ici, dans le cadre des « tables de choix ».

Tables de recherche sont une autre façon de compactifying notre code pour le rendre plus court, plus élégant et plus facile à comprendre.

Tout d’abord permet d’écrire le code et puis nous allons expliquer ce qui se passe. Tout d’abord, en haut de notre programme, nous aurons une section intitulée "numéros:" suivie de certaines directives d’assembleur « .db ». Ces directives « define octets » et ce qu’ils font, c’est qu’ils placent ces octets dans l’ordre dans une certaine partie de « La mémoire de programme » définie par les numéros d’étiquettes. Afin que lorsque le code hexadécimal est chargé sur le microcontrôleur, un certain segment de la mémoire flash qui stocke toutes les instructions de programme contiendra ces octets un après l’autre dans l’ordre.

Puis nous pouvons obtenir réellement ces chiffres chaque fois que nous voulons qu’ils puisqu’ils seront toujours situés à certains emplacements de mémoire de programme spécifié. Rappelez-vous comment nous avons traité avec les interruptions ? Nous avons placé une instruction à exactement 0 x 0020 dans la mémoire programme. Nous savions que, advenant une interruption de débordement du timer le cpu serait vérifier cet emplacement exact et exécuter toute commande nous mis là. Eh bien, tables de recherche fonctionnent de façon très similaire.

Nous allons ré-écrire notre "dice:" étiqueté sous-routine, qui est celui qui raconte le microcontrôleur qui épingles pour mettre en marche pour obtenir quel numéro sur un dé, afin qu’au lieu d’un article long et laid du code, il peut utiliser une boucle et faire les choses plus simplement. Voici le nouveau code :

Vous voyez que c’est beaucoup plus courte. En fait, chaque fois que vous vous retrouvez répétant le même jeu d’instructions reprises à l’intérieur d’une sous-routine et la seule chose différente chaque fois est que certains nombre particulier est différent, c’est le moment idéal d’utiliser une table de choix. Dans les cas où vous utiliseriez une "boucle" for ou une routine « switch-case » en C ou en une autre langue, c’est le bon moment pour utiliser une table de correspondance en assembleur.

Tables de choix ont la réputation d’être compliqué, mais je ne pense pas que c’est mérité. Je vais essayer de l’expliquer de façon simple ici.

Commençons par la carte de mémoire d’atmega328p. Il existe trois différents types de mémoire stocker des choses. La « mémoire de programme » qui stocke notre programme, la « mémoire de données SRAM » qui contient tous les registres que nous utilisons comme ce généraliste travaillant les registres, les ports d’entrées-sorties et tous les registres que nous utilisons pour activer/désactiver bits et contrôle les façon dont les choses sont faites et enfin de la mémoire « EEPROM », ce qui nous introduira dans un prochain didacticiel (si j’ai dernier cette longue) et est utilisé pour stocker des informations qui ne disparaîtra pas, lorsque nous nous tournons l’appareil hors tension. Très utile si vous faites un jeu et que vous souhaitez stocker somebodies score jusqu'à la prochaine fois qu’ils jouent !

Nous savons que chaque octet d’un type donné de mémoire a une adresse. Par exemple, le premier octet du code nous exécutons est à 0 x 0000 et le gestionnaire d’interruption de débordement timer est à 0 x 0020, etc.. Vous remarquerez que puisque nous avons plus de 256 octets de mémoire dans notre espace de mémoire programme, nous ne pouvons simplement utiliser adresses 0 x 00 à 0xFF. En fait, nous avons 32k de mémoire flash dans l’espace mémoire de programme. Cela signifie que nous avons besoin des adresses de 0 x 0000 jusqu'à 0x7FFF.

Maintenant, supposons que nous voulons lire tout ce qui est à une adresse spécifique en mémoire ? Par exemple, lorsque le cpu obtient une interruption de débordement il va à 0 x 0020 et exécute l’instruction, que nous avons placés là. Que se passe-t-il si nous voulons placer des instructions ou données ou que ce soit à une adresse spécifique dans la mémoire programme et ensuite l’utiliser dans notre programme ? Nous pouvons, sauf que notre généraliste inscrit ne peut supporter 8 bits (1 octet) entre 0 x 00 et 0xFF, et comme nous l’avons vu, une adresse prend 2 octets à écrire vers le bas (entre 0 x 0000 et 0x7FFF). Y a donc pas assez de place dans un registre d’usage général (c'est-à-dire une variable comme r16) pour contenir une adresse mémoire programme. Nous ne pouvons dire « ldi r16, 0b0000000000000010 » par exemple, puisque R16 n’est pas assez grand. Donc si nous avons aucun moyen de stocker l’adresse complète comment pouvons nous y allons lors de l’émission ? Nous pouvons juste prendre le téléphone, appelez le cpu et dire « pouvez-vous aller et exécuter ce que nous avons stocké à 0x2a7f s’il vous plaît » vous devez avoir cette adresse dans un r16 ou quelque chose et puis « mov » il ou « out », il a partir de là.

Voici donc ce que les gens de ATmel ont fait pour résoudre ce dilemme. Ils ont double dessein quelques uns de nos registres à usage général. En particulier, si vous regardez le tableau 7-2 à la page 12 de la feuille de données, vous pouvez voir comment les registres d’usage général sont organisées. Les registres r26, r27, r28, r29, r30 et r31 peut également être combiné en paires appelées X, Y et Z. Alors que X est r26 et r27 ensemble, Y est r28 et r29 ensemble, et Z est r30 r31 ensemble. De cette façon, si nous prenons Z par exemple, la première moitié de celui-ci est r30 et la seconde moitié de celui-ci est r31. Donc si nous voulons conserver une adresse de mémoire de programme nous stockons seulement la moitié r30 et l’autre moitié de celui-ci dans la r31 et puis nous dire le cpu pour rechercher Z si nous voulons parler de tout cela ensemble. Ils ont mis en œuvre deux instructions que cela. Le premier est le spm, qui signifie « Store programme mémoire » et l’autre est l/min, qui est l’abréviation de « Mémoire de programme de charge ». Alors maintenant, si nous voulons obtenir ce que jamais les instructions ou les données sont stockées à l’adresse mémoire 0x24c8 par exemple, nous mettre cette adresse en r30 et r31 et puis, quand nous voulons obtenir les données, nous serions juste l/min à une variable par la pratique

qui ira adresse mémoire Z, prendre quelque données nous y mettre et le coller dans la r16. La chose cool à ce sujet, c’est que si nous y ajoutons 1 à l’aide de Z

puis Z sera désormais « point » l’adresse mémoire suivante après le premier. Alors que se nous tenir toute une liste de numéros en mémoire un après l’autre, que nous pouvons défile en Z s’incrémente.

Comment nous utiliser dans notre programme ?

Eh bien, puisque chaque nombre sur le dé est affiché par pour allumer et éteindre les différents ports comme PC2 et PB5 stockons-nous juste le nombre qui fait cela pour chaque nombre du dé. Par exemple si nous « out » 0b11010010 à PortC PC0 sera défini à 0, PB1 à 1, etc. et allumer les voyants correspondants de nous donner notre numéro sur le dé. Dans ce cas, le numéro 4.

Donc nous allons utiliser une « table de correspondance » appelée "numéros:" pour stocker toutes ces configurations différentes meurent et simplifier notre code.

Je pense que si vous lisez le code ci-dessus et chercher les diverses instructions du manuel d’instructions, vous pouvez facilement comprendre comment il fonctionne. La partie seulement bizarre est le premier bit où on Initialise le pointeur Z.

Ce qu’il fait est Initialise le pointeur Z pointe vers notre liste intitulée « numéros ». La raison pour les 2 fois à l’avant, c’est que nous voulons que l’adresse de « numéros » vers la gauche d’un espace (c’est à quel moment en deux fait nombres binaires). Cela laisse libre la mèche à droite (le bit le moins significatif) qui est ensuite utilisée pour décider quel octet de mémoire programme, nous nous référons au. C’est parce que la mémoire programme est large de 2 octets (16 bits). Ainsi, par exemple, dans notre table, nous avons tout d’abord deux nombres comme
0b01111111 .db, 0b11011110

Étant donné que l’espace mémoire programme est de 16 bits de large tous les deux de ces numéros seront réellement assis à la même adresse mémoire programme donc la façon dont nous saisir l’une ou l’autre est pourquoi nous avons besoin du « temps par 2 » ou vers la gauche des bits. Lorsque le « bit » de Z est 0 il pointera à la première de notre liste : 0b01111111, et lorsque le bit le moins significatif de Z est un 1 il pointera vers l’autre de notre liste : 0b11011110.

Comme vous pouvez le constater, l’ajout de 1 à Z modifie le moins significatif peu de 0 à 1, puis en ajoutant 1 à Z augmente à nouveau l’adresse de mémoire de programme et de la DSJ remonte à un zéro. Donc vous voyez qu’il fonctionne très bien pour la cueillette à toute notre liste de numéros mémorisés, un à la fois en incrémentant simplement Z.

Avis que quand nous passer l’adresse de « numéros » laissé en multipliant par 2 afin de libérer le bit le moins significatif à utiliser pour sélectionner le premier ou le deuxième octet stocké à cette adresse nous perdent le « bit le plus significatif » de l’adresse. Cela signifie que nous pouvons seulement stocker nos données de table de recherche dans les adresses où le bit le plus significatif n’est pas grave - c'est-à-dire toutes nos données nommées aura le bit le plus significatif même. Cela signifie que notre adresse est effectivement 15 bits de longs. 2 ^ 15 est 32768 différentes adresses disponibles pour nos données stockées. Nous allons regarder cela plus en détail dans le prochain tutoriel, alors ne vous inquiétez pas si c’est un peu confus à ce stade.

Maintenant vous savez comment utiliser les tables de recherche et les pointeurs de X, Y et Z pour simplifier votre écriture de code.

Nous allons maintenant donner le programme complet avec ces innovations incluses.

Articles Liés

Tutoriel d’assembleur AVR 11

Tutoriel d’assembleur AVR 11

Bienvenue au didacticiel 11 !Dans ce bref didacticiel, nous allons enfin construire la première partie de notre projet final.La première chose que vous devriez faire est d'aller à la toute dernière étape de ce tutoriel et voir la vidéo. Puis revenez
Tutoriel d’assembleur AVR 1

Tutoriel d’assembleur AVR 1

J'ai décidé d'écrire une série de tutoriels sur la façon d'écrire des programmes de langage d'assemblage pour le Atmega328p qui est le microcontrôleur utilisé dans l'Arduino. Si les gens restent intéressées, je vais continuer à mettre un une semaine
Tutoriel d’assembleur AVR 8

Tutoriel d’assembleur AVR 8

Bienvenue au didacticiel 8 !Dans ce bref didacticiel, nous allons prendre un peu d'une déviation de l'introduction de nouveaux aspects de la programmation en langage assembleur pour montrer comment déplacer nos composants de prototypage pour un circu
Tutoriel d’assembleur AVR 6

Tutoriel d’assembleur AVR 6

Bienvenue au didacticiel 6 !Tutoriel d'aujourd'hui sera un court où nous mettrons au point une méthode simple pour transmettre des données entre un atmega328p et un autre à l'aide de deux ports qui les relient. Nous puis prendre dés rouleau de tutori
Tutoriel d’assembleur AVR 9

Tutoriel d’assembleur AVR 9

Bienvenue au didacticiel 9.Aujourd'hui nous allons montrer comment piloter un afficheur 7 segments, mais aussi un affichage à 4 chiffres à l'aide de notre code en langage assembleur ATmega328P et AVR. Ce faisant cela que nous allons devoir prendre de
Tutoriel d’assembleur AVR 2

Tutoriel d’assembleur AVR 2

Ce tutoriel est une continuation de "tutoriel d'assembleur AVR 1"Si vous n'avez pas passé par 1 tutoriel, vous devez arrêter maintenant et faire celui-là en premier.Dans ce tutoriel, nous allons poursuivre notre étude de programmation en langage
Tutoriel d’assembleur AVR 7

Tutoriel d’assembleur AVR 7

Bienvenue au didacticiel 7 !Aujourd'hui nous allons voir la première comment faire pour nettoyer un clavier et ensuite montrer comment utiliser les ports d'entrée analogiques pour communiquer avec le clavier.Nous ferons cela en utilisant les interrup
Tutoriel d’assembleur AVR 10

Tutoriel d’assembleur AVR 10

Bienvenue au didacticiel 10 !Désolé, qu'il a fallu si longtemps pour sortir cette nouvelle tranche mais c'est un moment assez intense de l'année. En tout cas, ici c'est !Nous avons parcouru un long chemin et vous êtes probablement déjà assez compéten
Tutoriel d’assembleur AVR 5

Tutoriel d’assembleur AVR 5

Aujourd'hui nous allons regarder de plus près aux divers emplacements mémoire dans le microcontrôleur Atmega328p et voir si nous pouvons mieux comprendre comment les choses sont stockés, où ils sont stockés et comment les pointeurs et les tables de r
Tutoriel d’assembleur AVR 3

Tutoriel d’assembleur AVR 3

Bienvenue au didacticiel numéro 3 !Avant que nous commencions, je tiens à faire un point philosophique. N'ayez pas peur d'expérimenter avec les circuits et le code que nous construisons dans ces tutoriels. Changer les câbles près, ajouter de nouveaux
MRETV - vidéo, stéréo Sound et beaucoup plus d’un Arduino standard !

MRETV - vidéo, stéréo Sound et beaucoup plus d’un Arduino standard !

MRETV - vidéo, stéréo Sound et beaucoup plus d'un Arduino standard !Maintenant mis à jour pour Arduino 1.6.6 novembre 2015 !Utiliser seulement deux résistances et deux diodes pour générer la vidéo plein écran. Texte 47 x 29 de 8 x 8 caractères, doubl
Comment charger des programmes à un Arduino UNO de Atmel Studio 7

Comment charger des programmes à un Arduino UNO de Atmel Studio 7

Dans ce court Instructable, nous allons apprendre à charger un programme à une carte Arduino UNO utilisant Atmel Studio au lieu de l'IDE Arduino. Cela est utile lorsque vous avez besoin élaborer un programme à l'aide de plusieurs fonctions avancées o
Star Trek sonnette Hack

Star Trek sonnette Hack

J'ai toujours été un fan de la Star Treks et comme tel, j'étais très excité lorsque mon colocataire ramené un panneau la comm série style Star Trek original. Je n'avais jamais vu l'un d'entre eux, mais une recherche rapide nous a pris sur le site de
Carte de développement pour microcontrôleurs Attiny84

Carte de développement pour microcontrôleurs Attiny84

Il s'agit d'une carte de développement pour microcontrôleur Attiny84. Tha Attiny84 puce possède 11 broches adressables avec l'IDE Arduino, 8k de mémoire flash pour le stockage de programme et 512 octets de mémoire vive disponible pour les variables d