Foros de Electrónica

Comunidad de discusión sobre Automatización, Electrónica industrial, Microcontroladores y electrónica digital, Robótica, Domótica, Telemática, Tecnologías móviles, y muchos temas más.




Perdida de datos con la UART del PIC16F876


       



#1  Perdida de datos con la UART del PIC16F876
Caesar^V^

Registrado: 18 Sep 2006
Mensajes: 5
Ubicación: Lugo
citar
Hola, tengo un problema con mi proyecto final de de carrera, haber si alguien me puede ayudar a solucionarlo o sugerir algo. Gracias de antemano.

El microcontrolador ha de leer informacion proveniente de un receptor gps, la ha de procesar e introducir en una trama que posteriormente será enviada al ordenador cada minuto.

Llegué a la conclusión de que el el pic no me lee todos los datos que le envía el gps, se debe saltar alguno y los datos que obtengo en mi aplicación no son los correctos, y no sé a que se debe.

El pic está perfectamente conectado al puerto serie del ordenador y comprobado.

El gps envía información continuamente a 9600 bps, en el protocolo TSIP, que funciona asi:
<DLE> <identificador del paquete> <data string bytes> <DLE> <ETX>, y cuando en el interior de la cedena de cartacteres hay un DLE, se envia otro adicional.

Al final adjunto el codigo fuente en C, a ver si alguien ve algún otro fallo,está hecho para el compilador CCS.

Para ir detectado a que se debía el problema hice varios programas, y llegué a la conclusión de que estaba en la UART, el programa con el que lo probé fué el siguiente, es un programa espejo:

=====================================================
CODIGO DE PRUEBA DE LA UART

#include <16F876.h>
#use delay(clock=4000000)
#fuses XT,NOWDT

set_tris_c(0x80); //Configuro el pin C7 como entrada

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, enable=PIN_B7) //Configura puerto serie
#int_rda
void rda_isr() {
putc(getc()); //Transmite el dato leido cada vez que se produce una interrupción
}

void main(){
enable_interrupts(global);
enable_interrupts(int_rda); //Habilito interrupciones generales y por recepción de datos
while(1){}
}
=====================================================

Si el gps lo conecto al ordenador sin mediar por el pic me lee los datos correctamente, pero la hacerlo a través del PIC nada.

A vista de lo que hay, parece que el pic no es lo suficientemente rápido como para pocesar todos los datos que recibe. No se si sería una posible solución cambiar el cristal de cuarzo del pic de 4Mhz por uno de 20 Mhz (por que creo que con el de 4 le hes suficiente) o cambiar el pic por uno más rápido.

A ver si alguien me puede ayudar. Gracias.

=====================================================
CÓDIGO FUENTE DEL PIC

#include <16F876.h>
#use delay(clock=4000000)
#fuses XT,NOWDT

#define ETX 0x03
#define DLE 0x10

typedef struct{
int8 id;
float latitud;
float longitud;
float altura;
float clock_bias;
float time_of_fix;
}GPS_POSITION;

typedef struct{
int8 frm_num;
int8 no_gps;
float latitud;
float longitud;
float altura;
int8 satelites;
int8 checksum;
}TRAMA;

TRAMA variable;
GPS_POSITION posicion;
int8 I;

set_tris_a(0x00);
set_tris_b(0x00);
set_tris_c(0x80); //Configuro el pin C7 como entrada y los demás salida

int1 escape=FALSE;
int8 matrix[60];

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, enable=PIN_B6) //Configuro puerto serie
#int_rda
void serial_isr() { // Rutina que atiende a la interrupción de la UART
int8 i;
int8 tmpbyte;
tmpbyte=getc(); // Recojo el caracter recibido

if(escape){

switch(tmpbyte){

case (DLE): matrix[i++]=tmpbyte;
break;

case (ETX): switch(matrix[0]){ // En funcion del id del paquete lo copio en un
en un destino

case (0x4A): memcpy(&posicion,matrix,sizeof(GPS_POSITION));
break;

default:break;
}
break;

default: i=0; // El dato que se recibe aquí es un id de paquete
matrix[i++]=tmpbyte;
break;
}

escape=FALSE;

}

else
switch(tmpbyte) {

case DLE:
escape=TRUE;
break;
default:
matrix[i++]=tmpbyte;
break;
}


}


