Como se hacen pic16f877a

hola me gustaria que me dijeran como se escriben las siguientes sentencias o condiciones en el .asm del mplab:

if else
while
do while
for
switch

si pudieran hacerlo con un pequeño ejemplo estaria mejor. gracias de antemano.
 
Los condicionales en asm del MPLAB yo no los recomiendo. Primero que nada, porque no se pueden usar bien en runtime, ya que el simulador solo compila la opcción por verdadero y no ambas. De todas maneras, te pongo ejemplitos como para que te des una idea de la sintáxis y te sea más ituitivo el asunto, por lo que preguntas debes programar en C.



Código:
variable temp=1
if temp=0
   movlw 0x0A
else 
   movlw 0x1E
endif

Código:
#define test
IFDEF test
  movlw 0x01
ifndef test
 movlw 0x02
endif

Código:
multiply macro arg1, dest_hi,
 local i=0
 movlw arg1
 movwf mulplr
 while i<8
   addwf dest_hi
 i +=1
endw
endm

Te adjunto un valioso documento sobre MPLAB, ahi encontrarás los ejemplos que hago mención.

Saludos
 

Adjuntos

  • 51410b_802.pdf
    188.7 KB · Visitas: 46
hola hoy me surgio un problema usando el "if"
tengo lo siguiente

...
hola equ 0x01 ;aqui son las primeras lineas creo que es como se declara "hola"
como variable
...
clrf hola ;con esto creo que pongo en 0 "hola"

...(primerasparte)

if hola>2
call subrutina ;aqui solo ira a la subrutina si "hola" es mayor a 2
else
endif
incf hola,1 ;si "hola" no era mayor a 2 se icrementa en 1 y no va a la subrutina
...(segundaparte)

if hola>2
call subrutina ;aqui solo ira a la subrutina si "hola" es mayor a 2
clrf hola ;con esto pongo en 0 "hola" y se repite el ciclo
else
endif
...
goto (primeraparte)
subrutina
NOP ;NO OPERACION ; la subrutina solo hara tiempo con "NOP" (claro que son unos cuantosa mas) para alargar la duracion de las partes del
programa
retfie
end


con ese programa esperaba que se ejecutara dos veces el programa de manera normal y a la tercera duraran un poco mas sus dos partes pero no resulto asi nunca va a la subrutina.

segun yo "hola" se maneja con numeros decimales y que "incf hola,1" le suma 1 cada ciclo y que "clrf hola" regresa a "hola" a cero.
y que "if hola>2" es que cuando hola es mayor que 2 hase lo que sigue.

asi que les pregunto que tengo mal, yo pienso que podria ser la manera en la que declaro "hola" y que es el primer programa que hago yo solo^^.

agradeceria que me ayudaran un poco.
 
aqui esta, te daras cuenta que es un poco diferente a lo que dije porque es de sies partes el programa, pero en esencia es lo mismo a lo que explique antes.

hehe va de nues
 

Adjuntos

  • hola_112.asm
    18 KB · Visitas: 14
A ver a ver, decime que es los que queres hacer? el código esta muy desprolijo, sin ir más lejos hasta finaliza con un "retfie", osea, me gustaria saber que es lo que supuestamente hace, y yo te hago mi versión utilizando los condicionales y como debe presentarse un código, porque por ejemplo, haces más de 30 lineas cuando las podrias hacer con solo 2 líneas. Contame un poco de que se trata, es tan redundante el código que no se llega a interpretar la idea.
 
hehe bueno quiero que mi programa genere 6 pulsos, estos 6 pulsos varian en 6 tiempos,

en el tiempo uno:
pulso1 en 1 logico
pulso2 en 0 logico
pulso3 en 0
pulso4 en 0
pulso5 en 1
pulso6 en 1

en el tiempo dos:
pulso1 en 1 logico
pulso2 en 1 logico
pulso3 en 0
pulso4 en 0
pulso5 en 0
pulso6 en 1

en el tiempo tres:
pulso1 en 1 logico
pulso2 en 1 logico
pulso3 en 1
pulso4 en 0
pulso5 en 0
pulso6 en 0

em el tiempo cuatro:
pulso1 en 0 logico
pulso2 en 1 logico
pulso3 en 1
pulso4 en 1
pulso5 en 0
pulso6 en 0

en el tiempo cinco:
pulso1 en 0 logico
pulso2 en 1 logico
pulso3 en 1
pulso4 en 1
pulso5 en 1
pulso6 en 0

y por ultimo en el sexto tiempo:
pulso1 en 0 logico
pulso2 en 0 logico
pulso3 en 0
pulso4 en 1
pulso5 en 1
pulso6 en 1

y que entren en un ciclo interminable regresando del sexto tiempo al primero.

tambien queria que la duracion de cada tiempo fuera de 1.3milisegundos para eso segun la frecuencia del cristal determinare cuantos NOP's pondre pero bueno el programa hara dos ciclos con 1.3milisegundos por tiempo y luego hara un tercero mas largo algo asi como 34milisegundos por cada tiempo. y luego repetira los dos cilos de 1.3milisegundos y despues uno de 34milisegundos y asi secesivamente.

