Autor Tema: Problema con timer e interrupcion en XC8  (Leído 2293 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado RSC

  • PIC10
  • *
  • Mensajes: 23
Problema con timer e interrupcion en XC8
« en: 05 de Febrero de 2016, 18:13:26 »
Hola soy nuevo :D tengo un problema con mi programa que hace lo siguiente(uso el 18f2550)
manda un "dale", el programa del pc lo recibe y envia un string que luego recibe el pic, lo procesa y hace los calculos necesarios para obtener el valor de pap1 y pap2(hasta aca funciona bien) luego abro timer1 y timer3 y respecto a los valores de pap1 y pap2 escribo en los timers y se abren las interrupciones para que se muevan los motores paso a paso, funciona bien una sola vez pero no repite el proceso del while(1), en el soft del pc visualizo 2 "dale" que el primero corresponde a la primer señal y el segundo corresponde a que termino de hacer todo y volvio a empezar el while(como tiene que ser) pero no lo hace otra vez como deberia, comprobe y el problema esta en los timers e interrupcion(que no tengo experiencia)
en resumen, solamente repite una vez el ciclo while(1) y deberia repetirlo infinitas veces
 adjunto el codigo

CODIGO
void main(void) {

        TRISB=0;
     i=0,i1=0,i2=0,i3=0;
    // i1=49;i2=10,i3=89,i4=77;
  CloseUSART();

PORTBbits.RB0=0; PORTBbits.RB2=0;
  //PORTBbits.RB1=0;while(BusyUSART());Delay10KTCYx(255);printf("hola\r\n");
PORTBbits.RB2=1;//for(a=0;a<10;a++)Delay10KTCYx(255);
//Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(255);
/* while(1){
     printf("dale");
Delay10KTCYx(255);Delay10KTCYx(255);
 }*/

 while(1){
     h1=0;h2=0;
      OpenUSART(USART_TX_INT_OFF &USART_RX_INT_OFF &USART_ASYNCH_MODE &USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 25);
     while(BusyUSART());
           printf("dale");
     getsUSART(r1,9);
for(i2=0;i2!='\n';i2++)if(r1[i2]==',')
for (p=0;p<i2;p++){pas1[p]=r1[p];pas1[4]='\0';}
 newpaso1=atoi(pas1);
for(i2=0;i2!='\n';i2++)if(r1[i2]==',')
      i3=i2+1; //printf("\r\n%d\r\n",i3);
for (p1=i3;p1<10;p1++){pas2[p1-i3]=r1[p1];}
 newpaso2=atoi(pas2);
 if (newpaso1==1013) PORTBbits.RB1=1;

r1[9]='\0';
pap1=newpaso1-oldpaso1;
oldpaso1=newpaso1;
pap2=newpaso2-oldpaso2;
oldpaso2=newpaso2;

//HASTA ACA FUNCIONA BIEN(ciclo while se repite)

INTCONbits.PEIE=1;
   INTCONbits.GIE=1;

  if (pap1>pap2){
         k=(200*pap1/pap2);
     tmr3=((-k/(0.2*2))+65536);
         tmr1=((-200/(0.2*2))+65536);
        }
          if (pap2>pap1){
         k=(200*pap2/pap1);
     tmr1=((-k/(0.2*2))+65536);
         tmr3=((-200/(0.2*2))+65536);
        }

OpenTimer1( TIMER_INT_ON & T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_2 & T1_OSC1EN_ON & T1_SYNC_EXT_ON );
 OpenTimer3( TIMER_INT_ON & T3_16BIT_RW & T3_SOURCE_INT & T3_PS_1_2 & T3_SYNC_EXT_ON );
WriteTimer1(tmr1);
 WriteTimer3(tmr3);
 while(h1<pap2*2 && h2<pap1*2);
 INTCONbits.PEIE=0;
   INTCONbits.GIE=0;
}
}
//HASTA ACA EL CICLO WHILE FUNCIONA UNA SOLA VEZ

INTERRUPCIONES
void interrupt interrupcionDeAlta(void)
        {
              if(PIR1bits.TMR1IF==1 && h2<pap1*2){
                     PIR1bits.TMR1IF=0;
                     LATBbits.LATB3=!LATBbits.LATB3;
       WriteTimer1(tmr1);
        h2++;    }

  if( PIR2bits.TMR3IF==1 && h1<pap2*2 ){
         PIR2bits.TMR3IF=0;
         LATBbits.LATB4=!LATBbits.LATB4;
         WriteTimer3(tmr3);
               h1++;   }
        }

Desde ya muchas gracias  :-/

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con timer e interrupcion en XC8
« Respuesta #1 en: 05 de Febrero de 2016, 23:13:03 »
Hola voy a comenzar a ver el programa y me encuentro con muchisimos problemas respecto a como se debe escribir el programa. Espero que no lo tomes a mal, es una cuestion de orden tanto para vos como para aquel que vea el codigo.

Escribo esto solo por que tenes que enteder que tu programa tiene que ser visto por otras personas ademas de vos ( aunque sea un proyecto tuyo personal)

JAMAS JAMAS hagas lo que estas haciendo. Estas cosas asi:

Código: C
  1. i=0,i1=0,i2=0,i3=0;

No tiene sentido para nadie, ni siquiera se para que sirven, distinto seria algo asi:

Código: C
  1. i=0;            // Variable usada para un Loop
  2.         Tmr1Loop=0;     // Variable usada para mantener las entradas a la interrupcion del timer1
  3.         Tmr2Loop=0;     // Variable usada para mantener las entradas a la interrupcion del timer2
  4.         i3=0;           // Variable usada ....

- Otra cosa.. Organizate. Primero inicia las variables.. Luego va la parte de Setup del micro, y finalmente tu loop infinito.
- Identa el codigo. No escribas todo en una linea

Código: C
  1. //PORTBbits.RB1=0;while(BusyUSART());Delay10KTCYx(255);printf("hola\r\n");
  2. PORTBbits.RB2=1;//for(a=0;a<10;a++)Delay10KTCYx(255);
  3. //Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(255);

Es ilegible eso. Tener que estar buscando los comentarios, no sabes donde empieza y termina el for, el while, etc. Es MALA costumbre. El codigo un poco mas identado:

Código: C
  1. while(BusyUSART());
  2.         Delay10KTCYx(255);
  3.         printf("hola\r\n");
  4.         PORTBbits.RB2=1;
  5.         //for(a=0;a<10;a++) {
  6.                 //Delay10KTCYx(255);
  7.         }
  8.         //Delay10KTCYx(255);
  9.         //Delay10KTCYx(255);
  10.         //Delay10KTCYx(255);
  11.         //Delay10KTCYx(255);

