External interrupt for ZX24u

Discussion specific to the 24-pin ZX microcontrollers, e.g. ZX-24r, ZX-24s and ZX-24t.
Post Reply
Jim Wilson
Posts: 2
Joined: 28 January 2016, 7:13 AM

External interrupt for ZX24u

Post by Jim Wilson »

I am working with a ZX24u using the xmega128A4U. I would like to create an external interrupt to wake the controller up. Looks like Pin 6 can be setup for this, but I'm having trouble understanding how to set up the interrupt in the software. No problem putting the controller to sleep.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

You may be able to use WaitForInterrupt() but you'd have to have that call in a separate task from the one that enters sleep mode. It may be simpler to write your own code to enable a pin change interrupt and write the interrupt handler for it. Any I/O pin can be used for the pin change interrupt and such interrupts will awaken the device in all sleep modes.

To write this specialized code you'll need the xmega datasheets. You can get the datasheets specific to the A4U device from the Atmel website. However, the primary difference between the A4 and the A4U is the presence of the USB controllers in the latter so you should be able to get the information you need from the xmega A4 datasheets available via links at the bottom of the Downloads Page.
- Don Kinzer
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

The sample code below configures an xmega device to generate an interrupt on a state change of a pin. The code is written specifically for pin C.0 but it can be modified for any pin of any port by following the instructions. It uses port interrupt 0 but it could be modified to use port interrupt 1 if necessary.

Code: Select all

Const PORT_INT0IF_bm as Byte = &H01        ' interrupt flag
Const PORT_INT0LVL_gm as Byte = &H03       ' priority mask
Const PORT_INT0LVL as Byte = &H02          ' medium priority    
Const PORT_ISC_gm as Byte = &H07           ' input sense mask
Const PORT_ISC_val as Byte = &H00          ' either edge

Dim Volatile pinChange as Boolean

Sub Main()
    Call initPinChangeInt()
    Do
        If (pinChange) Then
            Debug.Print "got pin change"
            pinChange = False
        End If
    Loop
End Sub

'
'' initPinChangeInt
'
' This subroutine sets up a pin for a pin change interrupt on either edge.  The code
' is written specifically for pin C.0.  To modify it for a pin on a different port, change
' the occurrences of PORTC to PORTA, PORTD, etc.  Further, the value written to the INTOMASK
' register must be modified to reflect the bit of the port and the PIN0CTRL must be changed
' to match the bit number as well.  For example, to change to B.7, PORTC must be changed to
' PORTB, the value assigned to Register.PORTB_INT0MASK must be changed to &H80 and
' Register.PORTC_PIN0CTRL must be changed to Register.PORTB_PIN7CTRL.
'
Sub initPinChangeInt()
    ' set the pin for level change interrupt
    Register.PORTC_PIN0CTRL = (Register.PORTC_PIN0CTRL And Not PORT_ISC_gm) Or PORT_ISC_val

    ' clear any pending interrupt
    Register.PORTC_INTFLAGS = PORT_INT0IF_bm
    
    ' prepare for the pin change interrupt
    Register.PORTC_INT0MASK = &H01    ' change the value to reflect the port pin
    Register.PORTC_INTCTRL = (Register.PORTC_INTCTRL And Not PORT_INT0LVL_gm) Or PORT_INT0LVL
End Sub

'
' This is the ISR for the pin change interrupt.  For purposes of this example, a flag is set
' to indicate that the interrupt occurred.
'
ISR PORTC_INT0()
    pinChange = True
End ISR
- Don Kinzer
Jim Wilson
Posts: 2
Joined: 28 January 2016, 7:13 AM

Post by Jim Wilson »

Thanks for the great reply. Very helpful.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

I neglected to mention that the flag in the pin change ISR is only needed for the test driver implemented in Main(). For the use case of awakening from sleep an empty ISR would work fine but even then, the flag indicating the occurrence of the interrupt might be useful.

Further, you can change the trigger condition of the pin change interrupt by changing the value of the PORT_ISC_val constant.
- Don Kinzer
Post Reply