Problems to identify Interrupts
Moderators: David Barker, Jerry Messina
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.
Thanks
CS
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.
Thanks
CS
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".
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".
Hi, Im backagain with no success. Instead I have more things wich I don't understand.
First here is my test project for interrupts:
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
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
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
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!"
Once done, it should look something like.
It work for me using the same hardware and jumper setting.
Enjoy!
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!"
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
Enjoy!
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.
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?
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.
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?
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.
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.
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
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
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..
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
But i guess it's not going to be an universal solution.. so maybe adding a line like
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 !
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
i thought it could be there
Code: Select all
// 8 - 13 channels - 0 comp
#elseif _comparator = 0
ADCON1 = $0F
Code: Select all
#elseif _device in (18F452, 18F252)
ADCON1 = 7
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 !
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.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!?
- David Barker
- Swordfish Developer
- Posts: 1214
- Joined: Tue Oct 03, 2006 7:01 pm
- Location: Saltburn by the Sea, UK
- Contact:
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,
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
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,
If you examine the ASM, you will see
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...
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,
Code: Select all
interrupt MyInt()
end interrupt
enable(MyInt)
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)
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
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 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,
So before moving forward, you need to at least get your basic INT0 and INT1 events working correctly, as shown above...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.
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:
I don't get any function. I also don't know what exactly TimB mean. Can anyone help?
Thanks
CS
The first answer came from:
My code for that looks like: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.
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
Thanks
CS