Lenguaje ensamblador para PIC desde 0

Publicada asm_desde_cero v1.9.pdf
 

Adjuntos

  • asm_desde_cero_v19_979.pdf
    886.5 KB · Visitas: 179
A Meta: Si, explicaría como hacer un diagrama de flujo. Pero es obvio que cada uno tiene su forma de programar.

A electroaficionado: Por mi no hay problema.

Saludos.
 
me vengo de otro tema y te paso el texto:
https://www.forosdeelectronica.com/f24/temporizacion-maxima-pic-17560/


cuando hice el curso de PIC con mi querido profe "pablin" hace mucho comenzo el mismo con programas lineales sin interrupciones , obvio que no se quedo en ellos .
pero quizas haya gente que estudio por su cuenta y si, se quedaron en un concepto lineal .
por eso (y esto va a quienes estan con el curso de ASM desde cero ) creo que es mas importante esas cosas que explicar las instrucciones que ya estan explicadas en la data.
si a lo mucho un buen enlace y copy paste , pero dedicar tiempo a lo que si lo vale.

es solo una opinion y nada de critica, ya que no se puede criticar algo que se esta haciendo MUY BIEN y con muy buena onda como lo que estan haciendo uds.

saludos
 
fernandob dijo:
es solo una opinion y nada de critica, ya que no se puede criticar algo que se esta haciendo MUY BIEN y con muy buena onda como lo que estan haciendo uds.

Es opinión y crítica, y si, si se puede criticar algo que se está haciendo muy bien. Dentro del término bien y no tan bien.
 
Fernandob. El curso está dedicado a los que no saben nada de ASM, por eso se llama ASM desde cero. Les sirve también a las personas que ya saben del tema y se quieran perfeccionar o ver las cosas desde otro punto de vista.
Si haría copiar y pegar, no sería un curso echo por mi si no de otro autor y tener que pasear por toda la web para buscar un buen material, me perdería mucho tiempo por algo que se y que me gusta explicar.

Si bien es verdad lo que decis, hay muchos puntos muy importantes para ver en el curso de ASM, y te digo que la programación de ASM es lineal, siempre se comienza desde arriba hacia abajo y se puede cambiar el curso del CP por medio de interrupciones, goto, call. Todo esto, hace que el programa sea cíclico (como todo programa).

Las interrupciones, es una explicación que va a estar en el curso como así los módulos del 16f877 que son bastantes y que sirven para otras familias.

Es verdad lo que dice META, es una crítica y por eso, te estoy agradecido, ya que son muy pocas personas que dan alguna crítica y sugerencias (toda crñitica debe estar acompañado de una sugerencia si no, no la tomo y la desacrtaré) y todo esto, ayuda a que el curso se mejore.

Y para cerrar, vino muy bien que explique las instrucciones, porque son en muy, pero en muy poco lugares, la explicación del goto y call y el porqué y como trabajar con las páginas de los PIC que a todos nos trae problema. Critican a microchip por esto, cuando ellos nos dieron la solución para trabajar más cómodamente y por la instrucción pageselw que solo MPASM lo lee.

Y vuelvo a repetir, no estoy enojado, si no agradecido por haber dado tu opinión y una crítica y sugerencia.

Manonline. Jamás trabajé con los pic de gama baja, por lo que por ahora, no tocaré nada del tema. Una vez que termine con este, veré si paso a los de gama baja o alta (de seguro, pasaré a los dspic si para entónces ya estoy trabajando con ellos)
 
Estaría bueno que trabajaras con el módulo usb de los PIC18FXX5X. Yo lo estoy trabajando en C de CCS, pero me gustaría ver las diferencias (A nivel de velocidad de trabajo).
Como tal es un comentario. Si lo llegas a llevar a cabo te podría llegar a dar una mano.
 
Lamentablemente, aún no he trabajado con USB. Ni siquera se programación de PC, pero ya estoy estudiando así puedo hacer aplicaciones con estos dispositivos que ya tengo varias cosas en mente.

Por ahora, voy a terminar lo que empezé y hablo de este curso. Luego veré que puedo seguir aportando.
 
RETLW