Ahora sigo viendo el codigo completo y luego te digo, pero es para que vayas viendo el problema. Ademas faltan las definiciones de las variables.


Dejo tu codigo identado.. Y ahora por fin se ven muchisimos errores que antes habia oculto por ahi.

Código: C
  1. void main(void){
  2.  
  3.         TRISB=0;
  4.         i=0;            //
  5.         i1=0;           //
  6.         i2=0;           //
  7.         i3=0;           //
  8.  
  9.         // i1=49;i2=10,i3=89,i4=77;
  10.         CloseUSART();
  11.  
  12.         PORTBbits.RB0=0;
  13.         PORTBbits.RB2=0;
  14.         //PORTBbits.RB1=0;
  15.         while(BusyUSART());
  16.         Delay10KTCYx(255);
  17.         printf("hola\r\n");
  18.         PORTBbits.RB2=1;
  19.         //for(a=0;a<10;a++)
  20.         {
  21.                 //Delay10KTCYx(255);
  22.         }
  23.         //Delay10KTCYx(255);
  24.         //Delay10KTCYx(255);
  25.         //Delay10KTCYx(255);
  26.         //Delay10KTCYx(255);
  27.  
  28.         /* while(1)
  29.         {
  30.                 printf("dale");
  31.                 Delay10KTCYx(255);
  32.                 Delay10KTCYx(255);
  33.         }*/
  34.  
  35.         while(1)
  36.         {
  37.                 h1=0;
  38.                 h2=0;
  39.                 OpenUSART(USART_TX_INT_OFF &USART_RX_INT_OFF &USART_ASYNCH_MODE &USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 25);
  40.                 while(BusyUSART());
  41.                 printf("dale");
  42.                 getsUSART(r1,9);
  43.                 for(i2=0;i2!='\n';i2++)
  44.                 {
  45.                         if(r1[i2]==',')
  46.                         {
  47.                                 for (p=0;p<i2;p++)
  48.                                 {
  49.                                         pas1[p]=r1[p];pas1[4]='\0';
  50.                                 }
  51.                         }
  52.                 }
  53.                 newpaso1=atoi(pas1);
  54.                 for(i2=0;i2!='\n';i2++)if(r1[i2]==',')
  55.                 i3=i2+1;
  56.                 //printf("\r\n%d\r\n",i3);
  57.                 for (p1=i3;p1<10;p1++)
  58.                 {
  59.                         pas2[p1-i3]=r1[p1];
  60.                 }
  61.                 newpaso2=atoi(pas2);
  62.                 if (newpaso1==1013)
  63.                 {
  64.                         PORTBbits.RB1=1;
  65.                 }
  66.  
  67.                 r1[9]='\0';
  68.                 pap1=newpaso1-oldpaso1;
  69.                 oldpaso1=newpaso1;
  70.                 pap2=newpaso2-oldpaso2;
  71.                 oldpaso2=newpaso2;
  72.  
  73.                 //HASTA ACA FUNCIONA BIEN(ciclo while se repite)
  74.  
  75.                 INTCONbits.PEIE=1;
  76.                 INTCONbits.GIE=1;
  77.  
  78.                 if (pap1>pap2)
  79.                 {
  80.                         k=(200*pap1/pap2);
  81.                         tmr3=((-k/(0.2*2))+65536);
  82.                         tmr1=((-200/(0.2*2))+65536);
  83.                 }
  84.                 if (pap2>pap1)
  85.                 {
  86.                         k=(200*pap2/pap1);
  87.                         tmr1=((-k/(0.2*2))+65536);
  88.                         tmr3=((-200/(0.2*2))+65536);
  89.                 }
  90.  
  91.                 OpenTimer1( TIMER_INT_ON & T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_2 & T1_OSC1EN_ON & T1_SYNC_EXT_ON );
  92.                 OpenTimer3( TIMER_INT_ON & T3_16BIT_RW & T3_SOURCE_INT & T3_PS_1_2 & T3_SYNC_EXT_ON );
  93.                 WriteTimer1(tmr1);
  94.                 WriteTimer3(tmr3);
  95.                 while(h1<pap2*2 && h2<pap1*2);
  96.                 INTCONbits.PEIE=0;
  97.                 INTCONbits.GIE=0;
  98.         }
  99. }
  100.  
  101.  
  102. INTERRUPCIONES
  103. void interrupt interrupcionDeAlta(void)
  104. {
  105.         if(PIR1bits.TMR1IF==1 && h2<pap1*2)
  106.         {
  107.                 PIR1bits.TMR1IF=0;
  108.                 LATBbits.LATB3=!LATBbits.LATB3;
  109.                 WriteTimer1(tmr1);
  110.                 h2++;
  111.         }
  112.  
  113.         if( PIR2bits.TMR3IF==1 && h1<pap2*2 )
  114.         {
  115.                 PIR2bits.TMR3IF=0;
  116.                 LATBbits.LATB4=!LATBbits.LATB4;
  117.                 WriteTimer3(tmr3);
  118.                 h1++;
  119.         }
  120. }

