Hi all, New to this forum in a posting perspective but it's been a great help in a lot of areas from the start of my 8051 classes this year and last year so for that thanks. Im coming near the end of my final year project and I'v come across a slight problem with my interrupt implementation. I have RTFMed about all I can find on interrupts from any number of sources before you tell me to Please read the manual. The problem is that my ISR is triggered fine the first time sets a flag goes back carries out a function ... due to it not being a good idea to have function calls within an ISR ... resets flag and then sits reading the clock again however when I try to interrupt again it will not carry out the ISR this next time.
I have : reset external interrupt flag; reset condition variable flag; even attempted to re-enable external interrupt (even though this is probably not required);
The code is a long one so Id rather not post the entire thing here if anyone wants to take a look at it who has a good idea as to what I'm doing wrong or if anyone wants to suggest a specific part to post to look at the ISR or the menu its being called from please contact me. I will however not be sending this code on to anyone who's just looking for something to copy as I've read the manual to get it this far. I'd also be very happy to have someone look over the code in general for bad programming implementation if they would ... I'm a student in this subject but I've a keen interest in the field.
Also I'm Irish but this website is picking me up in America for some reason ?
Regards Robbie.
Was a little silly to not include any code at all so here is my ISR ... my project is an RFID orienteering tag system and the elements in the array are correct for my usage before anyone points it out to me it is working its just that I cannot get it to retrigger the external interrupt after including (2) which is a small part of (3).
(1) //ISR void enter (void) interrupt 0 { while (1) { receive(); writecmd(0x99); if (card_id[2,3,4,5,6,7,8,9,10,11,12,13] == kite1[0,1,2,3,4,5,6,7,8,9,10,11]) { kite1_f = 1; delay(10000); IE = 0; return; } if (card_id[2,3,4,5,6,7,8,9,10,11,12,13] == kite2[0,1,2,3,4,5,6,7,8,9,10,11]) { kite2_f = 1; delay(10000); IE = 0; return; } if (card_id[2,3,4,5,6,7,8,9,10,11,12,13] == kite3[0,1,2,3,4,5,6,7,8,9,10,11]) { kite3_f = 1; delay(10000); IE = 0; return; } if (card_id[2,3,4,5,6,7,8,9,10,11,12,13] == kitef[0,1,2,3,4,5,6,7,8,9,10,11]) { kitef_f = 1; delay(10000); IE = 0; return; } else { writecmd(0x99); delay(4000000); writedata('R'); writedata('e'); writedata('t'); writedata('r'); writedata('y'); writedata('!'); return; } } } (2) if (kite1_f >= 1) { writecmd(0x99); writeline_lcd("Kite 1 scanned! "); split1[1]=c; split1[2]=e; split1[3]=f; delay(40000000); writecmd(0x99); writeline_lcd("Go To Kite 2 "); delay(10000); kite1_f = 0; }
while (1) it seems you are confusing an ISR as a task drop the while
Right so in reply to Andrew(hope you don't mind me using your first name) I have changed the check to this:
if (card_id[13] == kite1[13]) { for (i=2;i<14;i++) { if (card_id[i]!=kite1[i]) { writedata('E'); writedata('R'); writedata('R'); writedata('O'); writedata('R'); writedata('1'); return; } } kite1_f = 1; delay(10000); IE = 0; }
Hope thats a bit better, kind of quickly thrashing out code here maybe I should take some time with the problem ?
In reply to Mr Westmark : Hello there and thanks would I be correct in assuming when you are talking about placing in a queue you are talking about an array or is there some other construct for this implementation? I'll show you my current recieve(); function below but it appears that my function is currently working for the first external interrupt but then failing to trigger in the second instance however from my debugging I can see its not sticking inside the ISR just not recognising it. Also go easy on me when you see this recieve function as it was the first time I wrote anything for serial communication.
void receive() //Function to receive data serialy from RS232 { unsigned char k; for(k=0;k<14;k++) { while(RI==0); card_id[k]=SBUF; RI=0; } }
memcmp()
Hi eric I remember seeing your name before on these threads I think you helped a friend of mine Cian Young with his project too for certain reasons we didn't get the chance to do serial communications in our programmable electronics course and hence why the recieve function is a little butcheresque. The function is shown just above your post.
In all fairness, you did write "The 'C' programming language", not library.
Two things.
You have some paths of your ISR that do IE=0. But you also have paths that only do "return". Every single path out of your ISR must make sure that you leave the processor in a state where it will be able to react to a new interrupt.
Next thing.
And ISR should enter, do a very quick job and then leave.
You have an ISR that calls receive(). And receive() may take forever since it will not end until a fixed number of serial characters are received. But what if there are no characters to receive?
Rework it so you have zero delays and zero loops waiting for any events inside all of your interrupt handlers.
Yes - an array is a good primitive for creating a queue. Just that if you read up on "round robin" or "circular buffer", you'll see examples of how an array is used with one insert pointer and one read-out pointer, allowing an interrupt handler to insert received data, while the main loop reads out and processes data.
Such a buffer also works for outgoing data - you can insert multiple characters into a send buffert, and have a serial interupt handler pick up the characters one-by-one as the UART gets ready for more data. Your code that prints multiple characters in the interrupt handler will have to wait for the actual transmit speed of the UART since you emit multiple characters and then busyloops waiting for the ready flag from the UART.
void enter (void) interrupt 0 { receive();
first interrupt 0 is the EI0 interrupt second you go to recieve even if the interrupt is transmit
this need some clarification
Ok my reader has a output pin that triggers when an RFID tag is received, I'm using this to tell the 89s52 to go and carry out recieve to see what is on the UART when this happens. Im only using this reader to recieve and have no transmit connection present only intended on simplex communication. I hope that answers your question.
Hmmm I feel slightly out of my depth here now.
Yes, that was deliberate.
That, and the "such" - meaning a direct comparison operator of multiple array elements.
I agree that memcmp() from the standard Library would seem like an ideal choice here.
In all fairness, I'm surprised nobody else picked this up.
;-)
Ok my reader has a output pin that triggers when an RFID tag is received, I'm using this to tell the 89s52 to go and carry out recieve to see what is on the UART when this happens. WHY?, why not just read the data coming down instead of mickey-mousing the read KISS
Im only using this reader to recieve and have no transmit connection present only intended on simplex communication.
you STILL need (if you do not do the right thing and move the read to the UART interrupt) to test for RI or you will willi-nilly fetch 'bytes' that may or may not be read from the seral bus.
you are waaaay overcomplicating the issue
Hmm would this take up more space to include or will my new error check suffice for my application ? I reworked it again after the potential for error cancellation.
Ah ha ha damn so I've overcomplicated things again .... back to the drawing board so serial interrupt it is then.
Also Willy-nilly is that a technical term?
Hmm this could potentially remove all requirement for external interrupt if I can do a quick tag check after the serial interrupt is carried out set the required flag for the required tag and then that will return to the menu to carry out the function for the specified flag. ?
Or would I better to have external and serial interrupts active with the serial to recieve the data and then the external will be triggered to set a flag high and this flag will then enable a tag check within the menu function.?
I'm expecting my computer to slap me at this stage.. Ok I'm sure i'm not far away from being annoying at this stage but can an array be included in this serial interrupt or should I be staying away from that and trying to get each byte be read in by the UART exit the interrupt save said byte before the UART gets triggered for the next byte .... Confused is not the word right now
Have you googled for source code for a ring buffer yet?
Where your UART interrupt handler checks if there is a received character, inserts it into the buffer, and updates the write index.
The main loop sees that the read index doesn't match the write index so picks up the next character and does whatever is needed.
But then again - a UART interrupt handler could keep an index of RFID byte position and perform a digit comparison for that index position on the fly. And if all digits has been received set a "OK" flag.
Or if a difference is found set a fail flag and then wait to synchronize for a new RFID code.
Yeah im now lost tired and clueless.
i tried this as my last attempt I'm not even sure if this would work
void recieve(void) interrupt 4 { if (RI == 1) { RI = 0; card_id[s] = SBUF; s++; } }
like I said I haven't received any instruction on my course in interrupts so this is not going my way at all. I've tried a number of sites and books at this stage but im noot getting it at all.
Robert: in this code
You are very close. The way I would implement this is something like:
void recieve(void) interrupt4 { char c; if (RI==1) // a character recieve caused the interrupt { RI=0; c=SBUF0; // get the character } switch (state) { case WAITING_ID: { // // whatever you have to do to determine if this is an ID. state=WAIT_END; break; } case WAIT_END: { // whatever you have to do to determine if this is the end... if (end_of_packet) { state= DONE; } break; } case WAITING_START: { // whatever it takes to recognize that this is the start of the packet state=WAITING_ID; // prepare your buffer, and if this is based on a fixed length string, perhaps // initialize a counter and use it to determine when the packet ends. } } } elsewhere, you watch for state==DONE and then process the packet. When you are done, set state=WAITING_START; so that the state machine knows how to handle the next character. This code is skimpy on details, because I don't know how you recognize the start of the rfid read, and how you would recognize the id you want to extract, or recognize the end. If the packet is a fixed length, the simplest thing is to use a counter that starts at 0 when you recognize the start state, and decrement it, buffering the character until you find the ID, or else the end of the message. In a nutshell, this is a state machine that gets updated on each received character and reaches a DONE state after the full message is recognized. The main loop watches for the state to be tagged as DONE, then grabs the data, and resets the state to waiting for start (it might also reset the length etc.) This code as written probably won't run, and is certainly not a complete state machine for your application, but should give you an idea of what to do. The statemachine would recognize a start, buffer the data into a buffer until it recognizes an end. That can possibly be done by either a message count, or by analyzing the packet. I often implement protocols like this, and favor using a STX and EOT type protocol when I don't have binary data.
Thanks very much to everyone who gave me plenty to consider and so much food for thought I eventually found the problem with the ISR it turns out my code was working fine and I cannot believe no one saw the problem was that I was resetting IE instead of IE0. Now that was the most obvious problem however only today did notice it. So sometimes it is in fact the most simple solution that fixes these problems but look for complicated solutions and they will easily be found. Thanks again all, Robbie Dowdall.
Oh and a special thanks to Eric and Andrew for finding those errors that would have made me look a little thick :)
View all questions in Keil forum