Carga al CP con el valor de la parte alta de la pila para volver al lugar dónde se encontraba el CP desde dónde se llamó a la subrutina y al retornar, lo hace con un literal cargado en W especificado por el programador. Esta instrucción, se utilizan en las tablas (para más detalle, ver la explicación del GOTO y CALL).


Ejemplo:

Código:
            RETLW          'L'

En este ejemplo, el MPLAB, carga en W el código ASCII correspondiente a la letra L

Extendiendo el ejemplo:

Código:
           PAGESELW       TABLA             ;CONFIGURA AL PCLATH PARA VOLVER AL LUGAR CORRECTO
           MOVFW            contador        ;CARGA A W LA POCICIÓN A LEER EN LA TABLA POR EJEMPLO 3
           CALL               TABLA            ;LLAMA A LA RUTINA TABLA
           CALL               LCD_DATO      ;LLAMA A LA RUTINA PARA MOSTRA AL LCD
           NOP
;
;
TABLA   ADDWF             PCL,F            ;SUMA AL PCL CON EL CONTENIDO DE W POR EJEMPLO 3
           RETLW              '1'                ;RETORNA CON 1 ASCII
           RETLW              '2'                ;RETORNA CON 2 ASCII
           RETLW              '3'                ;RETORNA CON 3 ASCII
           RETLW              'T'                ;RETORNA CON 4 ASCII