Mi pregunta antes de continua con el programa es.... como estas manejando el motor PaP ? Por que veo que estas activando 2 salidas nomas, como si dieras un pulso para un lado o para el otro y hubiera un driver entre medio.

Por ahora solo espero que tomes los consejos y no digas "pero yo me entiendo asi" como me sucedio con otra persona y creo que todavia sigue sin saber por que no le funciono el codigo.
Respecto al programa como dije lo estoy viendo y tratando de entender que hiciste o intentaste hacer.
« Última modificación: 05 de Febrero de 2016, 23:35:07 por KILLERJC »

Desconectado RSC

  • PIC10
  • *
  • Mensajes: 23
Re:Problema con timer e interrupcion en XC8
« Respuesta #2 en: 05 de Febrero de 2016, 23:35:09 »
Hola, primero que nada perdon por postear una cosa asi no me di cuenta   :oops:  y gracias por ordenarlo y por la paciencia
para controlar los motores pap estoy usando los drivers a4988 pololu(arduino detected jaja) que dandole pulsos se mueven los motores, no conecte la direccion de los motores todavia(el pin direccion del driver lo puse a positivo para que se mueva en una sola direccion por ahora) por lo que RB3 y RB4 mueve cada motor
gracias

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con timer e interrupcion en XC8
« Respuesta #3 en: 05 de Febrero de 2016, 23:44:24 »
No te preocupes, solo te lo decia para que "mejores" realmente se ven muchos codigos asi. Que lo unico que hacen es que al momento de haber un problema nadie sabe donde comenzar a buscar.

