Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

PCINT Interrupts how to use?

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    www.mcselec.com Forum Index -> BASCOM-AVR Archive
View previous topic :: View next topic  
Author Message
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Thu Dec 23, 2010 11:18 am    Post subject: PCINT Interrupts how to use? Reply with quote

I want to use PCINT8 as an Interrupt but am having a hard time finding some sort of example on how to use these sort of Interrupts in Bascom I can find little bits but not a step by step example that explains it can any body point me to one.
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6197
Location: Holland

blank.gif
PostPosted: Thu Dec 23, 2010 11:34 am    Post subject: Reply with quote

did you checked the pcint_change.bas sample from the samples dir?
_________________
Mark
Back to top
View user's profile Visit poster's website
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Thu Dec 23, 2010 11:45 am    Post subject: Reply with quote

Did not see that! I have been going through the help trying to work it out I will have a look at the example and see if I can work it out thank you for the pointer (again!)

regards Paul
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6197
Location: Holland

blank.gif
PostPosted: Thu Dec 23, 2010 12:02 pm    Post subject: Reply with quote

the sample shows 2 ways, it would be better to make an example for non interrupt based, and interrupt based.
maybe an enthusiast user can make better samples Smile

_________________
Mark
Back to top
View user's profile Visit poster's website
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Thu Dec 23, 2010 12:05 pm    Post subject: Reply with quote

So looking at the example

Enable Interrupts 'enable global ints
Enable Pcint0 'we enable pcint0 as this has pcint0-pcint7

Then would
Enable Pcint1 cover pcint8-pcint15

Regards paul
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Thu Dec 23, 2010 12:17 pm    Post subject: Reply with quote

When I get this hardware to work I will post the whole program. I am trying to respond to a DTMF decoder when it has a lock on a tone pair. As I can do this in a loop I will do it that way as an example but also want to do it as a jump due to an interrupt so that it does not slow things up. The reason for PCINT8 is that its spare on the board to be used.
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6197
Location: Holland

blank.gif
PostPosted: Thu Dec 23, 2010 12:23 pm    Post subject: Reply with quote

Paulvk wrote:
So looking at the example

Enable Interrupts 'enable global ints
Enable Pcint0 'we enable pcint0 as this has pcint0-pcint7

Then would
Enable Pcint1 cover pcint8-pcint15

Regards paul


yes that is right.

_________________
Mark
Back to top
View user's profile Visit poster's website
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Tue Dec 28, 2010 7:21 am    Post subject: Reply with quote

Ok I have the pin change interrupt working (PCINT8) but how do I get it to respond only to a rising change ie logic 0 to 1 but not when it goes back 1 to 0 again.
Back to top
View user's profile
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 906
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Tue Dec 28, 2010 7:42 am    Post subject: Reply with quote

You can not.
PCINT.... are only change interrupts and can not be configured.
If you need rising or falling then you need to use int0 or int1 for example.
The possibility you have with PCINT is to read the port pin on interrupt and determine the state of the input, so you can determine if this is the interrupt to perform the wanted action.You hopefuly masked the interrupt, otherwise you also get int's from the other pcints in that group (I did not read the sample).
See the AVR datasheets for external interrupts.
Hubert
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Tue Dec 28, 2010 8:02 am    Post subject: Reply with quote

Ok that confirms what I suspected after reading through the data sheets and bascom (a number of times) yes I have masked the interrupt, I did not use one of the normal interrupts as I did not want to make a total new artwork and did not know then that INT0, INT1 would be the best to use. It has taught me more though, I will also learn more as I work around the state changes and move on to the next problem I have given myself, how to swap around binary 0100 to 0010 as I have the 4 bits around the wrong way at least the hardware works it detects the DTMF and decodes it.
Back to top
View user's profile
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 906
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Tue Dec 28, 2010 9:27 am    Post subject: Reply with quote

If you talk about input bits in a nibble, there are a few possibilities.
You can make a 16-byte conversiontable but the easiest maybe not most elegant is to declare 1 variable read the corresponding bitlocation and write the bit to the new location in the variable. An other mothode would be to AND, then shift and add also in extra variables 4 times ( a bit more time consuming).
Hubert
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Tue Dec 28, 2010 10:02 am    Post subject: Reply with quote

This has the interrupt working for a 0 to 1 transition and the bits I want are 1,2,3,4 as I used 0 as the pin change a re-do of the hardware would get rid of the mirror bits but what the heck I have learnt more this way.


Code:
Isr_pcint1:

If Pinc.0 = 1 Then