Este es un ejemplo sencillo de como utilizar RETLW. Para interpretar este código empezamos desde PAGESELW, supongamos que el CP está en esta instrucción (que está explicado que hace) luego pasa a la instrucción MOVFW contador y suponemos que tiene cargado 3 en decimal, por lo que W pasará a tener 3 en decimal. El CP continua con CALL TABLA, el CP saltará por encima a todas las demás instrucciones y se dirige a la etiqueta TABLA y ejecuta la instrucción ADDWF PCL,F En el código hablamos que le suma 3 al PCL, por lo que saltará al RETLW '3' cargando a W con el código ASCII 3. Retorna justo debajo del CALL TABLA, o sea retorna a CALL LCD_DATO y ejecuta la rutina correspondiente, cuando termina, regresa al NOP (que puede ser cualquier instrucción que necesite el programador.
Si en cambio, contador hubiera tenido cargado 4 en decimal cuando llegue a la tabla y le sume al PCL este apuntará a RETLW 'T' cargando en W el código correspondiente ASCII.

Para recordar RETurn es retornar Literal es literal W es el registro de trabajo W

No afecta ningún bit del registro STATUS.

RETURN

Carga al CP con el valor de la parte alta de la pila para volver al lugar dónde se encontraba el CP cuando se llamó a la rutina o subrutina.

La diferencia con RETLW es que RETURN regresa sin cambiar a W. Este se utiliza para terminar una rutina y no se necesite ningún dato. Por ejemplo en la rutina CALL LCD_DATO no nos sirve que vuelva con ningún valor ya que es una rutina para enviar datos a un LCD, asi que esta rutina tendrá implementada RETURN

Por ejemplo:

Código:
             RETURN

No afecta ningún bit del registro STATUS

Para recordar RETURN es retornar.
 
RLF

Rota hacia la izquierda los bit de un registro seleccionado por el programador. El destino de la operación se puede elegir. Cada rotación equivale a multiplicar por 2 si el bit C del registro STATUS es 0.

Ejemplo:

Código:
              RLF         PORTC,F

Si antes de la instrucción PORTC vale B'00001000', después de la instrucción vale B'00010000'. Si se hubiera elegido como destino W, PORTC después de la instrucción continua valiendo B'00001000' y W vale B'00010000'

Para recordar Rotate es rotar Left es izquierda File es el registro.

Afecta a:


  • C se pone a 1 si hubo acarreo

RRF

Rota hacia la derecha los bits de un registro seleccionado por el programador. El destino de la operación se puede elegir. Cada rotación equivale a dividir por 2 si el bit C del registro STATUS es 0.

Ejemplo

Código:
             RRF         PORTB,F

Si antes de la instrucción PORTB vale B'10000000' después de la instrucción PORTB vale B'0100000'. Si se hubiera elegido como destino W, PORTB después de la instrucción continua valiendo B'10000000' y W vale B'01000000'

Para recordar Rotate es rotar Right es derecha File es el registro.

Afecta a:


  • C se pone a 1 si hubo acarreo

Extendiendo la explicación de las instrucciones RRF y RLF

A la hora de utilizar estas dos instrucciones, hay que prestarle atención al bit C del registro STATUS. La razón de esto, es porque la rotación se hace atravéz del bit C.

Supongamos que tenemos lo siguiente:


  • BIT C = 0
    TEMP = B'00010000'

Ejecutamos la instrucción RRF y TEMP vale B'00001000'. O si ejecutamos la instrucción RLF TEMP vale B'00100000'

Pero si ahora tenemos:


  • BIT C = 1
    TEMP = B'00010000'

Ejecutamos la instrucción RRF y TEMP vale B'10001000'. O si ejecutamos la instrucción RLF TEMP vale B'00100001'

Vemos como rota los bit dependiendo del valor del bit C. Pero anteriormente, avíamos dicho que estas dos instrucciones afectan al bit C. La actualización del bit C, lo hace después de la rotación. Lo vemos con un ejemplo:

Código:
           MOVLW  B'10001001'
           MOVWF  temp
           BCF   STATUS,C        ;PONEMOS A 0 AL BIT C
           RLF   temp,F          ;ROTAMOS A LA IZQUIERDA

Al ejecutar este programa, nos dará lo siguientes resultados:


  • TEMP = B'00010010'
    BIT C = 1

Y para ver la diferencia vemos lo siguiente:

Código:
           MOVLW  B'00000001'
           MOVWF  temp
           BCF   STATUS,C        ;PONEMOS A 0 AL BIT C
           RLF   temp,F          ;ROTAMOS A LA IZQUIERDA

Al ejecutar este programa, nos dará lo siguientes resultados:


  • TEMP = B'00000010'
    BIT C = 0

Algo que me había olvidado de mencionar pero que MIGSANTIAGO del foro de TODOPIC estuvo atento es que estás dos instrucciones, nos sirve para enviar datos en forma serial utilizando el bit C que lo veremos más adelante.

Recordemos que, para utilizar estas instrucciones para multiplicar o dividir, debemos asegurarnos de que el bit C, esté en 0.

SLEEP

Pone al microcontrolador en bajo consumo.

Código:
              SLEEP

Para recordar SLEEP es dormir.

Afecta a:


  • TD se pone a 1
    PD se pone a 1

SUBLW

Resta el contenido de W con un literal de hasta 8 bit (.255). El resultado se guarda en W.

Código:
              SUBLW       .20

Si antes de la instrucción W vale .23 después de la instrucción W vale .3 Para saber si el resultado es negativo o positivo, hay que chequear el bit C del registro Status. Si hay acarreo, el resultado es negativo, y por el contrario, si no hay acarreo es positivo.

Para recordar SUBtraction es restar Literal es literal y W es el registro W.

Afecta a:


  • Z se pone a 1 si el resultado es 0
    DC se pone a si hay acarreo del bit del 4 al 5 bit del registro (recordemos que en la resta, es distinto a la suma, por eso, se pone a 0 si hubo acarreo).
    C se pone a 0 si hubo acarreo (recordemos que en la resta, es distinto a la suma, por eso, se pone a 0 si hubo acarreo).
 
Actualización asm_desde_cero v1.11.pdf Sólo 3 descargadas.

Sustituyo la v1.11 por la v1.12.
 

Adjuntos

  • asm_desde_cero_v112_304.pdf
    912.5 KB · Visitas: 207
SUBWF

Resta el contenido de un registro seleccionado por el programador con el contenido del registro W. La fórmula es F - W = d. d es la dirección elegida por el programador en dónde se guardará el resultado que puede ser el registro W o el registro elegido por el programador.

Ejemplo:

Código:
           SUBWF        MINUENDO,W

Si antes de la instrucción W vale .55 y MINUENDO vale .56, después de la instrucción, MINUENDO vale .56 y W vale .1

Para recordar SUBtraction es resta W es el registro W y File es el registro elegido.

Afecta a:


  • Z se pone a 1 si el resultado es 0
    DC se pone a 0 si hubo un acarreo del 4 bit al 5 bit (recordemos que en la resta, es distinto a la suma, por eso, se pone a 0 si hubo acarreo).
    C se pone a 0 si hubo acarreo del 7 bit. (recordemos que en la resta, es distinto a la suma, por eso, se pone a 0 si hubo acarreo).

SWAPF

Intercambia los bits de un mismo registro elegido por el programador. Los 4 bit de menor peso, pasan a ser lo 4 bits de mayor peso, y los 4 bits de mayor peso, pasan a ser los 4 bits de menor peso. El destino puede ser seleccionado.

Cabe pensar que puede ser una instrucción de muy poco uso, pero todo lo contrario si se utilizan con las interrupciones. Microchips recomienda su utilización a la hora de salvar el contexto y restaurarlo en una interrupción ya que no modifica el registro STATUS. Cuando trabajemos con la interrupciones, se verá que es muy recomendable salvar el registro STATUS y W en la RAM para luego restaurarlos. Si utilizamos la instrucción MOVF, es afectado el bit Z, perdiendo su estado original en el momento de la interrupción. Esto se soluciona, utilizando la instrucción SWAPF. No se preocupen si no lo entiende por ahora. Lo entenderan cuando veamos ejemplo de interrupciones.

Ejemplo:


Si antes de la instrucción W bale H'55' y el registro STATUS vale B'00100100', después de la instrucción el registro STATUS vale H'24' y el registro W vale B'01000010'

Para recordar SWAP es intercambiar NIBBLE es porción File es el registro.

No afecta ningún bit del registro STATUS.

XORLW

Realiza la operación lógica XOR entre un literal o valor y el registro W. El resultado queda guardado en el registro W.

Ejemplo:

Código:
               XORLW        B'11000101'

Si antes de la instrucción W vale B'11111000', después de la instrucción W vale B'00111101'.

Para recordar XOR es la operación lógica XOR Literal es un valor W es el registro W.

Afecta a:


  • Z se pone a 1 si la operación es 0

XORWF

Realiza la operación XOR entre un registro elegido por el programador y el registro W. La operación es F XOR W = d. El resultado se puede elegir dónde será guardado.

Ejemplo:

Código:
               XORWF        PORTB,F

Si antes de la instrucción PORTB vale B11111110' y W vale B'00000001', después de la instrucción W vale .1 y PORTB vale B'11111111'.

Para recordar XOR es la operación lógica XOR W es el registro W y File es el registro elegido.

Afecta a:


  • Z se pone a 1 si la operación es 0
 
Leon Elec dijo:
Meta. actualizé un error que tenía la instrucción INCFSZ, que está en la página 5 del foro. Saludos.

¿Te refieres sólo lo que indico abajo?

INCFSZ

Incrementa en 1, o suma en 1, el contenido de un registro elegido por el programador y cuando este es 0, el CP salta una instrucción.

Código: Seleccionar todo

VOLVER INCFSZ CONTADOR
GOTO VOLVER
INCF PORTA



El CP incrementará en 1 el registro CONTADOR y evalúa el valor, si no es cero, ejecuta línea siguiente que es GOTO VOLVER, el cual se dirige de nuevo a la línea VOLVER INCFSZ CONTADOR el cual volverá a incrementar en 1 y evalua el valor, si es cero salta la línea GOTO VOLVER y ejecuta la instrucción INCF PORTA. Esta última línea, el programador pondrá la instrucción que necesite ejecutar.
Este pequeño programa que acabamos de ver, es un temporizador o un retardo que tardará en salir del bucle dependiendo de la frecuencia de reloj y el valor cargado en CONTADOR. Normalmente, se utiliza el retardo con DECFSZ pero este también es válido.

NOTA: Esta instrucción, también hay que elegirle el destino. En el caso que no se exprese, como en este caso, el MPLAB dará por sentado que el resultado se guardará en el registro F y no en W.

Para recordar INCrement es incremento File es registro Skip es salto Zero es cero.

No afecta ningún bit del registro STATUS.
 
Una vez que vimos todas las instrucciones y asumiendo que ya se la saben de memoria (tiempo tuvieron de sobra) y si no lo han echo, es hora de hacerlo, empezemos a escribir programas muy sencillos. Pero ¿cómo?. Si se están asiendo esta pregunta, es hora de leer desde el primer mensaje. Tienen que acordarce las pociciones de las cuatro columnas.

Recuerden que vamos a escribir los programas en el MPLAB, por lo que si aún no lo tienen, es hora de descargarlo de la página de Microchip en forma gratuita e instalarlo en la PC. Lamentablemente, este programa trabaja solo bajo windows, por los que tienen mac o Linux, no lo prodrán hacer si no es por un emulador de windows y aún así, no se si funcione correctamente.

Empezaremos bien desde el principio y para ello, voy a explicar cosas nuevas. Todo programa tiene un encabezado que se repite en cada programa nuevo y que varía según el PIC a utilizar y las prestaciones del programa a escribir. Muchas de las personas crean plantillas nuevas para ahorrarce el trabajo. Yo soy una de ellas y aquí les doy una plantilla que pueden utilizar sin problemas y modificarlas según su necesidad.

He aquí la plantilla que también está adjuntado.

LIST P=16F877A
INCLUDE <P16F877A.INC>
__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC
;
;---------------------------------------------------------------
;VARIABLES.
;---------------------------------------------------------------
;
CBLOCK H'20'

ENDC
;
RESET ORG H'00'
GOTO INICIO
ORG H'04' ;VECTOR INTERRUPCIÓN
INTERRUP
;
INICIO
;
END

Primera línea:

LIST P=16F877A

Esta línea, sive solo para el MPLAB y le indica que el PIC a utilizar es el 16F877A. Se debe actualizar según sea necesario.

Segunda línea:

INCLUDE <P16F877A.INC>

Esta línea sirve a la hora de compilar ya que dentro de este archivo que viene incluido dentro del MPLAB, le indica al ensamblador dónde están ubicados cada registro y el nombre de cada bits del PIC a utilizar así, nos ahorra de hacerlo nosotros mismos. Si desean abrir el archivo, lo pueden hacer con el notepad o cualquier editor de texto. Se debe actualizar según sea necesario.

Tercera línea:

__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC

Linea muy importante pero se puede omitir. Aquí se configura la palabra de configuración del PIC y que está en el datasheet del pic correspondiente.
En mi caso, yo la omito y luego lo configuro desde el ICPROG a la hora de pasar el archivo .hex al pic. Es por eso que esta línea está incompleta para el pic a utilizar pero completa para el PIC 16F84.

Vemos en más detalle esta línea: __CONFIG Directiva para el ensamblador de que debe generar la palabra de configuración correspondiente de acuerdo a:

_CP_OFF la protección de lectura del PIC desabilitado.
_PWRTE_ON Reset de encendido habilitado
_WDT_OFF Perro guardián desabilitado.
_XT_OSC Oscilador a cristal.

El caracter & sirve para unir una directiva con otra.
 

Adjuntos

  • plantilla_102.asm
    391 bytes · Visitas: 169
Cuarta línea:

;
;---------------------------------------------------------------
;VARIABLES.
;---------------------------------------------------------------
;

Este no es más que un pequeño encabezado. El ensamblador omitirá estas líneas y solo porque empieza con ";". Recuerden que, toda línea que empieze con ";" es comentario y el ensamblador la omitirá.

Justo por debajo de este encabezado, penemos las variables. ¿a que le llamo variables? a pociciones de memorias o nombre de bit que yo quiera darle personalmente.
Por ejemplo, dentro del archivo P16F877A.INC a la pocición de memoria 0x05 le llama PORTA pero si yo quero llamarlo PUERTO_A, es quí dónde le indico al ensamblador.

¿Cómo se hace?

Es muy fácil y con la instrucción "EQU"

PUERTO_A EQU H'05'

Si al Bit RA6 lo quero llamar LED6 lo hacemos así:

LED6 EQU 6

Supongamos que quiero encender el LED 6 que está en el Puerto a bit 6, y este se activa con un 1 lógico, ponemos esta instrucción:

BSF PUERTO_A,LED6

Y el ensamblador lo traducirá así: BSF 0X05,0X06

Quinta línea:

CBLOCK H'20'

ENDC

A estas dos líneas las unifique porque van juntas. Entre ellas van los nombres de cada pocición de la RAM que nosotros querramos nombrar, o cada Registro que querramos renombrar.
Recuerden que los registros están implementados en la RAM y que la pocición de la RAM que puede utilizar el usuario para guardar cosas, empieza desde una pocición que está indicada en el datasheet. Para el caso de 16F877 empieza desde la pocición 0x20 como lo ven en la figura siguiente.

(Ver archivo adjunto)

La directiva CBLOCK H'20' indica que empezamos a nombrar pociciones de memoria desde la ubicación 0x20. Por ejemplo

CBLOCK H'20'
temperatura
demora1
demora2
ENDC

La pocición 0x20 se llama temperatura, la pocición 0x21 se llama demora1 y así sucesivamente. Tambien existe otra forma de nombrar o renombrar pociciones de memoria o registro, y ya lo vimos que es con la directiva EQU. por ejemplo:

temperatura EQU H'20'
demora1 EQU H'21'
demora2 EQU H'22'

Sexta línea:

RESET ORG H'00'
GOTO INICIO
ORG H'04' ;VECTOR INTERRUPCIÓN
INTERRUP

He unificado estas líneas porque por lo general así se escribe en la mayoría de nuestros programas. Vemos con más detalles estas líneas.

RESET ORG H'00'

Aquí es en dónde empieza el CP cuando se enciende al PIC. Y estos se debe, porque cuando hay un reset por el pin MCLR o un reset interno producido por, encendido del PIC o, por ejemplo, del perro guardía, el vector reset se ubica en la pocición 0x00 de la memoria de programa.
Como pueden apreciar, hemos llamado a la pocición 0x00 con el nombre de RESET, ya que la primer columna es una etiqueta. Las etiquetas sirven para nombrar pociciones de memoria de programa.

ORG H'00' indica que se empieza a escribir desde la pocición 0x00 por lo que la siguiente instrución, quedará alojada en la pocición 0x00. ORG es una directiva, y solo sirve para el ensamblador. Esta línea, SIEMPRE debe estar y no se puede modificar, salvo la etiqueta.

Siguiente línea es GOTO INICIO, esta instrucción queda alojada en la pocición 0x00 y es un salto a la etiqueta INICIO. Este salto tiene que estar, porque en las siguientes pociciones de memoria de programa, está la interrupción, externa e interna del PIC. Por eso es necesario hacer el salto.

Siguiente línea nos encontramos con ORG H'04', como se dieron cuenta, es una directiva. Esta pocición de memoria, indica el vector de interrupción. Cuando estén habilitadas las interrupciones y una de ella se activa, el CP apuntará aquí, a la pocición 0x04.

Siguiente línea nos encontramos con la etiqueta INTERRUP. Si trabajamos con las interrupciones, aquí es donde escribiremos lo que necesitamos hacer con ellas.

Séptima línea:

;
INICIO
;

Vemos la etiqueta INICIO. Aquí vendrá el CP cuando alla un reset gracias al GOTO INICIO ubicado en la pocición 0x00 de la memoria de programa. De esta manera, saltamos un montón de instrucciones que no debemos ejecutar antes. Como por ejemplo las interrupciones si hubiese.
Por ende, a partir de esta etiqueta, estará nuestro programa principal. Configuraremos los puertos, las insterrupciones y empezaremos a darle trabajo al CP.

Octava línea:

END

Esta es una directiva y solo sirve para el ensamblador indicando que después de esta directiva, se terminó el programa. Instruciones que estén por debajo de esta línea, no serán tenido encuenta. Y esta directiva es obligatoria colocarla.
 

Adjuntos

  • banco_de_memoria_ram_del_16f877jpg_123.jpg
    banco_de_memoria_ram_del_16f877jpg_123.jpg
    86.2 KB · Visitas: 117
Atrás
Arriba