Problems to identify Interrupts

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

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

Post by CS » Sun Dec 17, 2006 7:27 pm

XOR,

ok I can see the problem with the INTCON2.7 but all the other things makes me confused.

TRISB = 1 means (for my understanding) that all Pins on PORTB are Input ports. I think that is a must for using the Interrrupts on PortB.

I have checked all ten registers wich are for controlling the interrups, but I haven't found some more hints like the one with the PullUps. :cry:

Thanks

CS

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

Post by xor » Sun Dec 17, 2006 7:58 pm

TRISB = 1 is equivalent to TRISB = %00000001. Since "0" is the output direction you can see that everything is outputs except RB0. You would want TRISB = %00000111 or TRISB = 7.

I would recommend that you test the switch interrupts first and separately to be sure they're working as you expect before moving into the GLCD routines. Also, make sure that you have the switches anchored to GND with pull-down resistors on the PORTB inputs.

Of course, the flip side to your switch triggered interrupts is to let RBPU remain active (low) and change the edge detection for High_To_Low. This can all be done with INTCON2 = 0. Connect your normally-open switches to ground. You will not need anchoring resistors on the inputs with this setup.

There shouldn't be many more "gotcha's".

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

Post by CS » Sun Dec 17, 2006 9:35 pm

Hi,

it's a shame! Now where I read your explanations I see my main problem! :oops: TRISB = 255 makes all Pins as Inputs!

I'll follow your suggestion and test the switch interrupts separatly.
Tomorrow I can give you the result.

Thanks for the tips.

CS

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

Post by xor » Mon Dec 18, 2006 12:14 am

We've all suffered the same problems and mistakes at some time or other, even when we know better. :D

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

Post by CS » Mon Dec 18, 2006 12:55 pm

Hi, Im backagain with no success. Instead I have more things wich I don't understand.

First here is my test project for interrupts:

Code: Select all


Device = 18F452
Clock =  20

Include "Utils.bas"

Dim INT0IF As INTCON.1,   ' INT0 External Interrupt Flag bit
    INT1IF As INTCON3.0,  ' INT1 External Interrupt Flag bit
    INT2IF As INTCON3.1   ' INT2 External Interrupt Flag bit
    
interrupt Switches() 
    
     If INT0IF = 1 Then
        Toggle(PORTA.0)   
        INT0IF = 0
     End If
     If INT1IF = 1 Then
         Toggle(PORTA.1)
          INT1IF = 0
     End If
     If INT2IF = 1 Then
        Toggle(PORTA.2)
        INT2IF = 0
     End If

End interrupt    
 
RCON = 0                 ' Disable Interrupt priority
INTCON  = %10010000      ' Enable all unmasked interrupts; External Interrupt Int0 enabled
INTCON2 = %00000000      ' PortB PullUps enable; External Interrups 0,1,2 at falling edge
INTCON3 = %00011000      ' External Interrupt INT2,INT1 enabled
 
TRISA = 0                ' configure all Pins of PORTA as outputs
TRISB = 255              ' configure all Pins of PORTB as inputs

PORTA = %01111           ' Should enable PORTA.0 till PORTA.4 (Input PORTA.4 is open drain when configured as Output
                         ' The output is inverse of the send logic)

While true
 
Wend

For my understanding it should work. The compiler compiles the program with no errors.

Instead it is flashy that the LED on PORTA.4 don't light. I thought it should work like I commented the code, but I'm not able to make the LED on PORTA.4 light.

I'm using EasyPic4 JP17 connected to GND (Then I press a button the pic get GND) I have enabled the RBPU's and the edge detection is High to low.

What can I do?

Thanks

CS

User avatar
mister_e
Posts: 28
Joined: Fri Oct 06, 2006 2:02 pm
Location: Montréal, Canada
Contact:

Post by mister_e » Mon Dec 18, 2006 7:03 pm

You're SOOOOOOO close.

First you need to disable the ADCs , this will make you led working.

BUT the most important step here... you must Enable the Interrupts. Or it will never work. Oh well the EasyPic4 will look at you and say... "Hey guy.. it's getting boring here to spin in round!" :wink:

Once done, it should look something like.

Code: Select all

Device = 18F452
Clock =  20

Include "Utils.bas"

Dim INT0IF As INTCON.1,   ' INT0 External Interrupt Flag bit
    INT1IF As INTCON3.0,  ' INT1 External Interrupt Flag bit
    INT2IF As INTCON3.1   ' INT2 External Interrupt Flag bit
   
interrupt Switches()
   
     If INT0IF = 1 Then
        Toggle(PORTA.0)   
        INT0IF = 0
        End If

     If INT1IF = 1 Then
        Toggle(PORTA.1)
        INT1IF = 0
        End If

     If INT2IF = 1 Then
        Toggle(PORTA.2)
        INT2IF = 0
        End If

End interrupt   

RCON = 0                 ' Disable Interrupt priority
INTCON  = %10010000      ' Enable all unmasked interrupts; External Interrupt Int0 enabled
INTCON2 = %00000000      ' PortB PullUps enable; External Interrups 0,1,2 at falling edge
INTCON3 = %00011000      ' External Interrupt INT2,INT1 enabled
 
