View previous topic :: View next topic |
Author |
Message |
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
INT_RDA not detected, need more help |
Posted: Mon Oct 13, 2003 10:08 pm |
|
|
Hi,
I read a previous post where it was said that the USART could get an overrun error
I would like to know how I can detect this error. In my program I am using the INT_RDA interrupt sometimes this interrupt is not generated, one of the remedies suggested was that the #use rs232 directive must contain the ERROR parameter, this would clear the error bits.
It was also suggested that I should clear the bit manually twice , by polling for the error bit..
Kindly advise how I can do this.....??
thanks
arun
NOTE: The use of the error parameter has improved the performance of the communication of my application, although I notice the problem is still there... |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Tue Oct 14, 2003 12:25 pm |
|
|
It's not feasible to help you if we doesn't know:
1) The compiler version.
2) The microcontroller you are using.
3) The header and configuration settings.
4) The lines of codes involved in the problem.
5) The routine to service #INT_RDA.
6) Minimum hardware description.
Regards,
Humberto |
|
|
mfilion
Joined: 17 Sep 2003 Posts: 1 Location: Montreal, Canada
|
Re: INT_RDA not detected, need more help |
Posted: Tue Oct 14, 2003 2:56 pm |
|
|
arunb wrote: | Hi,
I read a previous post where it was said that the USART could get an overrun error
I would like to know how I can detect this error. In my program I am using the INT_RDA interrupt sometimes this interrupt is not generated, one of the remedies suggested was that the #use rs232 directive must contain the ERROR parameter, this would clear the error bits.
It was also suggested that I should clear the bit manually twice , by polling for the error bit..
Kindly advise how I can do this.....??
thanks
arun
NOTE: The use of the error parameter has improved the performance of the communication of my application, although I notice the problem is still there... |
You could poll the changes on the RS-232_ERRORS variable that is generated by the #USE RS232 |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Tue Oct 14, 2003 3:52 pm |
|
|
This is right out of the data sheet.
RCSTAx: RECEIVE STATUS AND CONTROL REGISTER
bit 7 SPEN: Serial Port Enable bit
1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
0 = Serial port disabled
bit 6 RX9: 9-bit Receive Enable bit
1 = Selects 9-bit reception
0 = Selects 8-bit reception
bit 5 SREN: Single Receive Enable bit
Asynchronous mode:
Don’t care
Synchronous mode - Master:
1 = Enables single receive
0 = Disables single receive
This bit is cleared after reception is complete.
Synchronous mode - Slave:
Don’t care
bit 4 CREN: Continuous Receive Enable bit
Asynchronous mode:
1 = Enables receiver
0 = Disables receiver
Synchronous mode:
1 = Enables continuous receive until enable bit CREN is cleared (CREN overrides SREN)
0 = Disables continuous receive
bit 3 ADDEN: Address Detect Enable bit
Asynchronous mode 9-bit (RX9 = 1):
1 = Enables address detection, enables interrupt and load of the receive buffer
when RSR<8> is set
0 = Disables address detection, all bytes are received, and ninth bit can be used as parity bit
bit 2 FERR: Framing Error bit
1 = Framing error (can be updated by reading RCREG register and receive next valid byte)
0 = No framing error
bit 1 OERR: Overrun Error bit
1 = Overrun error (can be cleared by clearing bit CREN)
0 = No overrun error
bit 0 RX9D: 9th bit of Received Data
This can be Address/Data bit or a parity bit, and must be calculated by user firmware
So to test for framing errors
Code: |
if(bit_test(RS232_ERRORS,2)) // Found Framing Errors
|
|
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
|
Posted: Tue Oct 14, 2003 10:23 pm |
|
|
Hi,
The details are given below, please note that the error still comes up even while using the ERRORS parameter, also when it is cleared.
Please suggest how I can clear /reset the USART module..
thanks
arun
Compiler Version : PCM 3.169
Microcontroller : PIC 16F877
#use delay(clock=4000000)
#use fast_io(B)
#use fast_io(D)
#use fast_io(A)
#use rs232(baud=9600,xmit=pin_c6, rcv=pin_c7,parity=n,brgh1ok,errors)
void main()
{
initialise();
do
{
restart_wdt();
if (RS232_ERRORS!=0)
RS232_ERRORS=0; //To clear the error
if (bShowField==1)
{
showfielddata();
bShowField=0;
}
} while(TRUE);
}
#INT_RDA
usart_isr()
{
disable_interrupts(INT_TIMER1);
if (nUSARTCmd==0)
get_command(getc());
else
process_command(getc());
enable_interrupts(INT_TIMER1);
} |
|
|
mcafzap
Joined: 07 Sep 2003 Posts: 46 Location: Manchester, UK
|
RS232 |
Posted: Wed Oct 15, 2003 5:48 am |
|
|
I use the following, within the 'main' loop, to pick up both overrun and framing errors:
#byte RCSTA = 0x18
#byte RCREG = 0x1A
if (RCSTA & 0x06){
RCSTA = 0x80;
j = RCREG;
j = RCREG;
j = RCREG;
RCSTA = 0x90;
}
Steve |
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE: |
Posted: Wed Oct 15, 2003 7:34 am |
|
|
Hi,
How does one clear the error ??? also how to prevent it.????
cheers
arun |
|
|
Ttelmah Guest
|
|
Posted: Wed Oct 15, 2003 7:49 am |
|
|
arunb wrote: | Hi,
How does one clear the error ??? also how to prevent it.????
cheers
arun |
You prevent the error, by ensuring that you service the interrupt quickly enough. The commonest reasons for overrun errors, are having large sections of the main code with interrupts disabled, or putting too much code in the interrupt handler. It is important to realise, that if you call a function in the interrupt handler, and the same function inside the main code, then the compiler will disable interrupts inside this function in the main code (since it does not support re-entrancy).
You clear the error, by disabling the 'continuous receive' bit in the UART, re-enabling it, and reading the characters that are waiting in the buffers at the time. You can do this in the main code, or in the interrupt handler (the interrupt will be called _once_ with the error flag set, then if the error is not cleared, will not be called again).
The compiler is meant to clear the error automatically, if the 'errors' directive is used, but this still leaves the buffers full, so the interrupt code should check before exiting, if there is another character waiting, or there is a high risk of the error re-asserting very quickly.
Best Wishes |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Wed Oct 15, 2003 9:10 am |
|
|
Hi Arunb,
Ttelmah made a brigth description concerning how to prevent frame and overrun errors.
Below you have my small contribution:
I made some changes in your code. I assume you are receiving a char, not a string.
Best wishes,
Humberto
Code: |
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=pin_c6, rcv=pin_c7,errors)
#use fast_io(B)
#use fast_io(D)
#use fast_io(A)
void main()
{
initialise();
do
{
restart_wdt();
if (RS232_ERRORS!=0)
RS232_ERRORS=0; //To clear the error
if (bShowField==1)
{
showfielddata();
bShowField=0;
}
if (get_command)
{
disable_interrupts(INT_RDA;
// your function().....
get_command = FALSE;
}
if (process_command)
{
disable_interrupts(INT_RDA;
// your function().....
process_command = FALSE;
}
} while(TRUE);
}
// Keep your isr as short as possible and don´t call any
// function, just set a flag.
#INT_RDA
usart_isr()
{
int rcved_char;
disable_interrupts(INT_TIMER1);
if (nUSARTCmd==0)
{
rcved_char = getc();
if (rcved_char == 'X') // Where 'X' the char expected
{
get_command = TRUE;
}
else
{
process_command = TRUE;
}
}
enable_interrupts(INT_TIMER1);
}
|
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Oct 15, 2003 9:30 am |
|
|
The code posted could still present problems since you are not always reading the char when the int occurs. Also it is not necessary to disable interrupts inside an interrupt.
Code: |
#INT_RDA
usart_isr()
{
int rcved_char;
if (kbhit())
{
rcved_char = getc();
if (nUSARTCmd==0)
{
if (rcved_char == 'X') // Where 'X' the char expected
{
get_command = TRUE;
}
else
{
process_command = TRUE;
}
}
}
}
|
Mark |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Wed Oct 15, 2003 10:11 am |
|
|
This routine checks for a framing error that indicates a bad baud rate. The bad baud rate indicates a need to change baud on the fly. Dealing with an overrun error should be just as easy. Remember you must always clear the buffer for a new byte by reading the it. The errors are cleared by the built in getc() function and stored in RS232_ERRORS. If you assemble this you will see that it is a very small routine.
Code: |
// Channel A Receive Interrupt
#int_RDA //**************
RDA_isr() // BYTE RECIEVED
{ int8 x; // Create byte storage
x = fgetC( chanA ); // Get incomming byte from buffer
if(bit_test(RS232_ERRORS,2)) // Found Framing Errors
{ ++ChA_Errors;
if(ChA_Errors & 8)
{ ChA_Errors=0;
ChA_Change_Baud(); // Jump to a new baud rate
}
}
else
{ ChA_PacketBuffer[ChA_PacketIndex++] = x; // Place incomming byte in PacketBuffer
if( bit_test(ChA_PacketIndex,6)) // If packet index larger than packetbuffer (64)
ChA_PacketIndex = 0; // Zero packet index value
}
} |
|
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE |
Posted: Wed Oct 15, 2003 9:49 pm |
|
|
Hi,
Thank you very much for the help.
You say the error is due to a bad baud rate, I am using a 4 MHz xtal , will changing to 20 Mhz improve things ???
cheers
arun |
|
|
Pete Smith
Joined: 17 Sep 2003 Posts: 55 Location: Chester, UK
|
Re: RE |
Posted: Thu Oct 16, 2003 3:38 am |
|
|
arunb wrote: | Hi,
Thank you very much for the help.
You say the error is due to a bad baud rate, I am using a 4 MHz xtal , will changing to 20 Mhz improve things ???
cheers
arun |
Your best bet is to switch to a crystal that is a multiple of a baud rate.
We use 1.8432MHz crystals, because you can get all the common baud rates from this, eg divide it by 192 to get 9600 etc.
If you need ~4MHz, then go for a 3.6864MHz one. If you actually want 20MHz, try a 18.432MHz one.
HTH
Pete. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Oct 16, 2003 6:15 am |
|
|
For a 20MHz or a 4MHz clock and 9600 baud rate, the error rate if 0.16% which is fine. You actual baud rate will be 9615.
Your orginal routine did not always read the data byte from the receive register. This is important to do or else you won't get another int! |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: RE |
Posted: Thu Oct 16, 2003 8:05 am |
|
|
arunb wrote: | Hi,
Thank you very much for the help.
You say the error is due to a bad baud rate, I am using a 4 MHz xtal , will changing to 20 Mhz improve things ???
cheers
arun |
The routine I posted checks for a framing error indicating a bad baud rate. An overrun error is a different error all together. A framing error means that the bit time within the received byte is wrong. An overrun error indicates that a byte was shifted in and placed in the received byte register before the last byte received was read from that buffer. This means the bytes are coming in faster than they are being removed from the buffer. An overrun error means you missed a byte in the incoming data stream.
Changing to a crystal that is 5 times faster will help prevent overruns because you can read from the buffer 5 times faster. The baud rate error will also be lessened and should eliminate framing errors. |
|
|
|