Problems to identify Interrupts

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Wed Dec 20, 2006 4:23 pm

Thanks Dave. Your explanations make it clearer to me now. :D

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed Dec 20, 2006 4:38 pm

> Thanks Dave. Your explanations make it clearer to me now.

No problem. Glad it was of some use.

> Now I want go back to the beginning of this thread

Here is a program which will switch on an LED connected to PORTA.0 if a button connected to PORTB.0 is held for more than (n) milliseconds. The LED is switched off when the button is released. It also supports a simple debouncing mechanism.

This program has been tested and works OK on my hardware. It can be extended to support more buttons...

Code: Select all

// program constants...
const
   ReloadTimerValue = 65536 - _clock * 250, 
   btnDebounce = 20,   // 20 millseconds
   btnTimeout = 5000   // 5 second hold time...
   
// timer registers...
dim 
   TMR0 as TMR1L.AsWord,
   TMR0IF as PIR1.Booleans(0),
   TMR0IE as PIE1.Booleans(0),
   TMR0On as T1CON.Booleans(0),
   RBPU as INTCON2.7, 
   INT0IE as INTCON.4,
   INT0IF as INTCON.1

// button structure...
structure TButton
   Timeout as word
   Debounce as byte
end structure
dim Button as TButton
    
// an interrupt declaration with no param
// is high priority by default   
interrupt OnChange()
   if INT0IF = 1 then
      INT0IF = 0
      Button.Debounce = btnDebounce
      Button.Timeout = btnTimeout
   elseif TMR0IF then
      TMR0IF = false
      TMR0 = TMR0 + word(ReloadTimerValue)     
      if Button.Debounce > 0 then
         dec(Button.Debounce)
      elseif PORTB.0 = 1 then
         Button.Timeout = 0
         low(PORTA.0)
      elseif Button.Timeout > 0 then
         dec(Button.Timeout)
         if Button.Timeout = 0 then
            high(PORTA.0)
         endif
      endif   
   endif    
end interrupt

// program start...
clear(Button)    // init button
ADCON1 = $07     // set ANx to digital
low(PORTA.0)     // LED A is low, set to output

INTCON2.6 = 0    // INT0 on falling edge
RBPU = 0         // enable weak pullups
INT0IE = 1       // enable INT0
enable(OnChange) // enable interrupt handler

TMR0 = ReloadTimerValue
TMR0IF = false  // clear TMR0 IF
TMR0IE = true   // enable TMR0 interrupts
TMR0On = true   // switch timer on
      
// loop forever...
while true
wend

CS
Posts: 127
Joined: Thu Nov 02, 2006 9:14 am

Post by CS » Wed Dec 20, 2006 6:59 pm

Hi David,

thanks for the program with the debouncing- and the timer part. It looks very complex, so I have to test and hopefully understand what's going on there. Until then

reguards

CS

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed Dec 20, 2006 8:45 pm

> It looks very complex...

You could remove the debounce if you like, it would work OK given the amount of time you have to detect a button hold state. Makes it a little easier to follow - just thought it nice to show how easy it is to add debouncing.

Anyway, here are the changes...

Code: Select all

dim ButtonTimeout as word
    
// an interrupt declaration with no param
// is high priority by default   
interrupt OnChange()
   if INT0IF = 1 then
      INT0IF = 0
      ButtonTimeout = btnTimeout
   elseif TMR0IF then
      TMR0IF = false
      TMR0 = TMR0 + word(ReloadTimerValue)     
      if PORTB.0 = 1 then
         ButtonTimeout = 0
         low(PORTA.0)
      elseif ButtonTimeout > 0 then
         dec(ButtonTimeout)
         if ButtonTimeout = 0 then
            high(PORTA.0)
         endif
      endif   
   endif    
end interrupt

// program start...
clear(ButtonTimeout)    // init button

CS
Posts: 127
Joined: Thu Nov 02, 2006 9:14 am

Post by CS » Wed Dec 20, 2006 9:11 pm

Hi David,

The debounce thing is quit nice because I normaly use a RC-Komponent to debounce the switches. (I asked for debouncing some posts ago so it is nice to have it although I didn't understand it yet.)

Only for understanding and using the right form of declarations in the future I want to know wich is the right one

Code: Select all

DIM TMR0IF As PIR1.Booleans(0) 

OR

DIM TMR0IF As PIR1.0
For my understanding it means tha the bit 0 from register PIR1 can have the true or the false (first line). It is like 1 and 0 (second line). Wich is the normaly used way?Thanks

CS

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed Dec 20, 2006 9:30 pm

> For my understanding it means tha the bit 0 from register PIR1
> can have the true or the false (first line). It is like 1 and 0
> (second line). Wich is the normaly used way?

Good question. It's just a style of coding issue. It's entirely up to you which one you use.

I quite like making bits 'boolean' types. Although

Code: Select all

DIM TMR0IF As PIR1.0 
has the virtue of matching the MCU datasheet notation, which I know many people prefer (I do sometimes, it just depends on what I am doing). In some situations, using booleans can make the code more readable, particulary with constructs that require a boolean expression. For example,

Code: Select all

dim TimerIsFlagged as PIR1.Booleans(0)

if TimerIsFlagged then
   ...
endif
but is does take you away from the datsheet somewhat. However, it can really help for some things. For example, take

Code: Select all

if PORTB.1 = 1 then
   ...
endif
then you would probably need to comment the code, indicating that when a button is released do something. With a boolean you can almost self document. For example,

Code: Select all

dim ButtonIsReleased as PORTB.Booleans(0)

if ButtonIsReleased then
   ...
endif
In summary

Code: Select all

if PIR1.0 = 1 then
   ...
endif

dim TMR0IF as PIR1.0
if TMR0IF = 1 then
   ...
endif

dim TMR0IF as PIR1.Booleans(0)
if TMR0IF then
   ...
endif
are treated the same - Swordfish is very flexible in this regard, so choose the style you prefer...

Post Reply