Solo deseo pedirte 2 cosas mas:

- Como se envia el string al PIC para darle la "velocidad" a los motores, es decir que le envias

- Que pongas las declaraciones de las varaibles. Ya que no se que son i1 i2 i3 h0 h1, es decir si son int, char, etc. Al igual que r1, cuantas posiciones de memoria posee. r1[10] ?

Desconectado RSC

  • PIC10
  • *
  • Mensajes: 23
Re:Problema con timer e interrupcion en XC8
« Respuesta #4 en: 06 de Febrero de 2016, 00:01:54 »
variables
        char r1[10],pas1[4],pas2[4];
     int a,i,i1,i2,i3,i4,len,p,p1=0,newpaso1,newpaso2,oldpaso1,oldpaso2;
     long k=0,tmr1=0,tmr0=0;
     long pap1,pap2,tmr1,tmr3;
long h1=0,h2=0;
fuses
#include <xc.h>
#include <plib/usart.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<plib/timers.h>

#pragma config PLLDIV=5,
#pragma config FOSC=HSPLL_HS
#pragma config CPUDIV = OSC1_PLL2

#pragma config USBDIV=2
#pragma config VREGEN = ON
//#pragma config FOSC=HS
#pragma config WDT=OFF
#pragma config PBADEN=OFF
#pragma config LVP=OFF
#pragma config PWRT =ON
#pragma config DEBUG=OFF
#pragma config MCLRE = OFF
#define EAUSART_V5

void putch(char c){//esto es para usar el printf con usart en xc8
while(!TXIF) continue;
TXREG = c;}

uso un cristal de 20mhz y con los fuses lo subo a 48mhz

el string de la pc al pic se envian del estilo asi
 ****,****
donde *es un numero(tambien puede leer asi ***,****) separa los numeros que estan antes y despues de la coma y los guarda en el string pas1 y pas2 que despues lo convierte en integer con atoi
no le envio la velocidad a los motores sino la cantidad de pasos que tiene que hacer de acuerdo a los grados que se tiene que mover de acuerdo a la cinematica inversa, por ejemplo, si con las ecuaciones de  cinematica inversa me dice que para el punto (x,y) se tiene que mover x1angulos el motor 1 y x2angulos el motor 2 los transformo en pasos(numeros enteros) y los mando al pic, se mueve pero lo hace 1 sola vez T-T

Desconectado RSC

  • PIC10
  • *
  • Mensajes: 23
Re:Problema con timer e interrupcion en XC8
« Respuesta #5 en: 06 de Febrero de 2016, 13:07:00 »
ya me funciono  :-/ :-/ :-/ hice 3 cambios, no se cual es el que funciono  :mrgreen:
1) cambie INTCONbits.PEIE=0;INTCONbits.GIE=0; por  CloseTimer1();CloseTimer3();
2)tenia declarada 2 veces la variable k, osea en una ponia long k=0-, y abajo ponia long k; borre la ultima y cuando comienza el while(1)lo inicio con k=0;
3)cambie pap1=newpaso1-oldpaso1;
oldpaso1=newpaso1;
pap2=newpaso2-oldpaso2;
oldpaso2=newpaso2;
por
pap1=newpaso1;
pap2=newpaso2;
para ver si me sumaba los pasos en vez de ir concadenandolos y si me funciono(no creo que sea esto porque igual deberia repetir el while(1))
gracias por todo, saludos  :lol:

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con timer e interrupcion en XC8
« Respuesta #6 en: 06 de Febrero de 2016, 14:08:36 »
Bueno veo que te funciono, pero tenes muchos errores, voy a ir agregando aca, y luego vos veras si lo cambias o no:

