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:
void main() {
// Configuracion de todos los modulos: oscilador, puertos, UART, Timers, etc
while(1) //Loop infinito
{
//Programa
}
}
void interrupt interrupcion()
{
if ( flag_interrupcion ) //Pregunto por el flag SOLO
{
Limpio_flag();
// Lo que debo hacer
}
}
Ahora si, con esa estructura en mente. Ahora vamos a tu codigo. Lo primero que vemos es que:
OpenUSART( USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 25);
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 );
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.
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;
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:
for(i2=0;i2!='\n';i2++)
{
if(r1[i2]==',')
{
for (p=0;p<i2;p++)
{
pas1[p]=r1[p];
pas1[4]='\0';
}
}
}
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.gifEntonces tu for se convertiria en lo mismo que :
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:
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:
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:
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:
for ( i = 0; i<9 ; i++)
{
if(r1[i]==',')
{
r1[i]='\0';
IndiceSegundoNumero = i+1;
}
if(r1[i]=='\n' || r1[i]=='\r')
{
r1[i]='\0';
}
}
r1[9] = '\0'; //Por si las dudas no habia ningun caracter nulo
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.
if(PasoMotor1==0)
{
// Posible error, ( por que podriamos haber pasado un numero 0 )
}
Esto es lo ultimo y luego te dejo que hagas el codigo como quieras.
En la interrupcion no podes hacer esto:
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:
if(PIR1bits.TMR1IF==1)
{
PIR1bits.TMR1IF=0;
if(h2<pap1*2)
{
LATBbits.LATB3=!LATBbits.LATB3;
WriteTimer1(tmr1);
h2++;
}
}
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:
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.