Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problems to handle RS232 interrupts in CCS

Status
Not open for further replies.

Plateau

Junior Member level 3
Junior Member level 3
Joined
Jan 4, 2012
Messages
30
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,288
Visit site
Activity points
1,553
lks, is everybody ok?

I'm making a Track System using a GSM and GPS module, both controlled by a PIC18F4680. At the moment, I'm facing a big problem to handle the data that come through USART using the interrupt approach. I don't know why, but after enabling the RS232 receive data available (#INT_RDA) interrupt, the LCD stops working (lcd_putc or printf through LCD don't work) and the microcontroller seems to stuck in some part.

My code is below. If someone can help me with these problems, feel free for making changes in my code.

Thanks in advance,

Pedro Rosa.

P.S: The compiler used was CCS 4.130

main.c

Code:
#include <18f4680.H>
#include <defines.h>
#include <global.c>

#use delay(clock=16610000)
#fuses HS,NOWDT,NOPROTECT,NOLVP

#use rs232 ( baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=SIM900D, bits=8, ERRORS ) 
#use rs232 ( baud=9600, xmit=PIN_C5, stream=PK2, bits=8, ERRORS ) 


#include <flex_lcd.c>
#include <functions.c>

void main(){

   setup_timer_0(RTCC_OFF);  				 // Configuração do Timer0
   setup_timer_1(T1_DISABLED);               // Configuração do Timer1
   setup_timer_2(T2_DISABLED,0,1);           // Configuração do Timer2
   setup_ccp1(CCP_OFF);                      // Configuração do CCP1
   setup_comparator(NC_NC_NC_NC);            // Configuração dos Comparadores
   setup_vref(FALSE);                        // Configuração da Tensão de referência

lcd_init();

delay_ms(500);
fputs("ABCD",PK2);

enable_interrupts(GLOBAL);

inicializaPIC();

while(1){
	output_toggle(LED_VERMELHO);
	delay_ms(500);
}
}

defines.h

Code:
/*
Header destinado a DEFINES
*/

//#define LED_USART_GSM PIN_D2
//#define LED_BUTTON PIN_D1

/*LEDs para diagnóstico*/
#define LED_VERMELHO PIN_D0
#define LED_VERDE PIN_D2
#define LED_AMARELO PIN_D1

/*SIM900D*/
#define PPWR_SIM900D PIN_D3
#define PRX_SIM900D PIN_C7
#define PTX_SIM900D PIN_C6
#define SIM900_OK 1

/*UP501*/
#define PRX_UP501 PIN_C4 //Software USART

/*Celular*/
#define tamNumCelular 13 //Comprimento máximo do número do celular
#define posStatusCadastro 0 //Posi;áo que indica se há ou náo celular cadastrado
#define posInicialCelular 1 //Posição inicial para armazenar o celular
#define posFinalCelular (posInicialCelular + tamNumCelular - 1) //Posição final para armazenar o celular

/*EEPROM*/
#define OFFSET 0x0000

function.c
Code:
void inicializaPIC(){
	
	/*Alterna Leds para indicar inicialização*/
	output_high(LED_VERMELHO);
	delay_ms(1000);
	output_high(LED_VERDE);
	delay_ms(1000);
	output_high(LED_AMARELO);
	delay_ms(1000);	
	output_low(LED_AMARELO);
	delay_ms(1000);		
	output_low(LED_VERDE);
	delay_ms(1000);	
	output_low(LED_VERMELHO);	
	
	/*Carregar variáveis globais*/	
	temCelularCadastrado = getTemCelCadastrado();
	if(temCelularCadastrado == 'S'){
		numCel = getCelCadastrado();
	}
	else{
		output_high(LED_AMARELO);		
		/*Checar se a inicialização foi bem sucedida*/
		if(inicializaGSM() != SIM900_OK ){
			int16 stuckTime = 0;
			for(;;){
				/*LEDs piscando a cada 1s */
				output_toggle(LED_VERMELHO);
				output_toggle(LED_VERDE);
				output_toggle(LED_AMARELO);
				delay_ms(500);
				stuckTime++;
				/*Resetar o PIC após 60s*/
				if(stuckTime == 120){
					/*Desligar o SIM900D através do pino*/
					output_high(PPWR_SIM900D);
					delay_ms(2000);
					output_low(PPWR_SIM900D);
					reset_cpu();
				}
			}			
		}//Ao receber o SMS
		//+CMTI: "SM",2
		//posSMSRecebido = chegouSMS();					
	}	
}

