Étape 3: Analyse en ligne du code
J’ignore les lignes qui sont simplement des commentaires que leur but est évident.
.nolist .include "./m328Pdef.inc" .list
Ces trois lignes incluent le fichier contenant les définitions de Registre et le Bit pour le ATmega328P que nous sommes la programmation. La commande .nolist raconte l’assembleur ne pas d’inclure ce fichier dans le fichier pushbutton.lst qu’il produit lors de l’assemblage il. Il désactive l’option de la liste. Après avoir inclus le fichier nous rallumer l’option de liste avec la commande .list. La raison pour laquelle que nous faisons c’est parce que le fichier m328Pdef.inc est assez long et il ne faut vraiment le voir dans le fichier de la liste. Notre assembleur, avra, ne génére automatiquement un fichier de liste, et si nous souhaitons nous rassemblerait à l’aide de la commande suivante :
avra -l pushbutton.lst pushbutton.asm
Si vous faites cela, il générera un fichier appelé pushbutton.lst et si vous examinez ce fichier que vous trouverez qu’il montre votre code de programme ainsi que des informations supplémentaires. Si vous regardez les informations supplémentaires, vous verrez que les lignes commencent par un c: suivi de l’adresse relative dans l’hexagone d’où le code est placé dans la mémoire. Essentiellement, il commence à 000000 avec la première commande et augmente de là avec chaque commande subséquente. La deuxième colonne après la place relative dans la mémoire est le code hexadécimal de la commande suivie par le code hexadécimal pour l’argument de la commande. Nous allons discuter de liste des fichiers supplémentaires dans les futurs tutoriels.
.def temp = r16 ; designate working register r16 as temp
Dans cette ligne, nous utilisons l’assembleur directive « .def » pour définir la variable "temp" comme égal à la r16 « Registre de travail. » Nous utiliserons le registre r16 comme celle qui enregistre les numéros que nous voulons copier dans divers ports et registres (qui ne peuvent être écrites directement à).
Exercice 1: Essayez de copier un nombre binaire directement dans un port ou un registre spécial comme DDRB et voir ce qui se passe lorsque vous essayez d’assembler le code.
Un registre contient un octet (8 bits) d’informations. Essentiellement, c’est généralement une collection de SR-loquets de chacun d’eux est un « peu » et contient un 1 ou un 0. Nous pourrions discuter de cela (et même construire un!) plus tard sur dans cette série. Vous demandez peut-être ce qu’est un « registre de travail » et pourquoi nous avons choisi r16. Nous allons discuter que dans un futur tutoriel lorsque nous plongent dans le bourbier des caractéristiques internes de la puce. Pour l’instant, je veux que vous compreniez comment faire des choses comme écrire le code et le programme matériel physique. Ensuite, vous aurez un cadre de référence de cette expérience qui rendra la mémoire et inscrire des propriétés du microcontrôleur plus facile à comprendre. Je me rends compte que plus manuels d’introduction et de discussions faire l’inverse mais j’ai trouvé que la lecture d’un jeu vidéo pendant un certain temps premier et dicking environ pour obtenir une perspective globale et ensuite lire le manuel d’instructions pour apprendre à mieux il est beaucoup plus facile que la première lecture du manuel.
rjmp Init ; first line executed
Cette ligne est un « saut relatif » de l’étiquette « Init » et n’est pas vraiment nécessaire ici puisque la prochaine commande est déjà dans Init, mais nous l’incluons pour une utilisation future.
Init: ser temp ; set all bits in temp to 1's.
Après le label Init nous exécuter une commande « set register ». Ceci affecte tous les 8 bits dans le registre « temp » (qui vous rappelez est r16) 1. Donc le temp contient maintenant 0b11111111.
out DDRB,temp ; setting a bit as 1 on the Data Direction I/O register ; for PortB, which is DDRB, sets that pin as output ; a 0 would set that pin as input ; so here, all PortB pins are outputs (set to 1)
Le registre DDRB (données Direction s’inscrire pour PortB) raconte qui épingle sur le PortB (c.-à-d. PB0 par PB7) sont désignés comme entrée et qui sont désignés comme sortie. Puisque nous avons la broche que Pb0 connecté à notre LED et le reste non connecté à tout ce que nous allons définir tous les bits à 1, ce qui signifie qu’ils sont toutes les sorties.
ldi temp,0b11111110 ; load the `immediate' number to the temp register ; if it were just ld then the second argument would ; have to be a memory location
Cette commande charge le 0b11111110 nombre binaire dans le registre de temp.
out DDRD,temp ; mv temp to DDRD, result is that PD0 is input and ; the rest are outputs
Maintenant nous Réglez le registre de Direction données pendant PortD de temp, car temp contient encore 0b11111110 que nous voyons que PD0 sera désigné comme un pin d’entrée (car il y a un 0 dans le spot d’extrême-droite) et le reste sont désignés comme sorties puisqu’il n’y a de 1 à ces endroits.
clr temp ; all bits in temp are set to 0's out PortB,temp ; set all the bits (i.e. pins) in PortB to 0V
Tout d’abord, nous avons « effacer » le temp de Registre qui signifie définissant tous les bits à zéro. Puis on copie qu’au registre PortB qui définit le 0V sur toutes les broches. Un zéro sur un bit PortB signifie que le processeur va maintenir que la broche à 0V, un sur un bit provoquera cette broche doit être défini à 5V.
Exercice 2: Utiliser un multimètre pour vérifier si toutes les broches sur le PortB sont en fait de zéro. Est quelque chose de bizarre se passe avec PB1 ? Aucune idée pourquoi qui peut être ? (similaire à l’exercice 4 ci-dessous puis suivre le code...)
Exercice 3: Supprimer les deux lignes ci-dessus à partir de votre code. Le programme est toujours exécuté correctement ? Pourquoi ?
ldi temp,0b00000001 ; load immediate number to temp out PortD,temp ; move temp to PortD. PD0 is at 5V (has a pullup resistor) ; since it has a 1 in that bit the rest are 0V.
Exercice 4: Supprimer les deux lignes ci-dessus à partir de votre code. Le programme est toujours exécuté correctement ? Pourquoi ? (C’est différent de l’exercice 3 ci-dessus. Voir le code pin sur le diagramme. Ce qui est le paramètre par défaut de DDDR pour PD0 ? (Voir page 90 de la feuille de données)
Tout d’abord nous « charge immédiate » le 0b00000001 numéro de temp. La partie « immédiate » est là puisque nous sommes charger une Quinte nombre de temp au lieu d’un pointeur vers un emplacement en mémoire contenant le nombre à charger. Dans ce cas, nous utiliserions simplement « ld » plutôt que "IGP". Ensuite, nous envoyons ce nombre à PortD qui définit PD0 sur 5V et le reste à 0V.
Maintenant, nous avons fixé les broches comme entrée ou sortie et nous avons mis en place leurs États initiaux comme 0 v ou 5 v (bas ou haut) et donc nous entrons maintenant dans notre programme « boucle ».
Main: in temp,PinD ; PinD holds the state of PortD, copy this to temp ; if the button is connected to PD0 then this will be ; a 0 when the button is pushed, 1 otherwise since ; PD0 has a pull up resistor it is normally at 5V
Le registre PinD contient l’état actuel des broches PortD. Par exemple, si vous attachez un fil de 5V à PD3, puis à l’horloge du prochain cycle (ce qui se passe 16 millions de fois par seconde puisque nous avons le micro-contrôleur relié à un signal d’horloge de 16MHz) le bit PinD3 (à partir de l’état actuel du PD3) deviendrait un 1 au lieu d’un 0. Donc, dans cette ligne nous copier l’état actuel des broches de temp.
out PortB,temp ; sends the 0's and 1's read above to PortB ; this means we want the LED connected to PB0, so ; when PD0 is LOW, it will set PB0 to LOW and turn ; on the LED (the other side of the LED is connected ; to 5V and this will set PB0 to 0V so current flows)
Maintenant, nous envoyer l’état des broches en PinD à la sortie du port. Effectivement, cela signifie que PD0 enverra un 1 à PortD0, à moins que le bouton est enfoncé. Dans ce cas, étant donné que le bouton est relié à la terre que la broche sera à 0V et il enverra un 0 à PortB0. Maintenant, si vous regardez le schéma de câblage, 0V sur PB0 signifie que la diode luminescente depuis l’autre côté de celui-ci est à 5V. Si nous ne sommes pas en appuyant sur la touche, afin qu’un 1 est envoyé à PB0, cela voudrait dire que nous avons 5V sur PB0 et aussi 5 v sur l’autre côté de la LED et donc il n’y a aucune différence de potentiel et courant ne s’écoule et donc la LED ne s’allume pas (dans ce cas que c’est une LED est une diode et tellement actuel coule seulement une direction sans se soucier, mais peu importe).
rjmp Main ; loops back to Start
Ce saut relatif nous boucle retour à notre principal : étiquette et nous vérifier PinD à nouveau et ainsi de suite. Vérifier chaque 16 millionième de seconde si le bouton est poussé et définissant PB0 en conséquence.
Exercice 5: Modifier votre code afin que votre LED est connecté à PB3 au lieu de PB0 et voir si elle fonctionne.
Exercice 6: Branchez votre LED GND au lieu de 5V et modifiez votre code en conséquence.