bueno esos es todo lo que quiero que haga por el momento
espero que te quede claroy grasias por la ayuda

quiza despues tambien tenga que hacer que yo seleccione con un boton el tiempo que quiera que se tarde cada tiempo asi que no duden que preguntare si tengo alguna duda.
 
Hola, creo que hay una confusión entre lo que pregunta metalblood y lo que está respondiendo MaMu.
Al preguntar por como hacer un if creo que no se refiere a directivas de compilación, sino como sería el equivalente en un programa asm.
Por ejemplo, sea el siguiente condicional:
Código:
if Contador = 25 then
   Instrucciones de la rama del sí
else
  Instrucciones de la rama del no
endif

en assembler se hacen con las instrucciones btfss o btfsc, decfsz, incfsz en conjunto con goto

Código:
InicioIf:
  movlw 25
  subwf Contador, W
  btfss STATUS,Z
  goto RamaNo
RamaSi:
  Instrucciones de la rama del si
  goto FinIf
RamaNo:
  Instrucciones de la rama del no
FinIf:
  sigue el resto del programa

En la primera parte (las instrucciones entre InicioIf y RamaSi) pueden haber variantes, depende de si lo que se testea es el valor de un registro (también va a ser distinto si se pregunta por < o >) o el de un bit (se reduce a btfss Registro, bit ; o btfsc Registro, bit; y ya vendría el goto RamaNo).

Eso en cuanto a un if, después para hacer un switch es una cadena de if anidados.
Para un for te recomiendo usar decfsz e incfsz depende la dirección de cuenta.
Para hacer lazos while, do while; bueno, no quiero dar todo hecho, proponé algo y lo debatimos.
 
metalblood dijo:
hola hoy me surgio un problema usando el "if"
tengo lo siguiente

...
hola equ 0x01 ;aqui son las primeras lineas creo que es como se declara "hola"
como variable
...
clrf hola ;con esto creo que pongo en 0 "hola"

...(primerasparte)

if hola>2
call subrutina ;aqui solo ira a la subrutina si "hola" es mayor a 2
else
endif
incf hola,1 ;si "hola" no era mayor a 2 se icrementa en 1 y no va a la subrutina
...(segundaparte)

if hola>2
call subrutina ;aqui solo ira a la subrutina si "hola" es mayor a 2
clrf hola ;con esto pongo en 0 "hola" y se repite el ciclo
else
endif
...
goto (primeraparte)
subrutina
NOP ;NO OPERACION ; la subrutina solo hara tiempo con "NOP" (claro que son unos cuantosa mas) para alargar la duracion de las partes del
programa
retfie
end

Lo que pasa, es que declaraste a hola en la pocición de la RAM en 01h y esta pocición, está recervada para uso del pic. Por ejemplo para el pic16F877A, corresponde al TMR0. Para uso del usuario, en este pic, corresponde desde la dirección 20h
 
hola, para hacer los lazos while creo que es de la siguiente manera

movlw 00

iniciowhile

addlw 1 ;creo que con esto se aumenta en 1 el acumulador cada vuelta
movwf contador
goto subrutina
btfss contador,1
goto iniciowhile
goto to finwhile

finwhile

...sigue el programa


me parece que esto hara que se repita la subrutina hasta que el registro contador llegue a 10
porque el btfss tiene que cheque el bit uno el cual yo creo que es el segundo de derecha a izquierda del registro.
bueno diganme que tengo mal.
y tambien quiero saber en que se manejan los registros del contador? hexadecimal, decimal o binario o en que.
 
Bueno, un par de aclaraciones. En vez de usar "goto subrutina" podrías meter directamente el código de la subrutina ahí mismo. Salvo que quieras (por cuestiones de comodidad o gusto) que se llama a una subrutina, en cuyo caso tendrías que usar la instrucción call.
Porque sino la subrutina tendría que conocer la dirección adonde tiene que retornar cuando finalice, y es algo que no se sabe (por lo menos no a priori) si la subrutina se llama desde dos o más lugares en el programa.

Y en cuanto a la cantidad de repeticiones, al usar como condición btfss contador,1 se ejecutaría el lazo solo dos veces.
Fijate que estás comparando el bit 1 del registro contador, si ese bit es = 1 se saltea la instrucción goto iniciowhile y se ejecuta goto finwhile. Eso es lo que hace esa instrucción.
Tu confusión viene porque creo que estás mezclando binario con decimal. El salto se produce cuando contador = 0000 0010; lo que llevado a decimal es 2:
contador = 0x1 + 1x2 + 0x4 + 0x8 + 0x16 + 0x32 + 0x64 + 0x128 = 2
Si tenés dudas sobre ésto busca conversión de binario a decimal y viceversa, que si no lo tenés claro del todo es un lío

porque el btfss tiene que cheque el bit uno el cual yo creo que es el segundo de derecha a izquierda del registro.

el bit 0 es el menos significativo (más a la derecha), y el bit 7 es el más significativo (más a la izquierda).