- Problemas, en el sentido que no funcionarian como uno "espera"
- Errores, en el sentido que estan mal posicionados
- Y tambien algunas cosas que deberias mejorar para que a simple vista se note.


Primero decirte una cosa. La estructura del programa normalmente es algo asi:

Código: C
  1. void main() {
  2.  
  3.         // Configuracion de todos los modulos: oscilador, puertos, UART, Timers, etc
  4.  
  5.         while(1)               //Loop infinito
  6.        {
  7.                        //Programa
  8.        }
  9.  
  10. }
  11.  
  12. void interrupt interrupcion()
  13. {
  14.  
  15.        if ( flag_interrupcion )                   //Pregunto por el flag SOLO
  16.        {
  17.               Limpio_flag();
  18.               // Lo que debo hacer
  19.        }
  20. }


Ahora si, con esa estructura en mente. Ahora vamos a tu codigo. Lo primero que vemos es que:

Código: C
  1. OpenUSART( USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 25);
  2.         OpenTimer1( TIMER_INT_ON & T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_2 & T1_OSC1EN_ON & T1_SYNC_EXT_ON );
  3.         OpenTimer3( TIMER_INT_ON & T3_16BIT_RW & T3_SOURCE_INT & T3_PS_1_2 & T3_SYNC_EXT_ON );

Todo esto deberia estar en la zona de "Setup" y no en el while en el que se este configurando el modulo una y otra ves, deberias configurarlo 1 sola ves y listo.
Y ojo con el TRISB=0; intenta ponerlo por encima de eso, por que seguro que si tenes la UART en el puerto B, tal ves el OpenUART te lo modifique! Asi que si pones TRISB=0 despues de eso estarias sobreescribiendolo.

Código: C
  1. char r1[10],pas1[4],pas2[4];
  2.      int a,i,i1,i2,i3,i4,len,p,p1=0,newpaso1,newpaso2,oldpaso1,oldpaso2;
  3.      long k=0,tmr1=0,tmr0=0;
  4.      long pap1,pap2,tmr1,tmr3;
  5. long h1=0,h2=0;

Estas teniendo Muchisimas variables y ya vamos a ver el tema de la UART.
Mirando un poco como haces para separarlo me encuentro con esto:

Código: C
  1. for(i2=0;i2!='\n';i2++)
  2.                 {
  3.                         if(r1[i2]==',')
  4.                         {
  5.                                 for (p=0;p<i2;p++)
  6.                                 {
  7.                                         pas1[p]=r1[p];
  8.                                         pas1[4]='\0';
  9.                                 }
  10.                         }
  11.                 }

Y lo primero que veo es tu "condicion" para el for, en el que i2 va dese 0 a '\n', Pero esto no quiere decir que va a revisar hasta que r1[j] sea igual a '\n'. Si no que '\n' para el micro es un caracter ASCII y tiene una traduccion en hexadecimal, que es 10 ( Line feed )

http://www.asciitable.com/index/asciifull.gif

Entonces tu for se convertiria en lo mismo que :

Código: C
  1. for(i2=0;i2!=10;i2++)

Entrando un poco mas en el for nos encontramos con otras cosas, que ahora voy a hacerte entrar en conciencia. SIEMPRE SIEMPRE desconfia de la entrada de un usuario, por que puede enviar CUALQUIER COSA. Y la otra es que tenes que tener en cuenta como funcionan las string en C, las string son una coleccion (array) de caracteres, y terminan cuando encuentra un caracter nulo: '\0' , o 0x00 en hexa. tu getsUART() NO pone ese caracter nulo. Es tu deber.

