RETURN donde retorna?

Hola

Estoy dando mis primeros pasos en assembler y los doy dentro del

16F628A. Vengo de C y C++, asi que tengo conocimientos en programaci=F3n, pero...

Tengo un c=F3digo (que copio al final del mensaje) con el que intento probar los temporizadores y llegar a los 5 minutos, pero me encontre con un funcionamiento extra=F1o del RETURN. El tema esta en que despu=E9s de la dir 0x00 hago un GOTO a Inicio, y cuando llega al RETURN (tres lineas despu=E9s del label Tiempo) vuelve a la linea "GOTO Inicio" posterior a 0x00 y entra en bucle. Esperaba que RETURN me retorne a la linea posterior al GOTO. =BFEstoy equivocado? =BFComo se resuelve?

Pero en esto aprendi a desconfiar de todo, :D estoy probando el c=F3digo en MPLAB 8.10 y no se si es el entorno o RETURN se comporta diferente a como esperaba.

=BFComo funciona RETURN?

;---------------Encabezado------------- LIST P=3D16F628 #include ;--------------------------------------

ORG 0x00 GOTO Inicio

;---------------- OCIO ----------------

OCIO SLEEP

;---- Atenci=F3n de la interrupci=F3n -----

ORG 0x04 GOTO Led GOTO OCIO

;--------------- Inicio ---------------

Inicio BSF STATUS,5 ; cambio al banco 0 (TRISB) CLRF TRISB ; seteo todo TRISB como salida

MOVLW 0x07 ; cargo w con 00000111 MOVWF OPTION_REG ; el Divisor =3D 256 BCF STATUS,5 ; regreso al banco 0

; GIE habilita todas las interrupciones ; T0IE habilita la interrupi=F3n del timer 0 MOVLW 0XA0 ; cargo w con 10100000 MOVWF INTCON ; habilitamos GIE y T0IE CLRF PORTB ; limpiamos PORTB

;------------- Tiempo -----------------

Tiempo MOVLW 0XD8 ; cargo w con 216 MOVWF TMR0 ; lo paso a TMR0 RETURN

;---------------- Led -----------------

Led BTFSS PORTB,0 ; si el led est=E1 apagado GOTO LedEnc ; envio a encender BCF PORTB,0 ; si no, lo apago GOTO LedFin

LedEnc BSF PORTB,0 ; enciendo el led GOTO LedFin

LedFin BCF INTCON,2 ; borro la bandera T0IF GOTO Tiempo ; cargo el temporizador RETFIE ; regreso habilitando la int

;-------------------------------------- END ;--------------------------------------

Reply to
LucasBols
Loading thread data ...

no programo ensamblador pero,,,, ¿y si en vez de return usas goto te falla igual?. si llamas a una rutina con ¿era call? debes usar return pero si llamas rutina con goto debes salir con goto... vamos, no me hagas mucho caso, es por si te sirve de pista....

un saludo

"LucasBols" escribió en el mensaje de noticias: snipped-for-privacy@d45g2000hsc.googlegroups.com...

Reply to
Carmelo J. Morales Muñoz

un goto es solo un salto, debe de existir una insuccion call (ahora mismo no recuerdo el juego de instucciones del pic), cuando haces un call si que se almacena la direccion de retorno, y entonces return vuelve a la instuccion siguiente al call. Ojo porque la pila solo puede almacenar 4 (creo recordar) direcciones, por lo que solo puede haber 4 call's anidadas

call es el equivalente a llamar a una funcion en C, return es igual al return del c, y goto es igual al goto del c

Reply to
Nolo Pongo

Como te dicen, debes usar un CALL para que te devuelva a la linea siguiente. El GOTO es un salto incondicional. CALL y las interrupciones te almacenan la dirección de retorno automáticamente en el Stack. En estos Pic's no existe PUSH ni POP. En el Stack puedes almacenar 8 posiciones de retorno, tanto de interrupciones como de Call y en caso de que metas mas, se sobreescriben. Esto no es, a mi entender, un obstáculo sino una ventaja, ya que procurarás mantener todo bien clarito y sin muchos saltos de un lado al otro en el código, que lo hace indescifrable. Empiezas con un GOTO inicio que está muy bien, para saltarte la dirección