#use rs232(baud=1200, parity=N, xmit=PIN_C6, rcv=PIN_C7, enable=PIN_B7)
void txmt_frame(BYTE *ptr, BYTE len) // Trasmite los datos para transmisor de radio
{

while(len--) // Este protocolo funciona perfectamente
{
switch(*ptr)
{
case (0xC0): putc(0xDB);
putc(0xDC);
ptr++;
break;
case (0xDB): putc(0xDB);
putc(0xDD);
ptr++;
break;
default: putc(*ptr);
ptr++;
break;
}
}
putc(0xC0);
}



void main(){

enable_interrupts(global); // Habilito interrupciones general y por recepcion UART
enable_interrupts(int_rda);

variable.frm_num=0;
variable.checksum=0;
variable.latitud=0; //Inicializo variables
variable.longitud=0;
variable.altura=0;

while(1)
{

if(posicion.id==0x4A) // Si el campo tiene ese valor copio en la trama que va a enviarse
{ via radio
variable.latitud=posicion.latitud;
variable.longitud=posicion.longitud;
variable.altura=posicion.altura;
}

else{}

for(I=0;I<sizeof(TRAMA);I++) // Genero un checksum
variable.checksum+=(*((&variable)+I));

txmt_frame(&variable,sizeof(TRAMA)); // Transmito la trama
variable.frm_num++; // Numero de trama
delay_ms(60000); // Espero 1 minuto antes de enviar otra trama
}

}

=============================================

#2  Re: Perdida de datos con la UART del PIC16F876
maunix
Colaborador
Registrado: 22 Oct 2005
Mensajes: 652
Ubicación: Cordoba, Argentina
citar
Caesar. antes de ponerme a leer tu software, te consulto lo siguiente.

Tienes posibilidad de direccionar lo que sale del GPS a la PC a través del PIC?

Por ejemplo, el GPS manda los datos siempre automáticamente o requiere que el PIC le indique algo?

Si no hace falta que el PIC mande nada y el GPS manda la trama todo el tiempo, entonces podrías conectar el PIN TX a la PC a través de un MAX232, y que haga un 'eco' de todo lo que recibe. De esa forma sabrás qué recibe y que no recibe tu pic.

Por último revisa la configuración del TRISC. En los 16F el TRISC<6> debe estar en 1 para ser pin de usart. (Relee el datasheet). Tú lo has puesto en 0


Saludos

#3  
Caesar^V^

Registrado: 18 Sep 2006
Mensajes: 5
Ubicación: Lugo
citar
Hola maunix, te explico.

El GPS siempre está mandando información, algunos paquetes son de tiempo, otros de posición, velocidad, información de los satélites.... No requiere que el pic envíe comando alguno al gps.

Yo creé una aplicación en labview que me interpretase todo esto, conecto el GPS al PC a través del max232 y la aplicación funciona perfectamente.

Ahora bien, si conecto el GPS al PIC y éste al PC, de forma que lo que reciba el pic del gps lo envíe tal cual al PC (en el protocolo TSIP), recibo datos de posición y todo. Pero eses datos no son correctos, pues da latitudes de 150ºN y valores completamente incoherentes. Y esto se debe a que el PIC no envía todos los datos, se debe saltar algún dato, y al ocurrir esto, el programa del LABVIEW compone los bytes, y como se saltó alguno el PIC da valores incorrectos.

Te explico más acerca del proyecto. El receptor de GPS va a ir colocado en elemento que se desea localizar (vehículo, animal...). Este receptor cada cierto tiempo envía una trama al ordenador donde estoy yo. Todo esto va por un enlace de radiofrecuencia a 433 Mhz.
Entonces el PIC es el encargado de recoger la información del GPS y analizarla, y en función del tipo de información que recibió, meterla en una parte de la trama, que posteriormente se va a enviar.