int8 inicializaGSM(){
	int8 status = 0;
	output_high(LED_VERMELHO);
	delay_ms(2000);
	
	/*Ligar o SIM900D através do pino*/
	output_high(PPWR_SIM900D);
	delay_ms(2000);
	output_low(PPWR_SIM900D);
	/*--------------------------------*/
	
	/*Delay de 25s para sincronismo com a rede GSM*/
	delay_ms(25000);
	
	/*Checar se o SIM900D está conectado a rede*/
	status = isGSMOk();
	output_low(LED_VERMELHO);
	
	return status;		
}

int8 isGSMOk(){
	
	int8 USARTCarCounter=0;//Contador de caracteres recebidos na USART
	int8 msgCounter=0;//Contador de caracteres da mensagem de interesse
	char msg[9];//Tamanho máximo da mensagem de status (1\r\n\r\nOK\r\n)
	
	msg = "";//Garantir que não há lixo na variável
	output_high	(LED_VERMELHO);
	
	/*Desabilitar o Echo Mode: ATE0*/
	fputs("ATE0\r\n", SIM900D);
	delay_ms(1000);
	output_low(LED_VERMELHO);
	
	enable_interrupts(INT_RDA);
	
	/*AT+CCALR?: 0 = NOT READY; 1 = READY*/
	fputs("AT+CCALR?\r\n", SIM900D);
	
	delay_ms(500);
	
	for(;;){	
		if(interrupt == 1){
			if(USARTCarCounter > 9){
				msg[msgCounter] = caracterRecebido;
				msgCounter++;
				if(caracterRecebido == '\r'){
					disable_interrupts(INT_RDA);
					output_high(LED_AMARELO);
					return msg;	
				}
			}
			else if(caracterRecebido == headerStatusGSMVec[USARTCarCounter]){
	         USARTCarCounter++;
	         putc(USARTCarCounter, PK2);
		  	}
		  	interrupt=0;
		  	caracterRecebido = ' ';
	   }
	}	
}

#INT_RDA
void RDA_isr(void){
	caracterRecebido = getc(SIM900D);
	interrupt=1; 
	//putc(caracterRecebido, PK2);
}
 
Last edited:

Hiho, folks.

