Hola. Empecemos primero por la instruccion ADDWF y el PC(PCL).
Primero, he tomado una imagen del Datasheet que describe el mapa de memoria de los pics 16F876A/877A:
En este mapa, vemos que el Registro PCL esta ubicado en la posicion 0x02 de la memoria RAM del PIC.
Sigamos.
La directiva EQU tiene una estructura asi: NOMBRE EQU DIRECCION.
Vamos a hacer una pausa aqui.
Esta directiva(EQU) nació para simplificar la programacion y comprension de un programa. NO SON SI O SI NECESARIAS.
Detallo: ¿Que es mas fácil, llamar y recordar a una persona por su nombre y apellido o llamarla por su numero de documento?
Supongo que responderas que es mas facil por su nombre y apellido.Para esto mísmo sirve la directiva EQU.
En lugar de tener que poner: ADDWF 0x02,1
Podemos asignarle un NOMBRE a la posicion de memoria 0x02, y de esta manera sera mas facil recordarlo, y entender el algoritmo luego.
Entonces puedo poner:
PEPITO EQU 0x02
Al hacer esto, automaticamente, el programa ensamblador(MPASM por ejemplo) sabrá que cada vez que ponga PEPITO, me estaré refiriendo a la posicion 0x02.
Entonces el ensamblador se encargará automaticamente cuando ensambles tu programa de reemplazar PEPITO por el valor 0x02 que es al que hice referencia.
al poner:
PEPITO EQU 0x02
y luego en el programa por ejemplo:
ADDWF PEPITO,1
El programa ensamblador reemplazara PEPITO por el valor que le puse, es decir que finalmente el ensamblador hará: ADDWF 0x02,1
¿Comprendido?
Sigamos, ahora la instruccion ADDWF
Esta instruccion suma el valor que contenga el registro de trabajo(Work=W) al contenido de un registro que especifiquemos.Al resultado de dicha suma, podemos guardarlo: en el registro de trabajo(W) o bien en el registro que especificamos.
Hasta aqui todo normal y espero que entiendas.
Ahora, vayamos a ver que es el registro PC(o tambien conocido como PCL).
Este registro, es un REGISTRO ESPECIAL. Basicamente, la RAM de un PIC contiene dos tipos de registros:
Los especiales y los generales.
Los especiales son aquellos que Microchip implementa segun cada PIC y sus capacidades. Estos registros sirven para acceder a distintos procesos, modulos y funciones del PIC(por ejemplo el FSR es un registro especial, y sirve para acceder de manera indirecta a la RAM de un pic).
Los registros generales son los que se utilizan para las variables y procesos que NOSOTROS necesitemos. Estos registros se denominan GPR (GENERAL PURPOSE REGISTER) o bien, registros de proposito general.
TODAS LAS VARIABLES AUXILIARES QUE NECESITEMOS para realizar nuestros programas, deben estar ubicadas en posiciones de la RAM destinadas a esto(fijate en la tabla, que indica el rango de memoria RAM destinada a estos registros).
En el caso de estos PICs que te puse de ejemplo, podes ver que la primer posicion destinada a registros generales es la 0x20(32 decimal), y la ultima es la 0x7F(127 decimal).
Por lo tanto, hago una excepcion aqui, y aun sin saber que PIC es el que estas utilizando, en tu programa pusiste:
leido equ 0a
No puedo asegurar que esto este mal, pero si me gustaria saber que PIC estas utilizando, ya que no recuerdo conocer ningún PIC que tenga la posicion 0x0a destinada a registros de proposito general(leido, es una variable que empleas en tu programa para realizar los calculos).Si te fijas en la tabla que te puse, en estos PICs que puse de ejemplo, la posicion 0x0a esta destinada al Registro PCLATH.
Este registro es la Parte semi-alta del contador del programa. Por lo tanto, si en el pic que estas utilizando, la posicion 0x0a tambien esta destinada como en este caso al registro especial PCLATH, tu programa hara cualquier cosa...
Revisa en el datasheet de el PIC que estes usando, si la posicion 0x0A esta dentro del rango de posiciones de la RAM destinada a GPR.Si no es asi, pues deberas cambiar el 0x0a a un valor que si este dentro de este rango.
Volvamos al PC(PCL):
El PC es un registro Especial,ubicado en la posicion 0x02 en todos los PICS que conozco(esto no quiere decir que sea igual en TODOS los PICs) y cumple una funcion muy importante en el PIC.MICROCHIP lo ubicó en la 0x02, y NO SE PUEDE CAMBIAR.
El PC es un registro que, bajo uso normal, es controlado por el PIC, no por nosotros. Cada vez que se ejecuta una linea de codigo el PC cambia de valor. Es el registro que indica la instruccion que se esta ejecutando dentro de la MEMORIA FLASH del PIC.
La memoria FLASH contiene todas las instrucciones que programamos en el archivo asm.
Vamos con un ejemplo:
si pongo:
org 0 ;como ya te dije, poniendo esto, indico que el codigo debajo de esto, se escribira a partir de la posicion 0 en la memoria FLASH del PIC. Por lo tanto:
nop ;Esta instruccion se escribira en la posicion 0 de la FLASH del PIC
nop ;Esta instruccion se escribira en la posicion 1 de la FLASH del PIC
nop ;Esta instruccion se escribira en la posicion 2 de la FLASH del PIC
nop ;Esta instruccion se escribira en la posicion 3 de la FLASH del PIC
Hasta aqui espero comprendas.
Cuando,por ejemplo, a un PIC lo alimentas(es decir, lo enciendes), automaticamente, el PIC arranca ejecutando el codigo ubicado en la posicion 0 de la memoria FLASH del PIC.
Entonces, el PIC debe guardar en algun lado la posicion actual que se va a ejecutar. Dicha posicion se guarda en los registro PCL, PCLATH y tambien en los bits RP0 y RP1 del registro STATUS del PIC.
Debido a que esta familia de PICs solo trabaja con registros de un tamaño de 1 byte, el maximo valor que puede adquirir un registro es de 255 en decimal. Pero...los PICs generalmente tienen mayor cantidad de memoria que 256 posiciones!
Entonces: ¿como hace para guardar las posiciones a ejecutar mas alla de la posicion 255?
Pues utiliza los registros especiales PCLATH y bits RP0 y RP1 del registro STATUS para contar mas alla de 255.
El PIC une estos registros, y arma entre todos, una valor mas largo(grande).
Entonces queda:
RB1 RB0 PCLATH PCL
En total, son 13 bits por banco. Los 8 bits mas bajos del contador se guardan en el registro PCL. y 5 "intermedios" en el registro PCLATH.
Los 2 mas altos en los bits RB1 y RB0 del registro STATUS.Estos se utilizan para seleccionar banco(los PICS que puse de ejemplo,poseen 4 bancos), .
Cuando el PCLATH supera el valor de 255, se incrementa en 1 el valor del PCLATH, y el PCL vuelve a valer cero.
Entonces en este caso nos quedaria por ejemplo: PCLATH = 1 PCL=0
uniendo los bits, nos queda: 1 0000000
Este valor es el valor 256.
Aclaro que a todo esto el PIC lo hace automaticamente por hardware.
Entonces, volviendo al ejemplo:
nop ;El pic ejecuta esta instruccion. Como esta instruccion esta en la posicion 0 de la FLASH el PCL= 0. Una vez ejecutada, el PCL se
;autoincrementa en 1(esto lo hace el PIC por hardware)
nop ;Entonces, al incrementarse, PCL= 1. Este segundo nop esta ubicado en la posicon 1 de la flash, por lo tanto, el PCL ejecuta esta y se
;autoincrementa. y asi sigue...
nop
nop
Entonces, el PCL(contador del programa) ante instrucciones NORMALES(como son las NOP) se autoincrementa para ejecutar la instruccion siguiente.
Ciertas instrucciones generan SALTOS del contador del programa.Por ejemplo: GOTO,CALL,RETURN,RETFIE,RETLW.Estas instrucciones alteran el normal autoincremento del PCL, forzandolo a ir a una posicion especifica dentro de la FLASH, para poder esquivar codigo que no debe ser ejecutado.
Tambien, podemos FORZAR un salto del contador del programa. ¿Como? hay muchas formas.
Ejemplo:
pc EQU 0x02
org 0
nop
nop
clrf pc
El programa arranca ejecutando el primer nop, ya que lo ubique dentro de la posicion 0 de la memoria FLASH.Aqui PCL = 0. Luego la ejecuta(a la instruccion nop), y el PCL se autoincrementa, valiendo ahora 1. En la posicion 1, esta el segundo nop. Entonces lo ejecuta y se autoincrementa. Ahora PCL = 2, que es donde esta clrf pc. Lo ejecuta...,se autoincrementa el PCL en 1, y...aqui CLRF pone el pc a cero. Como a pc lo declare como la posicion 0x02 que es la posicion RAM usada por el PCL, fuerzo al PCL a valer cero, entonces el programa SALTA al inicio de la FLASH(vuelve a ejecutar el primer nop ya que PCL pasa a valer cero, y ejecutara la posicion ubicada en la posicion 0 de la FLASH). Esto se produce eternamente. He generado un loop eterno.
En tu algoritmo, estas forzando a cambiar el PCL con otra instruccion: la addwf.
En este caso, el PCL saltara hacia adelante(Es decir, salteara tantas instrucciones) como valga W.
Si haces:
movlw .3
addwf PCL,1
Forzaras al programa a que SALTE(esquive) las siguientes 3 instrucciones que pongas debajo.
Ejemplo:
movlw .3 ;aqui el PCL supongamos que vale 40. La ejecuta, y se autoincrementa pasando a la siguiente posicion de memoria
addwf PCL,1 ;Aqui PCL = 41. La ejecuta y se autoincrementa. Entonces PCL = 42, pero...esta instruccion suma W al contador,forzandolo a saltar W instrucciones. Como W=3 entonces queda: PCL=42+3 = 45. El programa salta a la posicion de memoria 45(esquiva las 42, 43 y 44)
gotoCero ;esto esta ubicado en la posicion 42
gotoUno ;esto esta ubicado en la posicion 43
gotoDos ;esto esta ubicado en la posicion 44
gotoTres ;esto esta ubicado en la posicion 45 y es la que ejecutara inmediatamente luego del addwf PCL,1
LAS LINEAS EN BLANCO NO SE GRABAN EN LA FLASH. POR LO TANTO, NO OCUPAN ESPACION ALGUNO.
LO MISMO CON LOS COMENTARIOS.
Si pones:
nop
nop
;comentario
;nop
nop
El programa ensamblador eliminara todos los espacios y comentarios, quedando en realidad lo mismo que si hubieses puesto:
nop
nop
nop
Con respecto a los de las directivas ORG. Te sugiero, para que comprendas como funcionan:
Abrie el MPLAB y escribi un probrama cortito. Anda a Project-->Quickbuild y ensamblalo. Despues de eso, anda a View-->Program memory y fijate donde se guarda el codigo que escribiste dentro de la FLASH.
Luego, anda variando el valor de la directiva ORG que pusiste en tu programa, volve a ensamblar, y volve a revisar Program Memory para ver como afecta esto la posicion donde se grabara el codigo.
Espero haberte ayudado. Exitos.