TRISA = 0                ' configure all Pins of PORTA as outputs
TRISB = 255              ' configure all Pins of PORTB as inputs

PORTA = %01111           ' Should enable PORTA.0 till PORTA.4 
                         ' (Input PORTA.4 is open drain when configured As Output   
                         ' The output is inverse of the send logic)
    '
    '   Disable ADCs
    '   ============
ADCON1= $0F              ' Disable ADCs (OK OK SetAllDigital also work ;o) )
    '
    '    Enable Interrupts
    '   ==================
Enable(Switches)         
    '
    '
    '
While true
 
Wend 
It work for me using the same hardware and jumper setting.

Enjoy! :D

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

Post by CS » Tue Dec 19, 2006 12:59 pm

Hi mister_e,

you're the men! I have to admit, that I should read the help untill the end so I would notice, that I have to enable the interrupts. :oops:

The other part of the problem is still existing. The LED on PORTA.4 is still dark. I can do what ever I want I can't make the LED on PORTA.4 light although I use the order SetAllDigital.

Should I start a new thread or is this depending on the interrupts, or is my EasyPic4 damaged? (I don't thing that it is damaged but who knows?)
With the switch on board I can make it light.

Thanks

CS

P.S.: How to make the switch contact once when I press it( In Germany we say 'entprellen'?) When I press the button sometimes the light toggle 2 times. Is it possible to solve that within the software?

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

Post by xor » Tue Dec 19, 2006 3:41 pm

RA4 is a unique pin on the '452 (and several others). It is an open-drain output, which means the drain side is not connected to anything. You must tie the pin through a resistor to Vdd. This also means that the output becomes inverted logic. As an input, it's has a Schmitt trigger. Both of these features have their applications and something I'll not try to explain here. But a search on the internet about open-drain and open-collector circuits, and also what a Schmitt trigger does, will help.

Something I would like to note about the enabled interrupts is that you already enabled them with your INTCON and INTCON3 settings. You shouldn't need to enable them again unless you disabled them somewhere. You need to reset your flags after an interrupt, which you've done.....but nothing else is required.

Since you've moved to use PORTA you must do as mister-e has suggested by disabling the ADC's, only that setting ADCON1 = 0x0F still has AN0, AN1, and AN2 active. Use ADCON1 = 6 or ADCON1 = 7.

To keep your switch from multiple triggering, you need to put a delay in there somewhere, or test the button for a change back to normal before resetting the interrupt flags.

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

Post by CS » Tue Dec 19, 2006 5:00 pm

Hi XOR,

Thanks for the explanations. I thought the open-drain port is as easy to handle as the other pins with the different that the output signal is invert the logic I send. OK, I found lots of informations about the open-drain port on the www. (Sometimes even in German :) )

With the interrupt point I have to disapoint you. I've tested your suggestion with the enable thing without success. If I use the Enable(interrupts) the program works if I don't use this line the program doesn't work!

Maybe David Barker can give a statement about that!?

Thanks

CS

User avatar
mister_e
Posts: 28
Joined: Fri Oct 06, 2006 2:02 pm
Location: Montréal, Canada
Contact:

Post by mister_e » Tue Dec 19, 2006 5:57 pm

DOH!

Yeah i goofed ADCON1=$0F don't apply in here... but it's not 100% my fault (well... hum hum)... i looked in the SetAllDigital sub and ... something need to be changed...

When using SetallDigital on this device, the asm generated is..

Code: Select all

I10_F1_000032 ; L#MK SETALLDIGITAL
I11_F3_000441 ; L#MK ADCON1 = $0F
        MOVLW 15
        MOVWF ADCON1,0
so something have to be change in the Utils module under the SetAllDigital() sub to include some other directive for the 18F452, 252...

i thought it could be there

Code: Select all

  // 8 - 13 channels - 0 comp
  #elseif _comparator = 0
  ADCON1 = $0F
But i guess it's not going to be an universal solution.. so maybe adding a line like

Code: Select all

  #elseif _device in (18F452, 18F252)
  ADCON1 = 7
could work.. well at least for these specifics one.

About the open drain... unless you decide to use the crow-baring method the easyPIc4 will not work as expected. for this specific pin. Personally, i would choose another pin and keep this one for interesting stuff like the multiplexed ToCKI (Timer 0 Clock in), or for a simple input.

For your push button behaviours, it's just a matter of debouncing... well there's tons of different method, polling them until they are released, then do a delay of few mSec to debounce. A timer interrupt is handy in these case.

My opinion, Enable( ) is a directive... same as ON interrupt Goto on other compiler(s). If you don't tell to use interrupt, it won't work. To me, it make sense.

Don't give up !

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

Post by xor » Wed Dec 20, 2006 12:48 am

CS wrote:With the interrupt point I have to disapoint you. I've tested your suggestion with the enable thing without success. If I use the Enable(interrupts) the program works if I don't use this line the program doesn't work!