I've realized that if I don't call the function (inicializaPIC();) at void main() and uncomment this line (//putc(caracterRecebido, PK2);) at void RDA_ISR(void) (#INT_RDA function) I receive all the answer for AT commands that I've made.

Could anybody help me? I'm freaking out Haha
 

Hello, jayanth, are you fine?

Thank you so much for having answered me! Is the min() function the main() function? How can I get rid of these delays? Could you show me?

Is the Serial Interrupt for RS232 communication one of CCS' example programs (EX_SISR.C or EX_STISR.C)?

One more time, thanks in advance.

Regards,

Pedro Rosa!

P.S: I don't know why, but if I get rid of the interrupt routine and use a loop with KBHIT, the code works. I think the problem is really the many delays across my code... but I don't know how to solve this.
 
Last edited:

Sorry, that was a typo. it was indeed main() function. I haven't used CCS C. So you check the sample programs in CCS C. It surely contains UART examples which use Serial Interrupts. Post me the sample files. i will look into it. You can have delays in main() and use Serial Interrupt for receiving data. When serial Interrupt occurs it is serviced first and then other code will be executed.
 

Thanks, jayanth.

The examples are:

Code:
#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#elif defined(__PCD__)
#include <30F2010.h>
#fuses HS, NOWDT, NOPROTECT
#use delay(clock=20000000)
#use rs232(baud=9600, UART1A)
#endif


#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;


#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}

#define bkbhit (next_in!=next_out)

BYTE bgetc() {
   BYTE c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}

void main() {

   enable_interrupts(int_rda);
   #if defined(__PCD__)
   enable_interrupts(intr_global);
   #else
   enable_interrupts(global);
   #endif

   printf("\r\n\Running...\r\n");

               // The program will delay for 10 seconds and then display
               // any data that came in during the 10 second delay

   do {
      delay_ms(10000);
      printf("\r\nBuffered data => ");
      while(bkbhit)
        putc( bgetc() );
   } while (TRUE);
}

and

Code:
#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 12

#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 12


#elif defined(__PCD__)
#include <33FJ256GP710.h>
#fuses HS,NOWDT,NOPROTECT, PR
#use delay(clock=20000000)
#use rs232(baud=9600,UART1) 
#endif


#define T_BUFFER_SIZE 64
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;


#int_tbe
void serial_isr() {

   if(t_next_in!=t_next_out)
   {
      putc(t_buffer[t_next_out]);
      t_next_out=(t_next_out+1) % T_BUFFER_SIZE;
   }
   else
      disable_interrupts(int_tbe);
}

void bputc(char c) {
   short restart;
   int ni;

   restart=t_next_in==t_next_out;
   t_buffer[t_next_in]=c;
   ni=(t_next_in+1) % T_BUFFER_SIZE;
   while(ni==t_next_out);
   t_next_in=ni;
   if(restart)
      enable_interrupts(int_tbe);
}

void main() {

   #if !defined(__PCD__)
      enable_interrupts(GLOBAL);
   #endif
   
   #if defined(__PCD__)
      enable_interrupts(INTR_GLOBAL);
   #endif

   printf(bputc,"\r\n\Running...\r\n");

   do {
      delay_ms(2000);
      printf(bputc,"This is buffered data\r\n");
   } while (TRUE);
}
 

In your void inicializaPIC() function there is an else statement which contains a infinite for( ; ; ) loop. So, inicializaPIC() is called from main() then if the execution enters the else block and for( ; ; ) loop it will never come out of it even there is a serial interrupt. So your code in the main()'s while(1) loop will never be executed.
 

I've suspected that this part and thus I've decided call only isGSMOk() from main function for checking what will happen. So, something strange happens in this part:

Code:
	for(;;){	
		if(interrupt == 1){
			if(USARTCarCounter > 9){
				msg[msgCounter] = caracterRecebido;
				msgCounter++;
				if(caracterRecebido == '\r'){
					disable_interrupts(INT_RDA);
					output_high(LED_AMARELO);
					return msg;	
				}
			}
			else if(caracterRecebido == headerStatusGSMVec[USARTCarCounter]){
	         USARTCarCounter++;
	         putc(USARTCarCounter, PK2);
		  	}
		  	interrupt=0;
		  	caracterRecebido = ' ';
	   }
	}

In the moment, I'm getting rid of the interrupt approach and coming back to the KBHIT way until I see what I've done wrong. Now, my code is this below. It's not so brilliant but it works.

Code:
char* teste(){
	
	int8 USARTCarCounter=0;
	int8 msgCounter=0;
	char* msg;
	int control = 0, i=0;
	
	msg = "";//Garantir que não há lixo na variável
	
	/*Desabilitar o Echo Mode: ATE0*/
	fputs("ATE0\r\n", SIM900D);
	delay_ms(2000);
	
	/*AT+CCALR?: 0 = NOT READY; 1 = READY*/
	fputs("AT+CCALR?\r\n", SIM900D);
	while(1){
		output_toggle(LED_VERMELHO);
		if(kbhit()){
			caracterRecebido = fgetc(SIM900D);
			fputc(caracterRecebido, PK2);
			if(USARTCarCounter > 9){
				msg[msgCounter] = caracterRecebido;
				msgCounter++;
				if(caracterRecebido == '\r' || caracterRecebido == '\n'){
					output_high(LED_VERDE);
					return msg[0];
				}
			}
			else if(caracterRecebido == headerStatusGSMVec[USARTCarCounter]){
				USARTCarCounter++;
			}
		}
	}		
}

One more time, thanks for having helped me.

Best wishes.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top