0x04 de interrupción y luego ejecuta Inicio, pero cuando lo termina sigue con Tiempo, ya que no hay ninguna instrucción en medio y cuando llega a Return, como el Stack está a 0 te manda a la dirección 0x00. En el manejo de la interrupción usas Goto en vez de Call. Al final debes poner un Retfie, sino sigue con Inicio. También usas un SLEEP desde dentro de la interrupción que te para el reloj del chip, con lo que el temporizador tampoco anda. El Sleep te para el oscilador y hay cosas que dejan de funcionar. Para algo que sirve es para dormir el chip, con lo que consume menos, y despertarlo con una interrupción por un cambio en Rb0 o por Rb4-7, por ejemplo, al tocar el teclado. ;---------------Encabezado------------- LIST P=16F628 #include ;--------------------------------------

ORG 0x00 GOTO Inicio

;---------------- OCIO ----------------

OCIO SLEEP yo no lo utilizaría aquí

;---- Atención de la interrupción -----

ORG 0x04 GOTO Led call GOTO OCIO ?

retfie ;--------------- Inicio ---------------

Inicio BSF STATUS,5 ; cambio al banco 0 (TRISB) banco 1 CLRF TRISB ; seteo todo TRISB como salida

MOVLW 0x07 ; cargo w con 00000111 MOVWF OPTION_REG ; el Divisor = 256 BCF STATUS,5 ; regreso al banco 0

; GIE habilita todas las interrupciones ; T0IE habilita la interrupión del timer 0 MOVLW 0XA0 ; cargo w con 10100000 MOVWF INTCON ; habilitamos GIE y T0IE CLRF PORTB ; limpiamos PORTB seguría con Tiempo. Aquí pondría

Main, el programa principal,

que puede ser solo un bucle:

Main NOP

GOTO Main

;------------- Tiempo -----------------

Tiempo MOVLW 0XD8 ; cargo w con 216 MOVWF TMR0 ; lo paso a TMR0 RETURN

;---------------- Led -----------------

Led BTFSS PORTB,0 ; si el led está apagado GOTO LedEnc ; envio a encender BCF PORTB,0 ; si no, lo apago GOTO LedFin

LedEnc BSF PORTB,0 ; enciendo el led GOTO LedFin

LedFin BCF INTCON,2 ; borro la bandera T0IF GOTO Tiempo ; cargo el temporizador RETFIE ; regreso habilitando la int RETURN si usas CALL y deja el

RETFIE en la Interrupción.

;-------------------------------------- END ;-------------------------------------- Esto es lo que he visto, pero puedo estar equivocado. El código resultante puede que no funcione o lo haga a una velocidad que no verás el Led parpadear. Depúralo y nos comentas. Saludos.

Reply to
Observer

Muchas gracias a todos por las respuestas, con CALL se soluciono el poblema. Pero ahora me surgio el tema del SLEEP...

Este PIC tenia un programa que realizaba un bucle de llamadas telefonicas mediante un ISD1416P y un SIM340CZ, pero como el bucle a veces duraba mas de 5 minutos, el PIC calentaba y se quemaba. No existe la posibilidad de un cooler por el habitaculo donde va el PIC y por el consumo. Estoy intentando desarrollar un nuevo programa que, despues que lance la primer llamada, se ponga a dormir durante un par de minutos y lance la segunda llamada (para evitar el calentamiento). El programa anterior, despues de lanzar la primer llamada, entraba en un bucle que calculaba el tiempo transcurrido segun los ciclos que consumia el bucle, y por eso el PIC terminaba quemandose.

En este momento estoy familiarizandome con los timers, despues extendere el conteo desde los pocos milisegundos del timer a unos minutos mediante un decremento, pero de una forma o la otra, cuando procese la interrupcion del timer, supongo que voy a tener que llamar a un SLEEP para que el procesador descanse hasta la proxima interrupcion, que sera la que utilizare para la rutina de decremento o para comunicar que los minutos ya han pasado.

Pero Observer, me decis que el SLEEP para el reloj, como me sugeris que lo resuelva?

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 yo no lo

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0call

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0?

=A0 =A0 segur=EDa con Tiempo.

=A0 =A0 =A0 =A0RETURN si usas

nte

Reply to
LucasBols

Este PIC tenia un programa que realizaba un bucle de llamadas telefonicas mediante un ISD1416P y un SIM340CZ, pero como el bucle a veces duraba mas de 5 minutos, el PIC calentaba y se quemaba. No existe la posibilidad de un cooler por el habitaculo donde va el PIC y por el consumo. Estoy intentando desarrollar un nuevo programa que, despues que lance la primer llamada, se ponga a dormir durante un par de minutos y lance la segunda llamada (para evitar el calentamiento). El programa anterior, despues de lanzar la primer llamada, entraba en un bucle que calculaba el tiempo transcurrido segun los ciclos que consumia el bucle, y por eso el PIC terminaba quemandose.