He mirado el datasheet del pic16f876, yo creo que la configuración del puerto c está correcta, por que para que un bit de un puerto sea salida le hay que poner un 0, y para que sea entrada un 1:


Bit 7 6 5 4 3 2 1 0
Valor 1 0 0 0 0 0 0 0

1000000b=0x80


El pin C7 es el el RX de la UART y el C6 es el de TX, y creo que la configuración que le hay que poner es C6 como 0 y C7 como 1. Y transmitir el PIC transmite.

Yo creé un programa en C que enviase con la función txmt_frame el paquete de información de posición, pero en lugar de que el PIC leyese la información del GPS, la introduje yo en un array. Y me funcionó. Pero he ahí la cuestión, el PIC no lee bien, y no se por qué.

Muchas gracias. Saludos desde España.

#4  
maunix
Colaborador
Registrado: 22 Oct 2005
Mensajes: 652
Ubicación: Cordoba, Argentina
citar
Caesar^V^ escribió:
Hola maunix, te explico.
He mirado el datasheet del pic16f876, yo creo que la configuración del puerto c está correcta, por que para que un bit de un puerto sea salida le hay que poner un 0, y para que sea entrada un 1:


Bit 7 6 5 4 3 2 1 0
Valor 1 0 0 0 0 0 0 0

1000000b=0x80


El pin C7 es el el RX de la UART y el C6 es el de TX, y creo que la configuración que le hay que poner es C6 como 0 y C7 como 1. Y transmitir el PIC transmite.


Yo haría simplemente un software de ECO para que reciba algo y lo retransmita sin modificar nada.

En cuanto a la configuración de usart, es un error común el que estás cometiendo en los 16F.

Una cosa es setear el puerto para usos 'digitales' de propósito general y otra diferente es usarlo para la USART.

Te subo la parte del datasheet donde te comenta lo que te digo:

Datasheet. ds30292c. Page 95.

Bit SPEN (RCSTA<7>) and bits TRISC<7:6> have to
be set in order to configure pins RC6/TX/CK and
RC7/RX/DT as the Universal Synchronous Asynchronous
Receiver Transmitter.




Saludos

#5  
Caesar^V^

Registrado: 18 Sep 2006
Mensajes: 5
Ubicación: Lugo
citar
Hola maunix, ya he correigo ese error de la configuración de la UART tal y como tu me has dicho.

Y con el mismo programa de prueba que publiqué al principio del tema (que el pic envía lo que recibe tal cual, sin modificar nada), lo probé, y sigo teniendo el mismo problema.

El PIC se salta datos, si por ejemplo el GPS envía 5 datos el pic retransmite 3, y eso a la hora de componer los datos en la aplicación es desastroso.

Ya desesperado probé a cambiar el cristal de cuarzo de 4 Mhz por uno de 20 Mhz, pero nada, el problema sigue persistiendo.

Y ya no se que hacer, por que si el PIC pierde datos simplemente enviando lo que recibe, sin analizar nada, no me quiero ni imaginar lo que hará cuando tenga que analizar el dato que recibió e introducirlo en un array.

Si se te ocurre algo que me pueda solucionar esto te lo agradecería.

Muchas gracias. Saludos.

#6  
maunix
Colaborador
Registrado: 22 Oct 2005
Mensajes: 652
Ubicación: Cordoba, Argentina
citar
Te propongo lo siguiente que subas tu código pero como un archivo .zip

Cuando me haga un tiempo para verlo, te comento mi opinión al respecto


Saludos

#7  
Caesar^V^

Registrado: 18 Sep 2006
Mensajes: 5
Ubicación: Lugo
citar
Hola maunix, qui va publicado el codigo fuente.



Este mensaje contiene archivos adjuntos, para verlos debes estar registrado.

#8  
DIGALEQUESI

