View previous topic :: View next topic |
Author |
Message |
Nono
Joined: 16 Sep 2008 Posts: 3 Location: France
|
OERR bit on PIC18F4525 |
Posted: Tue Sep 16, 2008 9:27 am |
|
|
Hello everybody,
I've looking answers for my problem on your forum and found a lot of good things, but nothing to solve it.
Here is my config :
MPLAB v7.42, PIC18LF4525 @ 20MHz, 3.3V, baud rate @57600, CCS compiler v4.078.
The problem is that sometimes I have an overflow error (OERR bit) on the communication line. There are only two activated interruptions (RDA and Timer2) in my program and a big main. The timer2 is used with the PWM1 to manage a motor (frequency of PWM : 19.5kHz).
First I thought it was due to the speed of the serial com, but even with a speed @9600bds, the problem is still here.
Then I wanted to use the priority level of the PIC. I put the HIGH_INTS=TRUE in my code and the keyword HIGH after the #INT_RDA but the compile failed with the error "Invalid Pre-Processor directive". If I don't use the keyword HIGH, the IPEN = 1 but RCIP = 0 (low level) and there are no line code @ vector 0x0008 (normally the high-priority interruption vector).
Code: | #INT_RDA
void receive_isr (void)
{
do
{
m_cBufferFifo[m_message.nIndexWrite] = RCREG;
if(OERR)
{ //error reset module
CREN=0;
CREN=1;
m_message.bError = 1;
}
if (FERR)
{
m_message.bError = 1;
}
m_message.nIndexWrite++;
if(m_message.nIndexWrite >= MAX_BUFFER_FIFO)
m_message.nIndexWrite=0;
if(m_message.nIndexWrite == m_message.nIndexRead)
m_message.bError = 1;
} while (kbhit());
RCIF = 0;
}
#INT_TIMER2
void moteur_isr ()
{
//timer system
m_lPerTimer2Module +=VAL_PR2/2;
m_lPerTimer2Module++;
if (m_lPerTimer2Module>=INT_TIMER2_TIME_FACTOR) //with Prescale to 1
{
m_lPerTimer2Module -= INT_TIMER2_TIME_FACTOR;
m_lOverflowCounterTmr2++; //current time
}
TMR2IF = 0;
}
|
Maybe can I change the 20MHz crystal by a 10MHz crystal and activate the x4 PLL inside the PIC in order to have better computing performances ?
It will be great if anyone could help me. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Sep 17, 2008 4:52 pm |
|
|
Your code is not complete so it is possible there are problems in other parts of your code.
Your RDA interrupt routine doesn't look like it is the problem. Including the interrupt overhead it is about 240 instructions, at 20MHz that allows you to receive 20.800 characters per second. With a baudrate of 57.600 you receive a maximum of about 5700 characters, much less than the ISR can handle.
Are you sure it is the OERR flag that's causing you troubles? You are setting the same bError flag for different types of errors. It will be a good thing to make sure you are not hunting the wrong problem. See also the bug described below that might well be the cause of your problems.
I only see one problem in your code: Code: | if(m_message.nIndexWrite == m_message.nIndexRead)
m_message.bError = 1; | Here you detect the error of your ring buffer being full but there is no code to prevent overflow of the ringbuffer. After setting the error flag the next received character will be written to the ring buffer, nIndexWrite is increased and many nasty buffer overwrites will happen before you detect the error again.
Try changing to: Code: | ...
if (FERR)
{
m_message.bError = 1;
}
temp = m_message.nIndexWrite; // added a temp variable
m_message.nIndexWrite++;
if(m_message.nIndexWrite >= MAX_BUFFER_FIFO)
m_message.nIndexWrite=0;
if(m_message.nIndexWrite == m_message.nIndexRead)
{
m_message.bError = 1;
m_message.nIndexWrite = temp; // in case of overflow set the pointer back to last position
}
|
The HIGH interrupt is not going to solve your problem when you only have these two interrupts. With the high priority interrupt you can interrupt the other interrupts when these are active but your timer2 interrupt is very fast, no need to add the overhead of the high priority interrupt. |
|
|
Nono
Joined: 16 Sep 2008 Posts: 3 Location: France
|
|
Posted: Thu Sep 18, 2008 2:56 am |
|
|
thanks for your answer ckielstra. I really think that the problem is coming from the OERR because I put a breakpoint everywhere in the interrupt and it stops on the OERR fault. I will try your code. |
|
|
Nono
Joined: 16 Sep 2008 Posts: 3 Location: France
|
|
Posted: Thu Oct 02, 2008 10:54 am |
|
|
I found the problem. It was really tricky. It concerns the write in EEPROM. Indeed, all the interruption are disable during a write and I used this function often. That's why the problem appeared randomly. |
|
|
|