|
|
View previous topic :: View next topic |
Author |
Message |
Juan Guest
|
RS232 interrupt problem |
Posted: Tue Dec 07, 2004 11:24 pm |
|
|
Hi, I have a PIC16F876A and im using ccs c compiler to make a project,
I connected a GPS in the serial port (pin c6 and pin c7), and im reading the data via the interruption #int_rda , the thing is that with this code i only receive two characters and then i think it hangs, because the interruption is never called again, can anyone help me?, im desperate, whats wrong?
i plan to put the data in an eeprom via i2c.
#include <16F876A.h>
#device adc=8
#use delay(clock=4000000)
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT
#define EEPROM_SCL PIN_C3
#define EEPROM_SDA PIN_C4
#use i2c(Master,Slow,sda=PIN_C4,scl=PIN_C3,force_hw)
#use rs232(baud=4800,xmit=PIN_C6,rcv=PIN_C7,PARITY=N,BITS=8)
#include <string.h>
//variables de la interrupcion serial
unsigned char cuenta=0; //caracter q recibo del serial
unsigned char cuenta2=0; //cuenta de comas
unsigned char bandera=1; //(interrupcion serial)
unsigned char cadena; //variable en la interrupcion del serial
unsigned char cadena_1[]={"GPRMC"}; //(interrupcion serial)
unsigned char cadena_2[7]; //mensaje recibido para checar si mensaje es correcto(interrupcion serial)
unsigned char fin_mensaje=0;
unsigned char recibido;
unsigned char tiempo[6];//guardo el tiempo
unsigned char valido; //V-> no valido, A->valido
unsigned char latitud[9];//latitud
unsigned char latitudNS;//N->Norte, S->Sur
unsigned char longitud[10];//longitud
unsigned char longitudEW;//E->Este, W->Oeste
unsigned char fecha[6];//fecha
//prototipos
void Inicializa_Hardware();
void Inicializa_GPS(); //desactivo y activo mensajes
void enter(); //enter de mensajes hacia el GPS
void enter(){
putc(0x0D);
putc(0x0A);
}
void Inicializa_GPS(){
printf("$PSRF103,00,00,00,01*24"); //desactivo mensajes
enter();
printf("$PSRF103,01,00,00,01*25");
enter();
printf("$PSRF103,02,00,00,01*26");
enter();
printf("$PSRF103,03,00,00,01*27");
enter();
printf("$PSRF103,05,00,00,01*21");
enter();
printf("$PSRF103,04,00,09,01*29"); //activo mensaje cada 9 segs RMC
enter();
}
void Inicializa_Hardware(){
enable_interrupts(GLOBAL);
enable_interrupts(INT_RDA);
}
#int_rda //interrupcion del serial
void serial_isr(){
recibido=getc();
putc(recibido);
enter();
if (bandera){ //checa si mensaje es GPRMC
if (recibido!=0x0A){
cadena_2[cuenta]=recibido;
cuenta++;
putc(cuenta+0x30);
enter();
if (cuenta==7){
cadena=strstr(cadena_2,cadena_1);
if (cadena!=0){
bandera=0;
cuenta=0;
}else{
cuenta=0;
}
}
}else{//si es fin de mensaje 0x0A
cuenta=0;
fin_mensaje=1;
}
}else{ //mensaje bueno, si es GPRMC
cadena=recibido;
if(cadena!=0x2C){ //diferente de coma
switch (cuenta2){
case 0: tiempo[cuenta]=cadena;
cuenta++;
break;
case 1: valido=cadena;
break;
case 2: latitud[cuenta]=cadena;
cuenta++;
break;
case 3: latitudNS=cadena;
break;
case 4: longitud[cuenta]=cadena;
cuenta++;
break;
case 5: LongitudEW=cadena;
break;
case 8: fecha[cuenta]=cadena;
cuenta++;
break;
case 9:
bandera=1;
cuenta=0;
cuenta2=0;
break;
case 10:
bandera=1;
cuenta=0;
cuenta2=0;
break;
case 11:
bandera=1;
cuenta=0;
cuenta2=0;
break;
default:break;
}
}else{//fue coma
cuenta2++;
cuenta=0;
}
}
}
void main(void){
delay_ms(2000);
Inicializa_GPS();
delay_ms(2000);
Inicializa_Hardware();
cuenta=0;
bandera=1;
while(1){
if (fin_mensaje){
printf("latitud: ");
printf(latitud);
fin_mensaje=0;
}
}
} |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 08, 2004 12:45 am |
|
|
The problem is that you are sending several characters to the UART,
from inside the #int_rda function. The UART transmitter has a transmit
buffer (TXREG) and an output shift register. As soon as you write
two characters to the UART, you have filled up both those registers.
When you try to write a third character soon after that, the program
execution will wait in a loop, until the TXREG is empty.
While it is waiting for the TXREG to become available, you have characters
coming in to the UART on the receive pin. But you can't read them with
a getc() function, because the code is waiting for TXREG. So then
the UART gets an overrun error and the receiver locks up.
This is what is happening. So how to fix it ?
The best way is probably to move all the transmit code, such as putc(),
outside of the #int_rda function. In fact, move almost all of the code
that you have inside the #int_rda function to another function, outside
of it. The #int_rda function should only have code to get a character
and put it in a circular buffer. You should check the buffer and process
the characters in it, in code that runs in main(). Then your "lock up"
problems will not happen. See the example file, EX_SISR.C, for sample
code to do a circular buffer for the UART receiver.
That file is in this folder: c:\Program Files\Picc\Examples
Also, to clear an overrun error in the UART receiver, add the ERRORS
parameter to the end of your #use rs232() statement. You will still
lose a character when an overrun occurs, but at least the program will
not lock up.
#use rs232(baud=4800,xmit=PIN_C6,rcv=PIN_C7, ERRORS) |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|