Registrado: 04 May 2008
Mensajes: 3
Ubicación: colombia
citar
el receptor gps tiene una modalidad de envio de tramas automático o manual, es decir q el tiene un pin habilitado para enviar tramas cada vez q uno se lo pida unicamente cuando se envia un uno logico al pin del receptor, deberias habilitar ese modo manual de envio, por lo que alcance a ñeer el protoclo de comunicacion es tsip, por lo q supongo q usas un receptor marca trimble, lo mas aprobable es q posea el pin q te menciono,

#9  
Ardogan

Registrado: 19 Ago 2006
Mensajes: 298
Ubicación: Argentina
citar
Una cosita que me hace un poco de "ruido": estaba viendo proyecto.c la rutina serial_isr y dentro de:
switch (tmpbyte)->if(escape) (rama de sí) en la sección default aparece:

Código: Seleccionar todo
default:    i=0;
                                 matrix[i++]=tmpbyte;
                                 break;


me parece raro encontrar i=0 en ésta parte. A ver si es como pienso, se debería entrar en esta parte del programa cada vez que se recibe un dato que no indica inicio/fin de trama no?.

Supongo que i es un contador para los bytes que recibís en la trama, y que lo usas para guardar los datos en el array/vector/matriz "matrix".
De ser así estás inicializando siempre el contador a 0 cada vez que recibís un dato que no es encabezado, puede ser eso?.

Si es así yo metería el i=0 en el else del switch(tmpbyte) case DLE que es cuando se inicia la trama no?.

Código: Seleccionar todo
void serial_isr() {
int8 i;
int8 tmpbyte;


tmpbyte=getc();

      if(escape){

            switch(tmpbyte){

                     case (DLE): matrix[i++]=tmpbyte;
                                 break;

                     case (ETX):   switch(matrix[0]){


                                       case (0x4A): memcpy(&posicion,matrix,sizeof(GPS_POSITION));
                                                    break;

                                       default:break;

                                       }

                                 break;

                     default:    [b]i=0;[/b] //[i]esto es lo que no me cierra[/i]
                                 matrix[i++]=tmpbyte;
                                 break;
                     }

            escape=FALSE;

                 }

      else
            switch(tmpbyte) {

                     case DLE:
                              [b]i=0;[/b] //[i]no debería ir acá?[/i]
                              escape=TRUE;
                              break;
                     default: //[i]esta sección tampoco me queda claro para que está[/i]
                              matrix[i++]=tmpbyte;
                              break;
                             }


}


Bueno, especulé demás, porque hay cosas que no me quedan claras con respecto a la trama: 1) se supone que el pic tiene que tomar los datos que empiecen con un caracter DLE no?,
2) cuando eso pasa se pone el bit escape=1 no?
3) Los datos que interesan son los que ingresa cuando escape = 1?. Porque como marqué arriba, no entiendo por qué en la sección default del switch del else se guardan datos.

Saludos

 Responder



Google
 


 Temas de interés 
El tema está cerrado y no puedes editar mensajes o responder Destacado: Data cable siemens RS-232
No hay mensajes nuevos Data Cable Nokia RS-232: Forum
No hay mensajes nuevos Diagrama de construcción data cable Nokia DKU-5 (USB)
No hay mensajes nuevos Data cable para siemens c65
No hay mensajes nuevos Construcción del data cable Nokia 3595

Foros de Electronica
|| Cuestiones Elementales de Electrónica || Fuentes de alimentacion || Circuitos de radio || Diseño de circuitos en general ||
|| Sistemas de Audio: Preamplificadores, Ecualizadores || Amplificadores || Reparación || Discusión ||
|| Microcontroladores y sistemas embebidos || Circuitos logicos combinacionales y secuenciales || Interfaces y Programacion || Dudas en general || Sistemas de Video || PC Hardware || Telematica y comunicaciones || Tecnologias moviles || Software Electronico || Robotica, Domotica y Mecatronica || Autotrónica || Automatizacion, Electronica industrial y de Potencia || Documentacion, circuitos y esquemas || Donde Las Ideas Convergen... || Tutoriales y Manuales || Proyectos Prácticos ||