Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

07/10/2015 #1


Finalizar rutina
Hola chicos,

tengo una duda que puede ser muy tonta pero no consigo resolver. He programado un código simple para manejar un motor paso a paso bipolar. El caso es que cuando he intentado empezar a jugar con el número de pasos me ha surgido un imprevisto. Adjunto código:

Código PHP:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#include "FUSES.h"

#define _XTAL_FREQ 4000000


void prueba()
{
        
// Primer paso

        
PORTBbits.RB0 1;
        
PORTBbits.RB1 1;
        
PORTBbits.RB2 0;
        
PORTBbits.RB3 0;
        
__delay_ms(50);

        
// Segundo paso

        
PORTBbits.RB0 0;
        
PORTBbits.RB1 1;
        
PORTBbits.RB2 1;
        
PORTBbits.RB3 0;

        
__delay_ms(50);

        
// Tercer paso

        
PORTBbits.RB0 0;
        
PORTBbits.RB1 0;
        
PORTBbits.RB2 1;
        
PORTBbits.RB3 1;
        
__delay_ms(50);

        
// Cuarto paso

        
PORTBbits.RB0 1;
        
PORTBbits.RB1 0;
        
PORTBbits.RB2 0;
        
PORTBbits.RB3 1;
        
__delay_ms(50);

        
}