Cls

  Locate 1 , 1

  Lcd "Pin change "
  'As you see the mask does not change, so to find out which pin changed,
  'you need to read the PINC register.

  'Wait 2

  A = Pinc

  B = A And &B0001_1110                                     'Mask To Get to get bits 1,2,3,4

  Shift B , Right

  Locate 2 , 1




  Lcd B

 ' C = A And &B0000_1111                                 'Mask To Get Only Low Nibble Of Byte , Store As C



  'Wait 2

  Return

  End If

Return

 


Regards Paul
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Sat Jan 15, 2011 8:38 am    Post subject: Reply with quote

Ok I have a working example of pin change interrupt this uses a VOIP ATA to enable remote control of some relays, it answers the call after a pre set number of rings then waits and decodes DTMF tones sent to it. This is the prototype made with 3 seperate boards I am now making a finished version on one board this code would show how to use the interrupts if mark wants he can use it to replace the example in bascom. Any improvements/comments are most welcome.

Code:
'---------------------------------------------------------------------------

'---------------------------------------------------------------------------
'
'                             DTMF-DECODE.BAS
' This shows how to use the PIN CHANGE interrupts to decode DTMF using
' a HT9170 DTMF decoder that has a 4 bit output to enable remote control over
' a VOIP telephone adapter. It counts the number of rings and loops the adapter
' at a pre set number of rings then waits for DTMF digits
'---------------------------------------------------------------------------

$regfile = "m168pdef.dat"                                   'Using the Mega168p
$crystal = 8000000
'$crystal = 1000000                                          'Using the internal RC at 8 meg
$baud = 19200

'Print "{027}[2J";                                           ' when you have a terminal emulator, this will clear the screen
'Print "Test M88 ints"                                       ' init message

'The M88 and M168 can detect a level change on all port pins.



Dim A As Byte                                               'These are 8 bits
Dim B As Byte
Dim D As Byte
Dim R As Byte
Dim Timeout As Byte
Dim Dtmf As String * 1                                      'Only one character in this string
Dim Con As String * 16                                      'Can be 16 characters in this string


Config Pinc.0 = Input                                       'enable port as input
Config Pinb.7 = Input                                       'enable port as input


Config Pinb.2 = Output                                      'enable port as output

Config Pind.6 = Output                                      'enable port as output

Config Pind.7 = Output                                      'enable port as output

                                                             'An Alias makes it easy to refer to the PIN
Rly Alias Portd.7

Led Alias Portb.2                                           'the GATE of the FET transistor connected to PortB.2,
                                                             'with resistor (390 Ohm) to turn on LCD backlight take to GND
Relay Alias Portd.6                                         'A transistor on this port operates a relay to loop the line

Enable Interrupts                                           'enable global Interrupts

Enable Pcint0                                               'we enable pcint0 as this has pcint0-pcint7

On Pcint0 Isr_pcint0                                        'we jump to this label when one of the pins is changed

Pcmsk0 = &B10000000
          '76543210--pcint7--pcint0 pcint7 is on
Enable Pcint1                                               'we enable pcint1 as this has pcint8-pcint15

On Pcint1 Isr_pcint1                                        'we jump to this label when one of the pins is changed

Pcmsk1 = &B00000001                                         'enable pcint8  (portc.0)
          '15.14.13.12.11.10.9.8--pcit8 is on                With pcmsk you individualy select which pins must react on a logic level
                                                            'When you write a 1, the change in logic level will be detected.


Set Led                                                     'Turn on LCD backlight


Do

    Cls

 Locate 1 , 1

 Lcd "loop de loop"
 Lcd R

 Locate 1 , 14
 Lcd Timeout


 Locate 2 , 1

 Lcd "NUMBERS " ; Con


 If R > 4 Then

 Set Relay                                                  'This sets the port to a 1 which is +5V turning on the transistor and with it the relay

 R = 0

 End If

 If Len(con) > 6 Then                                       'If too many digits are sent it clears variable to start over

 Con = ""

 End If


 Wait 1

 If Relay = 1 Then                                          'Start a time out counter

     Timeout = Timeout + 1


 End If


 If Timeout = 60 Then                                       'When the counter = 1 min hang up

 Timeout = 0                                                'Reset counter to 0

 Con = ""                                                   'Clear any digits


 Reset Relay                                                'Release line

 Waitms 20                                                  'wait for things to stablize

 R = 0                                                      'Reset ring counter

 End If

 If Con = "##58##" Then

   Reset Relay                                              'This resets the port to a logic 0 which is 0V turning off the transistor and with it the relay


   Con = ""

   Waitms 20

   R = 0

 End If

 If Con = "##66##" Then

 'Cls

 'Locate 1 , 1
 'Lcd "SET RLY"

 'Wait 1

  Set Rly
  'Pind.7 = 0

  Con = ""

 End If

 If Con = "##67##" Then

 'Cls

 'Locate 1 , 1
 'Lcd "RESET RLY"

 'Wait 1

  Reset Rly
  'Pind.7 = 0

  Con = ""

 End If



 Loop


