Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC16F877A prevent queuing interrupts.

Status
Not open for further replies.
The size of the buffer is set by the directive #define FifoLength 32 - in this case 32 bytes long.

Mike.

Hey there Mike. Hope you are okay. I didnt want to open a new thread just for this, I started to study the circular buffer, for now I just want to ask one question, Im trying to figure it by myself to learn it. If i have further problems I ll try to seek for help, until now ...

Is possible to apply the circular buffer into an interrupcion right ? Actually Im using this piece of code

Code:
void interrupt ISR()
{
    if(RCIF)
    {
        buff[a] = RCREG;  /* read received byte from serial buffer */
        a++;
       
        if(RCSTAbits.OERR)  /* check if any overrun occur due to continuous reception */
        {           
            CREN = 0;
            NOP();
            CREN=1;
        }
        status_flag=1;  /* use for new message arrival */
    }

}

This is working perfectly buuut.. Its stacking the values that its getting so to keep myself away from problems I want to implement the circular buffer, Its posible to adapt it using the ISR to have a good disposal of the content right ?

Thanks in advance and once more excuse my grammar :woot:
 
Sure, you can put it in an ISR,
Code:
#define FifoLength 32
unsigned char FifoBuffer[FifoLength];
unsigned char *FifoStart;
unsigned char *FifoEnd;
unsigned char count;

void InitFifo(void){
    FifoStart=FifoBuffer;
    FifoEnd=FifoBuffer;
    count=0;
}

void interrupt ISR(){
    if(RCIF){
        *FifoEnd++=RCREG;
        count++;
        if(FifoEnd==FifoBuffer+FifoLength)      //reached end
            FifoEnd=FifoBuffer;                 //yes so wrap
        if(FifoStart==FifoEnd){                 //is head eating tail?
            //fifo full so deal with it!!
        }
        if(RCSTAbits.OERR)  /* check if any overrun occur due to continuous reception */
        {        
            CREN = 0;
            NOP();
            CREN=1;
        }
    }
}

unsigned char GetFifo(void){
unsigned char chr;
    while(FifoStart==FifoEnd);              //if fifo empty then wait
    chr=*FifoStart++;
    count--;
    if(FifoStart==FifoBuffer+FifoLength)    //wrapped?
        FifoStart=FifoBuffer;               //yes
    return(chr);
}

unsigned char FifoCount(void){
    return(count);
}
With the above implementation you would check the status by calling FifoCount and retrieve characters with GetFifo.

It will be a little tricky to check for OK in your main loop. I'll let you try that.

Mike.
Note, there is no code to deal with the buffer becoming full. Plus, if you call GetFifo when the buffer is empty it will wait until a character arrives.
Also, you should never get an Overrun error unless you disable interrupts for more than 1ms (at 9600 baud).
Edit, the variables now need to be volatile.
 
Oh i see... I have some doubts about the buff[] alone, why when i write into it .. and then i use memset(buff,0,80); later when i try to write on, nothing happens ? i discovered this tonight while running some tests. then i disabled that line, and i could see that the buff started to get written again, but i continued to write it, it would stack (naturally i guess).. i wanted to erase it with memset but seems that doesnt work. for the sake of the knowledge, why this happens ? :D

in the other hand, i ll play with that piece of code tomorrow, this tuesday is holiday for us.. soo free time!! I ll find what i can do with it . and yes, im aware of the condition of volatile, i just have to make sure to make volatile the right ones.
 
The only way you should empty the buffer is by calling GetFifo. Or, you can call InitFifo again to reset it but you will clear any received characters.

If you continuously receive characters without calling GetFifo then it will overwrite itself.

To help you understand the code a little better, the variables starting with a * are pointers and contain the memory locations of the head and tail of the buffer.

Mike.
 
Hello back Mike, I had a good day today battling agaisnt this pic haha, I found that using a Circular buffer for this task was kinda overkill, instead i found how empy a linear buffer and re utilize it again, making the process quick... also i wont lie to you, i tried to use the circular buffer, but i couldnt retrieve the chars with get fifo, since get fifo is a function, i set it like

content = GetFifo();
before hand that array was declared and i tried to use it to retrieve the content, you said that the fifo would wait until it was full before give its content so i changed to size to 2 and i tried with an OK. but for any reason the "content" was empty despite i was writing using the interrupt and all the stuff.. Maybe is my lack of knowledge about this topic or idk. this stuff about fifos is kind of hard haha.. but since you took some of your time i didnt want to let it down until i could at least try it and make it work, so maybe in a future i can make use of it if I need it.
 
The function GetFifo only returns 1 character and will only wait if the buffer is empty - it will not wait until the buffer is full.

To test for OK would require something like,
Code:
char rec,found,flag;
    found=0;
    flag=0;
    while(1){                            //loop forever
        if(FifoCount()>0){                //any chars available
            rec=GetFifo();                //yes so fetch first
            if(found==0&&rec=='O'){        //check for 'O'
                found++;
            }
            else if(found==1&&rec=='K'){//check for 'K'
                flag=1;
                found=0;  
            }
            else{
                found=0;
            }
        }
        if(flag==1){
            flag=0;
            //flash LEDs etc.
        }
    }
Note, change the buffer back to something sensible - at least 8 long.
Again, untested.

Mike.
Edit, this should be in the main code - not the ISR.
 
Actually, you don't need the flag variable.
Code:
char rec,found;
    found=0;
    while(1){                             //loop forever
        if(FifoCount()>0){                //any chars available
            rec=GetFifo();                //yes so fetch first
            if(found==0&&rec=='O')        //check for 'O'
                found++;
            else if(found==1&&rec=='K')   //check for 'K'
                found++; 
            else
                found=0;
        }
        if(found==2){
            found=0;
            //flash LEDs etc.
        }
    }

Mike.
 
Oh i see... I was believing that it would accumulate all the characters inside.. that thing about wait until get all the chars is kind of troublesome, with some logic would possible to stop waiting and work with a lesser entry ? like if the size is 5, and it got something like "hey" work with it ? maybe some kind of do while and put some condition like until .. : \n .. its possible ?
 
The above code will continuously loop so you can do anything else you want. That is the point of the fifo in the isr - you don't have to wait. The ISR and fifo will continue receiving character during your 5 second LED flash sequence. This is why the buffer should be larger - I can type a lot more than 8 characters in 5 seconds. Ideally, you would continue going round the loop and use a timer to do your sequence.

Mike.
Edit, the fifo is more useful for sending characters - you write a complete sentences and then carry on with your code rather than waiting for it to be sent.
 
Once more, thanks for your time, I ll keep studying this topic until i can get to do something with it haha . I'll check this again asap.
 
Actually, you don't need the flag variable.
Code:
char rec,found;
    found=0;
    while(1){                             //loop forever
        if(FifoCount()>0){                //any chars available
            rec=GetFifo();                //yes so fetch first
            if(found==0&&rec=='O')        //check for 'O'
                found++;
            else if(found==1&&rec=='K')   //check for 'K'
                found++;
            else
                found=0;
        }
        if(found==2){
            found=0;
            //flash LEDs etc.
        }
    }

Mike.
after reading this, I wonder, wouldnt it be easier to use strstr instead of checking for each character ? in this case something like
Code:
strstr(rec,"OK");


Edit : I ask to test myself and see If Im thinking correctly haha.
 
If you use strstr() then it returns a pointer to the matching substring. Also, you don't have the received characters in a string - just as individual character. You could copy the characters to a string and use strcmp() but that defeats the point of using a fifo. Maybe you should just go back to the original code that worked and then move on to the next bit you want to learn.

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top