Maybe David Barker can give a statement about that!?
It is possible. The compiler may take more control over the interrupts than I realized. Maybe Dave can clarify or I will look into the manual a bit more about this.

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

Post by xor » Wed Dec 20, 2006 12:54 am

mister_e wrote:My opinion, Enable( ) is a directive... same as ON interrupt Goto on other compiler(s). If you don't tell to use interrupt, it won't work. To me, it make sense.
Another thing for me to learn here. I suppose I am more used to discrete user control of the interrupt enables.

User avatar
mister_e
Posts: 28
Joined: Fri Oct 06, 2006 2:02 pm
Location: Montréal, Canada
Contact:

Post by mister_e » Wed Dec 20, 2006 6:10 am

Bah, once you know you need it ;)

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 1:43 pm

The first thing to note with Swordfish is that it supports both high and low priority interrupts. If you just declare one interrupt, it will default to high priority. For example,

Code: Select all

interrupt MyInt()
end interrupt

enable(MyInt)
Calling enable ensures that (a) MyInt is assigned to the correct interrupt vector and (b) that the correct global interrupt flag is set (for example, GIEH or GIEL).

Calling disable will switch global interrupts off. For example, you might have some timer, interrupt on change and USART code enclosed in your handler. If you use

Code: Select all

disable(MyInt)
Then the handler is disabled completely. To have both high and low interrupt handlers, you just need to pass a constant to denote the priority and enable as before. For example,

Code: Select all

interrupt MyIntA(1)
end interrupt

interrupt MyIntB(2)
end interrupt

enable(MyIntA)
enable(MyIntB)

If you examine the ASM, you will see

Code: Select all

        ORG 0X08
        BRA ISR_MYINTB_0
        ORG 0X18
        BRA ISR_MYINTA_0
        ...
        BSF RCON,7,0
        BRA MAIN
        ...
MAIN
        BSF INTCON,6,0
        BSF INTCON,7,0
You will also see in the ASM file that Swordfish will software context save BSR, WREG and STATUS for the low priority interrupt. This is correct, as the hardware shadow registers will be overwritten if a high priority interrupt is called when executing a low priority interrupt.

As you can see, this is very basic, but useful, system management of code that is required. Swordfish won't bloat an ISR. If you wrote raw ASM, you would need to perform these steps anyway and it wouldn't be any smaller than the code generated by Swordfish.

Even though the above code will compile, nothing is going to happen untill you enable a peripheral interrupt of some kind. Taking the INT0 and INT1 example outlined earlier...

Code: Select all

// some useful aliases...
dim 
   RBPU as INTCON2.7,    // RBPU, pullups
   INT0IE as INTCON.4,
   INT0IF as INTCON.1,
   INT1IE as INTCON3.3, 
   INT1IF as INTCON3.0
    
// an interrupt declaration with no param
// is high priority by default   
interrupt OnChange()
   if INT0IF = 1 then
      toggle(PORTA.0)
      INT0IF = 0
   endif
   if INT1IF = 1 then
      toggle(PORTA.1)
      INT1IF = 0
   endif 
end interrupt

ADCON1 = $07     // set ANx to digital
low(PORTA.0)     // LED A is low, set to output
low(PORTA.1)     // LED B is low, set to output

RBPU = 0         // enable weak pullups
INT0IE = 1       // enable INT0
INT1IE = 1       // enable INT1
enable(OnChange) // enable interrupt handler

// loop forever...
while true
wend
As you can see, you just need to concentrate on what flags are required to manage your interrupt. In this example, PORTA.0 will toggle when a button connected to PORTB.0 is pressed and PORTA.1 will toggle when a button connected to PORTB.1 is pressed.

As has already been pointed out, the above could do with some debouncing, else the behaviour will be ratty to say the least. However, I have tested this code on a PROTON development board with no problems. If you cannot get it to work on your system, you need to check your particular hardware configuration.

I should also restate here what is already in the help file,
The basic context saving of an interrupt means it is unsuitable for supporting high level language constructs. For example, what appears to be a simple statement may involve using many different system and compiler registers. If these are changed in your ISR, your main program will almost certainly fail. You should also never call another subroutine or function from an interrupt unless additional steps have been taken with respect to context saving.
So before moving forward, you need to at least get your basic INT0 and INT1 events working correctly, as shown above...

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

Post by CS » Wed Dec 20, 2006 2:54 pm

Again thanks for answering! Now I want go back to the beginning of this thread and I want to solve the thing with the 10 seconds.
The first answer came from:
TimB wrote: If you need any interrupt then you only need a simple timer.

In the code just check the port inputs and if set inc a counter, else clear it, once the count reaches 10 seconds worth then set another flag that your main prog looks for.

As I said a simple timer is all you need.
My code for that looks like:

Code: Select all


....

Dim Setup as boolean
....

while

       If PORTB.7 = 1 Then
           If Counter = 240 Then
              Setup = true
           Else
               Setup = false
               Dec(Counter)
           End If
        Else
            Setup = false
            Counter = 0
        End If
I don't get any function. I also don't know what exactly TimB mean. Can anyone help?

Thanks

CS

Post Reply