|
|
View previous topic :: View next topic |
Author |
Message |
elder
Joined: 16 Mar 2005 Posts: 19
|
help with interupt giving unexpected results (PIC = 16F648A) |
Posted: Thu Mar 24, 2005 3:25 am |
|
|
Well all has been going well up untill now, i am having problems now that i'm trying to use an interupt.
I'll explain what i'm doing first:
-I am receiving infrared data. It is IrDA encoded ('1' is always high and a '0' has a 1.6us low pulse)
-I am receiving this on the TOCK1 pin(RA4). This is set up so that Timer0 iterates on the high_to_low transition on this pin. I set Timer0 count to 0xFF so that when the pulse of the '0' start bit comes in it causes Timer0 to overflow and sets TOIF (timer 0 interupt flag).
-Once i've detected the start bit, i use timer1 to time bit periods and TOIF again to check if each bit was a '1' or a '0'.
OK, now i have this working perfectly fine when i continously check for the TOIF for the start bit in my main while loop.....
Code: |
int irdaStartBitDetected(){
if (INTCON.TOIF){
INTCON.TOIF = 0;
set_timer0(0xFF);
set_timer1(0); //bit period timer
return TRUE;
}
return FALSE;
}
void main(){
//setup stuff here
while(1){
if (irdaStartBitDetected()) {
ch = getIrdaByte();
putIrdaByte(ch);
}
}
|
but when i change to trying to use the timer0 interupt instead of just checking the flag, it doesn't work properly
Code: |
#INT_TIMER0
void irdaDetected(){
INTCON.TOIF = 0;
set_timer0(0xFF);
set_timer1(0);
ch = getIrdaByte();
putIrdaByte(ch);
}
void main(){
//setup stuff here
while(1){
}
}
|
The actual interupt works, i'm still receiving bytes. However, i'm not getting the bytes i should be. the 4th bit( reading from lsb as this is how its sent) is always read as '1'(ie no pulse) even if it should be '0'. so i read:
'i' (01101001) when i should be reading 'a' (01100001)
'j' (01101010) when i should be reading 'b' (01100010)
and i get chars like 'i' and 'j' correctly as these have the 4th bit as '1'.
Any ideas on why this could happen?
I know it takes some instructions to get inside the interupt but this shouldn't ruin my bit period timing. If i delay for some instructions inside my irdaStartBitDetected() i dont get this problem! and besides if it was causing a bit period timing error i'd expect all bits to be shifted not a single bit to always be '1'.
I'm lost for reasons and I really need this interupt, i have a fair amount of calculations that will need doing between incomming bytes. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
|
Guest
|
|
Posted: Fri Mar 25, 2005 2:43 am |
|
|
sorry, heres the 'get' functions.
Now as i said these get functions work, however when i call them inside the interupt i always get a '1' on the 4th pass of getIrdaBit(). So the timer0 interupt flag is not set on the 4th pass of getIrdaBit when it should be.
Code: |
int getIrdaBit(){
while (get_timer1() < 32); //104.16us
set_timer1(0);
if (INTCON.TOIF){ //zero bit detected
INTCON.TOIF = 0; //reset TMR0 Flag
set_timer0(0xFF); //set TMR0 1 before flag
return 0; //return 0 bit
}
return 0b00000001; //return 1 bit
}
BYTE getIrdaByte(){
int i;
BYTE b;
for (i = 0; i<8; i++){
b = b | (getIrdaBit() << i);
}
return b;
}
|
Thanks for the irda example but it uses a start bit detected function, as i've said when i use a similar function mine works fine. I have to do other work with the PIC so i cant be continuously checking for the start bit like that though :(. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Mar 25, 2005 8:11 am |
|
|
Whats your crystal speed? |
|
|
elder
Joined: 16 Mar 2005 Posts: 19
|
|
Posted: Sat Mar 26, 2005 4:59 pm |
|
|
11.0592mhz
timer1 is on a div by 8, so 104us calculates to 36 increments of timer1 i think it was. But i've tried increments around 36 to see the effect (which is why it was at 32 when i posted the code).
To actually receive a '1' at bit 4 because of bit timing going out i'd have to get the remaining bits shifted too.
A: 01100001
too short: 11001001
too long: 11101001 (timing would be way off for a '1' @ bit 4 here)
what im getting: 01101001 (cant happen simply from bit period error) |
|
|
elder
Joined: 16 Mar 2005 Posts: 19
|
|
Posted: Mon Mar 28, 2005 2:53 am |
|
|
no ideas?
Tommorow i'll to set up my detected() function to delay the same i'd expect from the interupt, this is around 20-25 instructions right? |
|
|
Ttelmah Guest
|
|
Posted: Mon Mar 28, 2005 4:21 am |
|
|
30 instruction times.
There is one instruction time to actually 'respond', then about 24 to save the registers, then it tests if the interrupt is enabled, then if it has occured, and finally jumps to the handler. Totals 30 to 31 instructions, assuming you have no other interrupt sources enabled. If you have more than one interrupt source enabled, then add about six instruction times for each one defined 'ahead' of this one, or ahead of it in the #priority statement, and if you want to deal with the 'worst case', you then have to allow for the possibility that it deals with the other interrupt first, and have the save time, the call time, the execution time for the other interrupt, the restore time, and then the save and call time for the second interrupt...
Testing with this delay added to the polling routine is a very good idea.
My suspicion is that the behaviour is the result of a fractionally slow bit grab, combined with being very late in the byte, because of the interrupt latency. Remember that if two edges occur in one sample time, the interrupt flag will only be set once. If your sampling 'point', is just in front of the transition, and the samplin interval, is just fractionally wider than the gap between two edges, you potentially can 'see' two edges as one. I'd look at possibly using 'set_timer1(5)', in the interrupt routine, before calling get_IrdaByte, which should move you to sampling at about the same point in the data stream, as the polling version.
Best Wishes |
|
|
elder
Joined: 16 Mar 2005 Posts: 19
|
|
Posted: Mon Mar 28, 2005 6:56 pm |
|
|
Thanks for that
I've spent another few hours on it, polling routine works all the way up to 200+ instruction delay, as i'd expect.
Now in disbelief that my code could possibly be giving me this result, i decided to toggle an LED to show what bit i receive as that 4th bit. I actually get the right bit !!!!!!!!!!!!!!!!! so the interupt is either somehow effecting my putchar (which it shouldn't) or the bit is getting corrupted somehow, anyway now i know my receive byte is working i'll do some more LED tests to see whats happening at other times
[edit]Update: i just checked the bit value before sending char, and its always 1, so its not my getchar or putchar thats causing the problem, the bit is someone getting modified |
|
|
elder
Joined: 16 Mar 2005 Posts: 19
|
|
Posted: Mon Mar 28, 2005 7:24 pm |
|
|
lol i found the problem, in getIrdaByte() u'll see i don't initialise ch to 0. Strangely the ch initialised as 0b00001000 when using the interupt method, but initialised as 0b00000000 when using the polling method.
I've got over 10+ pages full of calculations and drawings of bit signals here, 2 of them A3 sheets, its all pretty funny now |
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 29, 2005 2:04 am |
|
|
The classic 'Aargh' type problem.
The fact that it worked in the non-interrupt version, was misleading as to the root of the actual problem.
Glad you have it going now.
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
|