Otra cosa mas.. Como sabes que solo manda un '\n' y no un '\r' (retorno de carro tambien ? ).
Es todo un tema pero que tenes que protejerte de eso.

Luego tambien esta en tu programa principal algo asi:

Código: C
  1. while(h1<pap2*2 && h2<pap1*2);

Tu programa principal no deberia quedarse esperando. Al menos como lo estas haciendo.
La UART va a seguir recibiendo y recibiendo caracteres hasta que no pueda recibir mas y ahi dejara de recibir. Por eso mismo no estoy muy de acuerdo con el tema de hacer un getsUART() como lo hiciste, y soy mas partidiario de las interrupciones para las comunicaciones. Pensa que si en el tiempo que esta atrapado en ese while envias:

Código: [Seleccionar]
1234,5678
Y el PIC posee solo 2 lugares, cuando llegue nuevamente al getsUSART va a tomar el 12 nomas ( suponiendo que se destrabe al tener el error de overrun la UART ) y si envias otra ves lo mismo, lo que vas a tener en r1[] es algo asi:

Código: [Seleccionar]
121234,56
Lo cual no es lo que se intento hacer y lo peor es que de ahora en adelante quedo mal todo, por que quedo "78" dentro de la UART volviendose a repetir el error. Por eso prefiero los datos de la UART por interrupcion. Como consejo por ahora ( por que a veces es necesario) intenta no poner while dentro del while(1).

Si fuera un mundo ideal en el que siempre vas a tener los datos y una coma podes resumir todo eso en:

Código: C
  1. for ( i = 0; i<9 ; i++)
  2. {
  3.         if(r1[i]==',')
  4.         {
  5.                 r1[i]='\0';
  6.                 IndiceSegundoNumero = i+1;
  7.         }
  8.         if(r1[i]=='\n' || r1[i]=='\r')
  9.         {
  10.                 r1[i]='\0';
  11.         }
  12. }
  13. r1[9] = '\0';                           //Por si las dudas no habia ningun caracter nulo
  14.  
  15. Paso1 = atoi(r1);
  16. Paso2 = atoi(&r1[IndiceSegundoNumero]);

