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 información 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(0B);
putc(0C);
ptr++;
break;
case (0B): putc(0B);
putc(0D);
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
}
}
=============================================
El microcontrolador ha de leer información 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(0B);
putc(0C);
ptr++;
break;
case (0B): putc(0B);
putc(0D);
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
}
}
=============================================