En este momento estoy familiarizandome con los timers, despues extendere el conteo desde los pocos milisegundos del timer a unos minutos mediante un decremento, pero de una forma o la otra, cuando procese la interrupcion del timer, supongo que voy a tener que llamar a un SLEEP para que el procesador descanse hasta la proxima interrupcion, que sera la que utilizare para la rutina de decremento o para comunicar que los minutos ya han pasado.

Pero Observer, me decis que el SLEEP para el reloj, como me sugeris que lo resuelva?

----------------------------------------------------------------------- Es que es muy raro que el Pic se caliente. ¿Cual es la frecuencia del cristal? ¿Has conectado a alguna salida del Pic un Relé directamente u otra carga importante? ¿Tienes condensadores de desacoplo en la alimentación? Un Pic en condiciones normales puede consumir 10 mW o menos y esto es un consumo ridículo que no lo calienta. Dime algo.

Reply to
Observer

No se como han conectado el pic, yo solamente lo programo, me lo encargaron por ese tema.

Pero si me decis que no calienta, entonces lo pondre en la placa de pruebas, lo dejare que ejecute varios ciclos y vere cual es el problema del calentamiento.

Otra cosita:

Modifique el codigo anterior, y en el MPLAB ejecuta los SLEEP, pero al agregarle una variable de decremento, si la variable la ubico en 0x0C, como sugiere algun manual, ocasionalmente el decremento se "come" varios pasos, por ej: salta en un ciclo de 120 a 70, cambie la dir a

0x20 que es un registro de proposito general como indica la datasheet del PIC y al ejecutarse, hace un decremento y muere, aparentemente va al sleep y ahi queda, que puede ser?

el cod es este:

;---------------Encabezado------------- LIST P=3D16F628 #include ; ---------Mapa de la memoria ---------

decr equ 0x0E

;--------------------------------------

ORG 0x00 CALL Inicio CALL Tiempo

;---------------- OCIO ----------------

DORMIR SLEEP

;---- Atenci=F3n de la interrupci=F3n -----

ORG 0x04 CALL Dcrmnt GOTO DORMIR

;--------------- Inicio ---------------

Inicio BSF STATUS,5 ; cambio al banco 1 (TRISB) CLRF TRISB ; seteo todo TRISB como salida

MOVLW 0x07 ; 0x07 cargo w con 00000111 MOVWF OPTION_REG ; el Divisor =3D 256 BCF STATUS,5 ; regreso al banco 0

; GIE habilita todas las interrupciones ; T0IE habilita la interrupi=F3n del timer 0 MOVLW 0XA0 ; cargo w con 10100000 MOVWF INTCON ; habilitamos GIE y T0IE CLRF PORTB ; limpiamos PORTB movlw 0xC8 ; 0x64 100 movwf decr ; lo cargo para decrementar RETURN

;----------- Decrementador ------------

Dcrmnt decfsz decr,1 ; decrementa y si no llego a 0 retfie ; retorna habilitando la int call Led ; si llego, cambia al led retfie ; retorna habilitando la int

;------------- Tiempo ----------------- ; Temporizaci=F3n =3D (255-TMR0) * Divisor de Frecuencia Tiempo MOVLW 0X00 ; 0XD8 cargo w con 216 MOVWF TMR0 ; lo paso a TMR0 RETURN

;---------------- Led -----------------

Led movlw 0xC8 ; 0x64 100 movwf decr ; lo cargo para decrementar BTFSS PORTB,0 ; si el led est=E1 apagado GOTO LedEnc ; envio a encender BCF PORTB,0 ; si no, lo apago GOTO LedFin

LedEnc BSF PORTB,0 ; enciendo el led GOTO LedFin

LedFin BCF INTCON,2 ; borro la bandera T0IF GOTO Tiempo ; cargo el temporizador RETURN ; regreso habilitando la int

;-------------------------------------- END ;--------------------------------------

rga

Reply to
LucasBols

No debes ubicar la variable en 0x0C ni en 0x0E, ya que están ocupadas ( en el 16F84 no están ocupadas). Las posiciones libres están a partir de la 0x20. Mira el datasheet.

Por otro lado, el programa se te para en cuanto pone al chip en SLEEP, ya que no puede salir de aquí con este diseño. No debes usar para nada el sleep ya que no lo necesitas y el calentamiento del Pic debe deberse a la proximidad del módulo GSM, falta de blindaje o falta de desacoplo en la alimentación.

Animo !

Saludos.

Reply to
Observer

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.