Isr_pcint0:

   If Pinb.7 = 0 Then

    Cls                                                     'Clear the LCD
    Locate 1 , 1
    Lcd "Phone is Ringing"
    Locate 2 , 1
    Lcd Str(r)

    R = R + 1

   Do

   Waitms 100                                               'Wait 100 mili seconds

   Loop Until Pinb.7 = 1                                    'Loop until pinb.7 goes to a logic 1 +5V
                                                             'this tells us that the line is not ringing

   End If




Return

Isr_pcint1:

If Pinc.0 = 1 Then                                          'There is a DTMF digit to decode

   Timeout = 0                                              'Reset timeout counter

'Cls
                                                             'Clear the LCD
  'Locate 1 , 1

  'Lcd "Pin change "
  'As you see the mask does not change, so to find out which pin changed,
  'you need to read the PINC register.


  A = Pinc                                                  'Read pin register for portC

  B = A And &B0001_1110                                     'Mask To Get to get bits 1,2,3,4
                                                             '&B0000_1111  Mask To Get Only Low Nibble Of Byte
                                                             '&B1111_0000  Mask To Get Only High Nibble Of Byte
  Shift B , Right                                           'Move the bits one to the right so they represent
                                                             'a 4 bit binary number 0 to 16

  'Locate 2 , 1




  'Lcd B





  'Since I have the 4 bits backwards I have to translate the values


  Select Case B

      Case 5 : Dtmf = "0"
      Case 8 : Dtmf = "1"
      Case 4 : Dtmf = "2"
      Case 12 : Dtmf = "3"
      Case 2 : Dtmf = "4"
      Case 10 : Dtmf = "5"
      Case 6 : Dtmf = "6"
      Case 14 : Dtmf = "7"
      Case 1 : Dtmf = "8"
      Case 9 : Dtmf = "9"
      Case 13 : Dtmf = "*"
      Case 3 : Dtmf = "#"
      Case 11 : Dtmf = "A"
      Case 7 : Dtmf = "B"
      Case 15 : Dtmf = "C"
      Case 0 : Dtmf = "D"

  End Select

  'Cls                                                       'Clear the LCD

  'Locate 2 , 5                                              'Print at line 2  position 5 on LCD




  'Lcd Dtmf                                                  'Print the DTMF value to the LCD
  Con = Con + Dtmf                                          'Add the value to the string

  'Locate 2 , 7                                              'Print at line 2  position 7 on LCD

  'Lcd Con                                                   'Print the recived values thus far to the LCD



  End If

Return

End

 
Back to top
View user's profile
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 906
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Sat Jan 15, 2011 5:50 pm    Post subject: Reply with quote

The ENABLE INTERRUPTS would normaly be the last thing after all the setup.
I would also not spend so much time in the ISR routines because as long as you are in the ISR no other interrupt is serviced with atmega.
This might not be a problem with your specific application but it is not a good practice in general.
Interrupts should only set a condition and then you do the evaluation from the main routine possibly in a sub.
If you have 4 pins that can change then you could use all four interrupts and branch in the main program after reading the port and AND with an "ON VALUE" or "CASE".
Just some thoughts
Hubert
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Sun Jan 16, 2011 6:59 am    Post subject: Reply with quote

All information is welcome, the events that trigger the interrupts are hardware events one is when the DTMF chip has valid tone pairs the other is when the ATA puts ring on the line, it could have been done in a loop but I wanted to teach myself how to use the interrupts. I do understand that spending as short a time in the interrupt as possible is the best way but want I wanted to do was to have a program that runs but do something else when hardware events happen then go back to where it was and keep running. The project has served its purpose well it has and still is teaching me a lot plus I will have a usefull bit of harware to control devices with. When its finnished I will make both the code and hardware plans avaliable for all.
Back to top
View user's profile
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    www.mcselec.com Forum Index -> BASCOM-AVR Archive All times are GMT + 1 Hour
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
You cannot attach files in this forum
You cannot download files in this forum