CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

help with interupt giving unexpected results (PIC = 16F648A)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
elder



Joined: 16 Mar 2005
Posts: 19

View user's profile Send private message

help with interupt giving unexpected results (PIC = 16F648A)
PostPosted: Thu Mar 24, 2005 3:25 am     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Thu Mar 24, 2005 7:07 am     Reply with quote

You kind of forgot to post the code that actually gets the byte! Maybe that is where the error is.

You might take a look at this
http://web.media.mit.edu/~ayb/irx/irda/irda.c
Guest








PostPosted: Fri Mar 25, 2005 2:43 am     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Fri Mar 25, 2005 8:11 am     Reply with quote

Whats your crystal speed?
elder



Joined: 16 Mar 2005
Posts: 19

View user's profile Send private message

PostPosted: Sat Mar 26, 2005 4:59 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Mar 28, 2005 2:53 am     Reply with quote

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







PostPosted: Mon Mar 28, 2005 4:21 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Mar 28, 2005 6:56 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Mar 28, 2005 7:24 pm     Reply with quote

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 Razz
Ttelmah
Guest







PostPosted: Tue Mar 29, 2005 2:04 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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