También veo que estás repitiendo el lazo una cierta cantidad de veces fija, eso sería más un for que un while. Un while sería para cuando uno no sabe cuántas veces se va a repetir el lazo, pero sí sabe que si se da cierta condición el lazo debe parar de repetirse.
Mi versión de un for sería
Código:
  movlw cuentasFor; 
    ;en lugar de cuentasFor reemplazar por la 
    ;cantidad de veces que se repite el lazo
  
  movwf ContadorFor, F; ContadorFor = W = cuentasFor

InicioFor
   ...;código que se repite dentro del for
  
  decfsz ContadorFor, F; esta instrucción decrementa ContadorFor, 
    ;compara el resultado con cero, y si es cero 
    ;saltea la próxima instrucción
  
  goto InicioFor;

  ...;ya terminó el for, a partir de acá sigue el resto del programa
 
hola gracias por la correcion.

bueno aqui va otro intento de while que creo me quedo en for pero porfavor dime si esta mal.


clrf hola;
clrf hola2;
clrw
....inicioejemplo
movlw hola2; nose si esto sea correcto
movwf hola
iniciowhile1
call subrutina
decfsz hola,f
goto iniciowhile1
finwhile1
sigueejemplo
btfsc PORTA,0
call sumador
btfsc PORTA,1
call restador
goto inicioejemplo;

sumador
incf hola2,1
retfie
restador
decfsz hola2,1
retfie

segun yo es como un for que se repetira el numero de veces que se determine segun el numero de veces que la entrada del porta,0 halla sido detectada en "1"
y le quitara una iteracion si la entrada porta,1 es detectada en "1"
 
hola a todos, bueno el programa que puse arriba ya le he hecho algunos cambios:

inicioejemplo
addwf hola2,0
movwf hola
clrw
iniciofor1
call subrutina
decfsz hola,f
goto iniciofor1
finformaciónr1
segundaparte
btfsc PORTB,0
call sumador
btfsc PORTB,7
call restador
goto primertiempo;

sumador
;addlw 1
;movwf hola2
incf hola2,1
retfie
restador
decf hola2,1
retfie

bueno este programa lo simule en el "isis 7 professional" y para mi sorpresa funciono, cada vez que el portb,0 esta a 1 logico (en el tiempo por el que el programa pasa por la linea "btfsc PORTB,0") el programa repite una vez mas la subrutina, y de la misma forma si portb,7 esta a 1 logico (en el tiempo por el que el programa pasa por la linea "btfsc PORTB,7") el programa repite una vez menos la subrutina.

bueno gracias a todos por ayudarme.
¿Pero esto es un while?
 
Primero una cosa importante, para volver de una subrutina no uses retfie, puede que funcione pero no está pensado para eso. retfie se utiliza para retornar de rutinas de interrupción y para habilitar las interrupciones globales (ambas cosas a la vez).
Para retornar de una subrutina utiliza return (solamente hace el retorno) o retlw (retlw además copia un valor literal al registro W).

En tu penúltimo mensaje habías puesto "movlw hola2; nose si esto sea correcto"; y tu duda es justificada, movlw está pensado no para mover información entre registros, sino para cargar una constante en el registro W. Uno puede poner movlw 25 o movlw 0x1F; es decir, el parámetro de movlw es siempre un valor numérico (un literal) de 8bits, pero no un registro.

Y ahora vamos al programa. El primer lazo definitivamente es un for, porque se va a repetir un número fijo de veces, independientemente de lo que pase en el resto del universo (o casi, si le tiran una bomba al pic seguramente dejará de ejecutarse el for :) ). Se ejecutaría hola2 + W (siendo el valor de W el que tenía antes de ejecutar la instrucción addwf hola2,0 ) veces.

En la segunda parte yo diría que es más bien un if doble, porque se ejecuta una sola vez. Sería como:

Código:
if RB0=1 then
  sumador
else 
  nada
finIf
if RB7 = 1 then
  restador
else
  nada
finIf
goto primerTiempo

No sé adonde salta la última instrucción, si salta para arriba (volviendo a ejecutar algo que ya se ejecutó antes) sería un lazo infinito, que por cierto, siempre tiene que estar presente en un pic para que funcione (salvo el particular caso de que se maneje pura y exclusivamente con interrupciones).
En cuanto a hacer un while, no me preocuparía tanto por si es un while o un do-while o un for, mientras el programa haga lo que se quiere y sea entendible no me haría problema por eso.
 
Ardogan dijo:
...
En tu penúltimo mensaje habías puesto "movlw hola2; nose si esto sea correcto"; y tu duda es justificada, movlw está pensado no para mover información entre registros, sino para cargar una constante en el registro W. Uno puede poner movlw 25 o movlw 0x1F; es decir, el parámetro de movlw es siempre un valor numérico (un literal) de 8bits, pero no un registro.

Lo que entiendo que metalblood quería hacer es: movfw hola2

lo que transfiere el contenido de hola2 al registro W.
 
hola

Ardogan es verdad se deben de usar return y no retfie. gracias por la aclaracion.

y la instruccion de mov fw no sabia que existia pero ahora ya la conosco y si esa es la que se usaria. gracias

seguire intentando hacer el while hasta entonces.
 
Atrás
Arriba