int main(void) {

    
TRISBbits.TRISB0 0;
    
TRISBbits.TRISB1 0;
    
TRISBbits.TRISB2 0;
    
TRISBbits.TRISB3 0;
   
    
   
//int n = 1;

    
for(int i i<10 i++)
    {

        
prueba();
        
    }
    

como veis he creado una función que contiene la secuencia de pasos del motor paso a paso (prueba()). Mi idea era controlar el número de pasos que va dar el motor mediante el bucle for. De esta manera, el bucle for llamaría a la función prueba() 10 veces (hasta que la variable i fuera 10), por tanto, daría 40 pasos.

Pues bien, resulta que una vez programo el código en el microcontrolador, el código se ejecuta infinitamente. Es decir, el motor paso a paso va dando pasos de manera ininterrumpida.

¿Alguien tiene idea de por qué sucede esto? He probado con un return 0 al final del main pero tampoco funciona. Seguramente será una tontería.

Gracias a todos de antemano. Un saludo!
07/10/2015 #2


lo unico que se me ocurre es que el for esta reiniciando la variable i haciendo que se cicle infinitamente, prueba con un pulsador para verificar el ciclo o agrega otra condicion. ese es todo tu codigo?

puedes agregar por ejemplo j y comparar con un if.

int j=0;

if j>0 {
}
else{
ciclo for
j++;
}
07/10/2015 #3


Hola Luis30,

no creo que el problema sea el for, ya que este no inicializa la variable i cada vez que se llama a la función prueba(). Es más, he hecho la siguiente prueba:
- Sacar el contenido de la función prueba()
- Introducirlo directamente en el main()
- Quitar cualquier bucle (for, while,..)

De esta forma, OBLIGATORIAMENTE debería ejecutarse la secuencia de pasos UNA SOLA VEZ. Pero esto no sucede. El problema debe estar en la forma de finalizar el main(). Creo que es el main el que se ejecuta eternamente.
07/10/2015 #4

Avatar de Dr. Zoidberg

Agregá la línea:
Código:
while( 1 );
al final del main...
07/10/2015 #5


Hola Dr. Zoidberg,

efectivamente funciona ahora de manera correcta. Sin embargo tengo la duda de por qué pasa esto. En teoría lo que hace el bucle while(1) es quedarse eternamente en ese bucle que no tiene ninguna acción, ¿correcto?

¿Es la única manera de conseguir esto?

Muchas gracias. Un saludo
07/10/2015 #6
Moderador

Avatar de D@rkbytes

También puede ser con un bucle DO, o la instrucción SLEEP.
Pero para pruebas de funcionamiento, yo usaría una comprobación de pulsador con un IF para ejecutar la rutina.
Así puedes realizar las pruebas que quieras y no una sola vez.
07/10/2015 #7


Hola Darkbytes,

gracias por tu respuesta. Seguiré vuestros consejos.

Un saludo!
07/10/2015 #8

Avatar de Dr. Zoidberg

Galix dijo: Ver Mensaje
Hola Dr. Zoidberg,

efectivamente funciona ahora de manera correcta. Sin embargo tengo la duda de por qué pasa esto. En teoría lo que hace el bucle while(1) es quedarse eternamente en ese bucle que no tiene ninguna acción, ¿correcto?
Eso pasa por que el µC no tiene un sistema operativo a quien devolver el control cuando el programa finaliza, y como hay que mantenerlo haciendo algo, pues que se que quede "dando vueltas".. . No sé que le dice el compilador que haga cuando acaba el main, pero al parecer no es algo muy bueno que digamos...

Galix dijo: Ver Mensaje
¿Es la única manera de conseguir esto?
Naaaa.
Podés usar:
Código:
do{ }while(1);
o
Código:
for(;;);
Galix dijo: Ver Mensaje
Muchas gracias. Un saludo
07/10/2015 #9

Avatar de CarloShura

Al momento de usar el ciclo for estás dándole un valor inicial a tu variable i, por lo que cada vez que se ejecuta el ciclo i toma el valor de 1; lo que te recomiendo es declarar la variable int i = 1 al inicio del programa, es decir fuera del main(), y al momento de utilizar el ciclo for, ponerlo de la siguiente manera:

for(i ; i<10 ; i++)
{
prueba();
}

Espero sea de ayuda, espero tus comentarios.
07/10/2015 #10


Dr. Zoidberg una pregunta para que sirve poner while(1); al final del main?, lo he visto en algun codigo y no lo entiendo.
07/10/2015 #11

Avatar de Dr. Zoidberg

miglo dijo: Ver Mensaje
Dr. Zoidberg una pregunta para que sirve poner while(1); al final del main?, lo he visto en algun codigo y no lo entiendo.
Es un lazo infinito.... el µC se queda sin hacer nada.. algo como:
Código:
10 goto 10
07/10/2015 #12
Moderador

Avatar de D@rkbytes

Pues sí, aunque en realidad se está generando un bucle mientras 1 sea 1. (O sea, siempre)
Pero como no contiene instrucciones internas, el bucle no hace nada más que generar el mismo ciclo.
07/10/2015 #13

Avatar de Dr. Zoidberg

En realidad es "mientras la condicion sea verdadera" y 1 siempre es verdadero, lo mismo que cualquier cosa distinta de cero.
Como el cuerpo es una oracion vacia, lo unico que hace es evaluar la condicion, que siempre es verdadera.... y queda haciendo eso para siempre...
07/10/2015 #14


y entonces como se sale de ese bucle?
07/10/2015 #15

Avatar de Dr. Zoidberg

De ese bucle no se sale. Esta hecho para tener.al micro ocupado haciendo algo. Si necesitas salir hay que hacer otra cosa, pero eso es lo que necesitaba quien hizo la consulta
07/10/2015 #16

Avatar de JoaquinFerrero

Galix dijo: Ver Mensaje
Pues bien, resulta que una vez programo el código en el microcontrolador, el código se ejecuta infinitamente. Es decir, el motor paso a paso va dando pasos de manera ininterrumpida.

¿Alguien tiene idea de por qué sucede esto? He probado con un return 0 al final del main pero tampoco funciona. Seguramente será una tontería.
Dr. Zoidberg dijo:
No sé que le dice el compilador que haga cuando acaba el main, pero al parecer no es algo muy bueno que digamos...
No es ninguna tontería. Es algo que hay que tener en cuenta, y que a veces puede ser útil.

Lo que ocurre es que el programa, al terminar, como dice Dr. Zoidberg, no regresa a ningún sitio, por lo que el microcontrolador... sigue ejecutando el código que hay en la memoria de programa. Y al llegar al final, el micro vuelve a la posición 0, y continúa (ver pág. 796 del "Programming and Customizing the PIC Microcontroller", de Myke Predko, 3 ed., McGraw-Hill, 2008).

En un PIC18, la memoria contendrá valores 0xFFFF o 0x0000. Los diseñadores de los PIC tuvieron el detalle de hacer que esas dos combinaciones equivalen a la instrucción nop, por lo que el micro no hace nada -excepto tardar un momento-, hasta que llega al final, y recomienza en la posición 0.

En los PIC del rango medio, la memoria se suele rellenar con 0x03FFF, que equivale a la instrucción addlw 0xFF, es decir, decrementa W en 1. Y lo mismo que antes: al llegar al final, se reposiciona a la dirección 0.

Un ejemplo de para qué puede servir esto tan raro. Supongamos que estamos en un PIC16F84, con 1 Kpalabras de memoria de programa. Podemos escribir el programa más corto -que haga algo- en un PIC:
Código PHP:
    title “SHORT Is this the Shortest Possible Application?
;
Look at a Two Instruction ApplicationContinually Update
(with the “unprogrammed” ADD 0x0FF) and then use the
value for “PORTB” and “TRISB”.
;
Hardware Notes:
16F84 Running at 4 MHz
Reset is tied directly to Vcc and PWRT is Enabled.
PortB is used for Output
;
;
Myke Predko
;
99.10.26 “Short” Created
;

    list 
R=DEC
    
include “p16f84.inc”
    __CONFIG _CP_OFF 
_XT_OSC _PWRTE_ON _WDT_OFF

        org 0x03FE

        tris    PORTB           
Save WREG in TRISB
        xorwf   PORTB
f        ; XOR PORTB with the contents of WREG

        end 
La instrucción tris, lo que hace es mandar el valor de W al registro TRISB. Lo que en realidad hace es:
Código PHP:
        bsf     STATUSRP0     Bank 1
        movwf   TRISB
^0x080     Almacena WREG en TRISB
        bcf     STATUS
RP0     Bank 0 
Y luego hace un xor entre el valor de WREG y el del PORTB. Así que estamos cambiando el valor del puerto B.

A continuación, el micro se lanza a ejecutar 1022 instrucciones "addlw 0x0FF" con lo que tenemos que W se ha incrementado realmente en 2, y se ha esperado 1022 ciclos de instrucciones (una pequeña espera). Al llegar al final, el contador de programa se pone a 0, y se repite todo de nuevo.

Si ponemos un LED en RB7 (el más significativo de PORTB), veremos cómo va cambiando. Como detalle final, el programa se ha colocado (con el org) al final de la memoria de programa, para verificar con el simulador que, efectivamente, W se incrementa en 2 en cada vuelta.
07/10/2015 #17

Avatar de Dr. Zoidberg

El problema es que no conozco el mapa de memoria en el que el compilador distribuye el codigo del programa.
Si en el PC=0 hay un salto al inicio del main y las funciones estan entre este salto y el main, entonces todo funciona OK, pero si estuviera el inicio del main y las funciones a continuacion de este, la finalizacion del main produciria que el proximo codigo que se ejecute sea el de las funciones con cualquier valor en los parametros.
En tu ejemplo en assembler no hay problema, pero usar eso como referencia del compilador.... hummmmm

Mejor es programar defensivamente...
08/10/2015 #18


Muchas gracias a todos por vuestra colaboración en las respuestas. En especial a Joaquin Ferrero por su detallada explicación y Dr. Zoidberg por su implicación.

Creo que he entendido bastante bien la razón del problema y tengo ahora varias herramientas para solucionarlo gracias a vosotros. Seguiré pendiente de este tema por si alguien más aporta datos interesantes.

Un saludo a todos y gracias!
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.