CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

RS232 interrupt problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Juan
Guest







RS232 interrupt problem
PostPosted: Tue Dec 07, 2004 11:24 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 08, 2004 12:45 am     Reply with quote

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)
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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