Lo demas no lo vi demasiado, aunque solo deberia nombrar una cosa mas que es la funcion atoi(), y que deberias tener en cuenta. Cuando esta funcion NO recibe un numero ( ejemplo vos queres convertir "123," devuelve un 0. Y deberias actuar en consecuencia, es decir debes actuar indicando que hay un error etc.

Código: C
  1. PasoMotor1 = atoi(pas1);
  2. if(PasoMotor1==0)
  3. {
  4.    // Posible error, ( por que podriamos haber pasado un numero 0 )
  5. }

Esto es lo ultimo y luego te dejo que hagas el codigo como quieras.

En la interrupcion no podes hacer esto:

Código: C
  1. if(PIR1bits.TMR1IF==1 && h2<pap1*2)

Por que en algun momento se va a disparar la interrupcion del Timer1 pero no va a poder entrar ahi. Entonces no se va a limpiar el flag, y cuando salga de la interrupcion al no limpiarse el flag va a volver a entrar quedando atrapado en la rutina de interrupcion para siempre. Algo correcto seria:

Código: C
  1. if(PIR1bits.TMR1IF==1)
  2.         {
  3.                 PIR1bits.TMR1IF=0;
  4.                 if(h2<pap1*2)
  5.                 {
  6.                         LATBbits.LATB3=!LATBbits.LATB3;
  7.                         WriteTimer1(tmr1);
  8.                         h2++;
  9.                 }
  10.         }

Si observas ahora SI estoy borrando la flag de interrupcion cuando se produzca y no estoy cambiando los valores de puerto para nada. Pero ese no es el unico error, vos tenes que darte cuenta que la idea del programa es que este continuamente ejecutandose lo del while(1) ( Loop principal ) y solo cuando dispare una interrupcion entre aca y salga continuando lo del while.
Peeero dentro del while tenemos:

Código: C
  1. h1=0;
  2. h2=0;

Es decir que nunca tendrias a h1 y h2 lo suficientemente alto, ya que lo estas poniendo a 0 siempre. Pensa de la interrupcion como un programa "paralelo" al principal ( main ) que se va a ejecutar cuando debe. Pero como ves uno puede afectar al otro.
« Última modificación: 06 de Febrero de 2016, 14:21:47 por KILLERJC »

Desconectado RSC

  • PIC10
  • *
  • Mensajes: 23
Re:Problema con timer e interrupcion en XC8
« Respuesta #7 en: 06 de Febrero de 2016, 15:27:21 »
gracias por las aclaraciones, analizas muy bien el codigo y yo soy un desastre que hace todo rapido  :mrgreen:

Código: C
  1. void main() {
  2.  
  3.         // Configuracion de todos los modulos: oscilador, puertos, UART, Timers, etc
  4.  
  5.         while(1)               //Loop infinito
  6.        {
  7.                        //Programa
  8.        }
  9.  
  10. }
deberia ser asi pero no me lo toma con el getsUSART y tambien vi que en el foro de microchip muchos tenian este problema, cada vez que usaban el getsUSART debian declarar otra vez el openUSART, porque sino funcionaba una sola vez el getsUSART, debe ser un problema del usart.h

no sabia eso del i2!='\n' era igual que 10, muy buen dato lo voy a corregir
con el tema de la usart yo puse que priemero mande un "dale" el soft pc recibe el "dale", lo procesa y le manda la cantidad de pasos, hasta que comienza de nuevo y se repite y le manda el "dale" para que reciba de nuevo, es como una interrupcion(creo)
el h1 y el h2 van a obtener el valor maximo de h1<pap2*2 porque le puse el while(h1<pap2*2 && h2<pap1*2); horrible pero funciona ^^ se supone que tendria que hacer otras cosas mientras se esta moviendo pero modifique tanto el codigo para que me funcione... muchas gracias por todos los consejos los voy a corregir, este año recien veo pic en la facu asi que voy a aprender bien
saludos  :-/

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con timer e interrupcion en XC8
« Respuesta #8 en: 06 de Febrero de 2016, 16:02:54 »
getsUSART podes ver el codigo y es algo asi:

Código: C
  1. void getsUSART(char *buffer, unsigned char len)
  2. {
  3.   char i;    // Length counter
  4.   unsigned char data;
  5.  
  6.   for(i=0;i<len;i++)  // Only retrieve len characters
  7.   {
  8.     while(!DataRdyUSART());// Wait for data to be received
  9.  
  10.     data = getcUSART();    // Get a character from the USART
  11.                            // and save in the string
  12.     *buffer = data;
  13.     buffer++;              // Increment the string pointer
  14.   }
  15. }

Es decir lo unico que hace es tomar el array e ir llenandolo letra a letra, y el dato lo toma por getcUSART. getcUSART imagino que sera simplemente leer el registro RCREG ( es decir lo que llega a la UART )

El DataRdyUSART() simplemente es la bandera de interrupcion de la UART RX. Ojo que la bandera de interrupcion no significa que va a entrar, la bandera de interrupcion se pone a 1 cuando se cumple la condicion de esa bandera, en este caso recibir un caracter, y para que funcione realmente la interrupcion es necesario habilitarla, aca usa simplemente esta para saber si puede o no leer el registro RCREG.

El mayor problema del getsUSART es que la gente piensa al comienzo:

- Que el PIC puede mantener todos los caracteres posibles enviados por el PC , ( recorda que se envian de forma serial, 1 por 1 ), hay algunos pic que pueden mantener 2 (1+1 es lo mas comun), otros 3 ( 2 + el registro de entrada que no es accesible por las personas), y otros micros varios mas.
- O que el PIC no recibe mientras no se este ejecutando el getsUSART()

Y esos son los errores mas comunes. Por eso te decia antes que si tenes el getsUSART y el while ese, y llegan caracteres desde la PC,  tal ves por que no esperaste a que terminara, o tal ves por que queres pararlo, te vas a encontrar con los problemas estos.

El modulo mismo posee varios bits indicando cuando ocurren esos problemas:

 RCSTAbits.OERR         // Overrun Error, es decir enviaron mas caracteres y no se llego a hacer lugar para estos
 RCSTAbits.FERR         // Frame Error, Cuando hay una falla en el paquete enviado y no respeta el Frame del protocolo.

Para cada uno de esos hay que actuar acorde.. No recuerdo muy bien pero por ejemplo se que para un error y que vuelva a recibir se debe deshabilitar la recepcion y volverla a habilitar. ( Lo cual hace el OpenUART y CloseUART)

Entonces es por eso que seguro tienen problemas, al no conocer exactamente como es que funciona el PIC y la comunicacion.

Citar
con el tema de la usart yo puse que primero mande un "dale" el soft pc recibe el "dale", lo procesa y le manda la cantidad de pasos, hasta que comienza de nuevo y se repite y le manda el "dale" para que reciba de nuevo, es como una interrupcion(creo)

Esa es la gran diferencia. Pensa que la UART es un estante con 2 lugares, llega tu primer letra llenas el primer lugar, y va llegando la segunda y va llenando el 2do lugar. Para quitar eso de ahi y hacer mas espacio, deberia leer el registro RCREG (es decir lo recibido). Tu codigo permite que pueda haber un overrun como comente antes ya que lo que saca de ese "estante" es el getsUSART pero no lo va a poder hacer atrapado en el while, mientras que si vos realmente actuas en la interrupcion, es decir cada ves que reciba 1 caracter entra a la interrupcion para ponerlo en el array que desees. Nunca deberias tener el problema del overrun. Ya que apenas se recibe uno se saca uno.

Citar
se supone que tendria que hacer otras cosas mientras se esta moviendo pero modifique tanto el codigo para que me funcione

La idea de lo que planteo es para que vos puedas agregar mas cosas sin que te afecte el programa, mas que nada esa era la finalidad, tal ves agregando algo termines con un problema y que se deba al codigo inicial.

Un ejemplo simple para agregar seria decirte que quiero que cuando presione la S en el teclado de la PC, deje de girar el motor PaP ya sea por que cometiste un error antes o lo que se te ocurra. Esto con tu codigo no lo vas a poder hacer de forma simple por que va a estar atrapado en el while.

Citar
muchas gracias por todos los consejos los voy a corregir, este año recien veo pic en la facu asi que voy a aprender bien

De nada, solo decirte que estamos aca para responder cualquier duda que tengas (Siempre y cuando tengamos idea de la respuesta :P ).
Y suerte en la facu. Vas a ver que a medida que empieces a entender el PIC te va a ser mas facil. Y te vas a adentrar un poco mas en como funciona/registros

PD: Aprende a leer el datasheet, especialmente los modulos y como funcionan. Vas a ver que esas funciones como OpenUSART simplemente configuran los registros que dice el datasheet.
Y por ejemplo en tu codigo, si deseas detener el timer, no hace falta cerrarlo y volver a abrirlo. Hay algunos timer como el Timer1 que posee un bit que permite parar su cuenta o activarlo para que siga contando:

T1CONbits.TMR1ON = 1;

( tal ves no coincida el nombre del registro pero el bit esta )
Pero otros Timers como el Timer0 no se pueden parar! y siempre estan contando.
« Última modificación: 06 de Febrero de 2016, 16:12:45 por KILLERJC »

Desconectado RSC

  • PIC10
  • *
  • Mensajes: 23
Re:Problema con timer e interrupcion en XC8
« Respuesta #9 en: 07 de Febrero de 2016, 22:58:06 »
Hola, gracias por todas las aclaraciones estaba estudiando para la facu, cualquier cosa puedo preguntar? recien lo agarro de nuevo y me doy cuenta de que los motores giran pero no como los grados que les estoy indicando(antes si lo hacian)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con timer e interrupcion en XC8
« Respuesta #10 en: 07 de Febrero de 2016, 23:02:40 »
Siempre y cuadno este a nuestro alcance podes preguntar todo lo que desees, si no hay respuestas es por que seguro la mayoria no conoce para poder responderte o tal ves no lo vio.

Respecto a pasar de grados a pasos: Estaras calculando mal los pasos.