|
|
View previous topic :: View next topic |
Author |
Message |
Alejandro
Joined: 25 Mar 2011 Posts: 7
|
Problems INT_EXT or WDT ? |
Posted: Tue Apr 05, 2011 7:49 am |
|
|
Hi, I have implemented an application with a PIC18F452 on CCS. When the PIC receive an interrupt for RB0, the PIC performs a process. Everything works fine but the problem occurs after a time that the PIC has been energized. I do not understand why the PIC is frozen, is it something to do with the WDT? This error is related to the WDT? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9247 Location: Greensville,Ontario
|
|
Posted: Tue Apr 05, 2011 8:06 am |
|
|
Show us a small program that has the problem, please include compiler version and PIC type. |
|
|
Alejandro
Joined: 25 Mar 2011 Posts: 7
|
|
Posted: Tue Apr 05, 2011 9:52 am |
|
|
I am use the CCS 4.074.
Here is my code:
Code: | #include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)// RS232 Estándar
#include <241025multi.h>
#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL)
//***********************************************************************************
//* DECLARACION DE INCLUDES *
//***********************************************************************************
#include <string.h>
#include <STDLIB.H>
#include <MATH.H>
#include <Flash_leds.h>
//***********************************************************************************
//* DECLARACION DE REGISTROS *
//***********************************************************************************
#byte reg_TXREG = 0xFAD // Buffer de TX del UART
#byte reg_RCREG = 0xFAE
#byte port_b = 0x0F81 //declaracion del puerto b
//***********************************************************************************
//* DECLARACION DE DEFINES *
//***********************************************************************************
#define ON output_high
#define OFF output_low
#define BUFFER_SIZE 550
//***********************************************************************************
//* DECLARACION DE VARIABLES *
//***********************************************************************************
int xbuff=0x00;
int16 Indice_Buff=0x00;
char Buffer_Modulo1[lenbuff]; // Buffer
char flagcommand = 0;
char Flag_Modulo2 = 0;
char flag = 0;
int UART_Modo;
int16 j;
int p;
int32 q;
int32 r;
int t;
int16 Data_TX;
int Buffer_Cont;
int16 k;
int8 buffer[BUFFER_SIZE];
int16 next_in = 0;
int16 next_out = 0;
int8 n = 0;
int8 Buffer_Modulo2 = 0;
int16 Cont_Data_Modulo2;
int16 Pag_SMS;
int Mensaje_Modulo1 = 0;
int Modulo2_OK;
char Data_Modulo2[538] ;
char Buffer_Pag_Modulo1[9];
int32 Pag_MSB_Modulo1;
char Pagina_Modulo1[4];
int8 bufferx[4];
int Buffer_Pag_Modulo2[2];
int32 Pag_Modulo1;
int32 Pag_Modulo2;
int32 Cont_Pag_Modulo2;
char Ping_ON = 0;
char PAG_ON = 0;
int Conta_Comas;
char Valor[2];
int Nro_Mensajes;
char Variable;
int i;
int Hay_mas_Mensajes;
//***********************************************************************************
//* #priority *
//* Configura la prioridad de las interrupciones del proceso *
//***********************************************************************************
#priority INT_EXT,INT_RDA
//***********************************************************************************
//* #INT_RDA *
//***********************************************************************************
#INT_RDA
void serial_isr() {
unsigned int t, p;
p = getc();
switch (UART_Modo) {
case 1: Add_Buffer_Moudlo1(p);
break;
case 2: Flag_Modulo3 = 1;
buffer[next_in]= p;
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t;
break;
}
}
//***********************************************************************************
//* INT_RB0 *
//* Monitorea alguna Interrupcion por cambio de estado del RB0 *
//***********************************************************************************
#INT_EXT
void IntRB0()
{
Mensaje_Modulo1 = 1;
}
//***********************************************************************************
//* bkbhit *
//* Llena el buffer del recepcion con los datos del GPS *
//***********************************************************************************
#define bkbhit (next_in!=next_out)
int bgetc() {
BYTE x;
WHILE(!bkbhit) ;
x = buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(x);
}
//***********************************************************************************
//* iniBuffer_Modulo1 *
//***********************************************************************************
void Ini_Buffer_Modulo1(void){
int n;
int count=32;
for(n=0;n<count;n++){ // Bucle que pone a 0 todos los
Buffer_Modulo1[n]=0x2; // caracteres en el buffer
}
xbuff=0x00; // Inicializo el índice de siguiente
}
//***********************************************************************************
//* addBuffer_Modulo1 *
//* Llena el buffer de recepcionBuffer_9601 con los caracteres recibidos del *
//* modem 9601 *
//***********************************************************************************
char Add_Buffer_Modulo1(char c){
switch(c){
case 0x0A: // Enter -> Habilita Flag para procesar
if (flag >= 3 )
flagcommand=1;
else
flag++;
break;
default:
Buffer_Modulo1[xbuff++]=c; // Añade carácter recibido al Buffer
}
}
.
.
.
.
.
.
//***********************************************************************************
//* Enable_Int_Hardware *
//* Habilita todas la insterrupciones producidas por el PortB y el RTC *
//***********************************************************************************
void Enable_Int_Hardware(){
enable_interrupts(int_ext); // Activar interrupcion RB0
ext_int_edge(H_TO_L); // por cambio de Alto a Bajo
enable_interrupts(GLOBAL); // Activa todas las Interrupciones
}
//***********************************************************************************
//* Disable_Int_Hardware *
//* Deshabilita todas la insterrupciones producidas por el PortB y el RTC *
//***********************************************************************************
void Disable_Int_Hardware(){
disable_interrupts(int_ext); // Desactivar interrupcion RB0
disable_interrupts(GLOBAL); // Desactiva todas las Interrupciones
}
//***********************************************************************************
//* Enable_Int_UART *
//* Habilita todas la insterrupciones producidas por UART *
//***********************************************************************************
void Enable_Int_UART(){
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
clear_interrupt(INT_RDA);
}
//***********************************************************************************
//* Disable_Int_UART *
//* Deshabilita todas la insterrupciones producidas por UART *
//***********************************************************************************
void Disable_Int_UART(){
disable_interrupts(INT_RDA);
disable_interrupts(GLOBAL);
}
//***********************************************************************************
//* Programa Principal *
//***********************************************************************************
void main(){
SET_TRIS_B (0b11111111);
SET_TRIS_D (0b00000000);
output_bit( PIN_D0, 0);
output_bit( PIN_D1, 0);
Mensaje_Modulo1 =0;
Disable_Int_Hardware();
Disable_Int_UART();
Wr_EEprom_Request();
Init_Modulo1();
enable_Int_Hardware();
Ping_ON = 0;
PAG_ON = 0;
while (TRUE){
if (Mensaje_Modulo1){
disable_Int_Hardware();
Hay_mas_Mensajes = 0;
do{
Interroga_Modulo1();
Mensaje_Modulo1 = 0;
if (Ping_ON ){
Modo_Moudlo1_Ping();
Ping_ON = 0;
}
if (PAG_ON ){
Interroga_Modulo2();
Modo_Modulo3();
PAG_ON = 0;
}
if (Nro_Mensajes != 0){
Nro_Mensajes--;
Hay_mas_Mensajes = 0;
}
else {
Hay_mas_Mensajes = 1;
}
} while (Hay_mas_Mensajes == 0);
enable_Int_Hardware();
}
}
}
|
|
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1937 Location: Norman, OK
|
|
Posted: Tue Apr 05, 2011 10:02 am |
|
|
One thing I see right off... In #INT_EXT you do not clear the interrupt for
RB0. I see later where you disable/enable the interrupt but it is still not
cleared. You would typically do this by reading the port or using the
clear_interrupt() command. _________________ Google and Forum Search are some of your best tools!!!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Tue Apr 05, 2011 10:12 am |
|
|
There are lots of things that could be wrong, which we can't see, and a few that 'are'.
Now, you declare your buffer to have size 'lenbuff', but the declaration for this is not shown.
Then, you use the '%' operator to get the remainder, and limit the counter to the 'BUFFER_SIZE'. Don't. This _must_ only be used with _binary_ buffer sizes (8,16,32, 64 characters etc.. Used with an odd number like 550, it results in the compiler having to perform an integer division in the interrupt. In your case, if the buffer really is 550 characters long, it'll need a int16 division, and will result in interrupts being disabled in any int16 divisions in the external code, as well as a huge amount of time being used. 550, is a really ludicrous amount of memory for a buffer, and unless you are doing something silly a much smaller size will be better.
Then you seem to have two different buffers being used.
In the Add_Buffer_Modulo1 routine, there is no sign of a test for the buffer size being reached. Without this, there is a good change, that this routine _will_ write over and destroy variables stored after it's buffer (who's size we cannot tell, because no sign of the lenbuff declaration). Probable reason for hang. However the address used here is an int8, not an int16.
Seriously, switch to the standard ex_sisr code, and use a buffer size like 128 bytes, or recode the size limit using a test like:
Code: |
if (++next_in == BUFFER_SIZE) next_in=0;
|
and the same for the next_out counter.
There is no sign of a buffer overflow test. Again possible problems.
No, your problem is not the watchdog. In fact if you had a watchdog, it with care, might be able to allow your code to recover from the problems, _but_ you must fix the code first, otherwise it could be hiding dangerous problems...
Best Wishes |
|
|
Alejandro
Joined: 25 Mar 2011 Posts: 7
|
|
Posted: Tue Apr 05, 2011 1:28 pm |
|
|
Hi Ttelmah, thank you by your help..
Quote: | you declare your buffer to have size 'lenbuff', but the declaration for this is not shown |
I'm sorry, here is:
Code: | int const lenbuff = 32; // Longitud de buffer |
Quote: | if the buffer really is 550 characters long, it'll need a int16 division, and will result in interrupts being disabled in any int16 divisions in the external code, as well as a huge amount of time being used. 550, is a really ludicrous amount of memory for a buffer, and unless you are doing something silly a much smaller size will be better. |
Unfortunately I have to use a buffer of this size, because when I interrogate the Module2 this answer me with a string of 550 ASCII characters
Quote: | Seriously, switch to the standard ex_sisr code, and use a buffer size like 128 bytes, or recode the size limit using a test like:
Code:
if (++next_in == BUFFER_SIZE) next_in=0;
|
Is correct this change?
Code: | case 2: Flag_Modulo3 = 1;
buffer[next_in]= p; // Interrupcion producida por el MGRAFO
t=next_in;
if (++next_in == BUFFER_SIZE)
next_in=0;
else
next_in=t;
break; |
and this another?
Code: | #define bkbhit (next_in!=next_out)
int bgetc() {
BYTE x;
WHILE(!bkbhit) ;
x = buffer[next_out];
if (++next_out == BUFFER_SIZE) next_out=0;
return(x);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Tue Apr 05, 2011 2:39 pm |
|
|
Seriously, the return message being this size, is _not_ a reason to have a buffer this large.
Assuming you are processing this message as it arrives, the buffer _only_ needs to be the size corresponding to how much behind the message the processor will get at the worst case. The only reason to buffer the whole thing, would be if there was a part at the end, that was needed before you can start processing the beginning. It is like a reader refusing to read a message arriving on a teletype until the entire message has arrived. Normally you start reading at the beginning, and will only be a few characters behind the message as it arrives.
Best Wishes |
|
|
|
|
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
|