B4R Question MCP23017 Interrupt usage

atiaust

Active Member
Licensed User
Longtime User
Hi All,

Has anyone had any success in getting the Interrupt functions working on the MCP23017 port extender chip?

I am trying to use the interrupt functions on a MCP23017 with 12 push buttons as inputs, attached to a WEMOS D1 R2 controller.

I would like one of the MCP23017 interrupt pins (INTA, INTB) to change when one of the push buttons are pressed.

I have tried Erel's examples in https://www.b4x.com/android/forum/posts/461711/.

At this stage I have the device address set to 0x20, the IO set to Inputs using IODIRA & B set to 0xFF which set all IO's to Inputs and GPPUA & B to use the internal pull-up resistors for each Input.

From research I have found that once an Input changes state the interrupt flag INFTFA & B needs to be read to indicate which input was triggered.

In Erel's example.
B4X:
master.WriteTo(0x20, Array As Byte(0x12 + PortIndex)) 'will be either 0x12 or 0x13
Dim result() As Byte = master.RequestFrom(0x20,  1)
I assume that master.Write sets the device (0x20) and the address (0x12) to read from while the master.RequestFrom then reads the data back.

I have setup Interrupt pins with listeners but not able to get to work.

Does anyone have any ideas?

Thanks
 

atiaust

Active Member
Licensed User
Longtime User
Hi All,

For anyone who is interested I was able to get the interrupt functions working on the MCP23017 port extender.
I built a 4x3 key pad using keyboard push buttons to replace a faulty device which is no longer available.
All the keys switch to ground and all the inputs are held high with the MCP23017 internal pullup resistors.

For this project I needed to know when a key was pressed or released.

The attached code is not complete but the interrupt setup and key press/release is working.

Hope this is of use to someone.

Thanks

B4X:
'    Microchip - MCP23017 - 12C Port extender
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 300
#End Region

'
'    wemos pin    |    header board pin#
'        D7        |         D9        (GPIO13) Serial 2 (Rs232 to Motion Board) - Transmit
'        D6        |        D8        (GPIO12) Serail 2     "        "        "      - Recieve
'        D5        |        D7        IRQ for B channel MCP23017
'        D4        |        D6       
'        D3        |        D5       
'        D2/SDA    |        D4
'        D1/SLC    |        D3
'        D0        |        D2        IRQ for A channel MCP23017
'        TX        |        D1       
'        RX        |        D0       
'
'    Note: the IRQ channels need to be on D5 & D0 otherwise they interfere with the boot and program update functions
'

Sub Process_Globals
      Public Serial1 As Serial
      Private master As WireMaster
'     Private PortState(2) As Byte
    Private D1 As D1Pins
    Private IntA As Pin            ' MCP23017 Interrupt - A channel Buttons 0 to 7
    Private IntB As Pin            ' MCP23017 Interrupt - B channel Buttons 0 to 3
'    setup keys - Bank A - Middle row
    Private setRef As Int = 0        'A-16
    Private leftArrow As Int = 0    'A-32
    Private fast As Int = 0            'A-64
    Private rightArrow As Int = 0     'A-128
'    setup keys - Bank A - Bottom row
    Private cancel As Int = 0        'A-1
    Private downArrow As Int = 0    'A-4
    Private start As Int = 0        'A-8
'    setup keys - Bank B - Top row
    Private Plot As Int = 0            'B-1       
    Private upArrow As Int = 0        'B-4
    Private home As Int = 0            'B-8
'   
    
End Sub
'

Private Sub AppStart
    Serial1.Initialize(115200)
       Log("AppStart")
       master.Initialize
'    IODIRA & B - IO Direction - 1 is input - 0 is output
'    Use 0xFF to set all A to Inputs or 0x00 to set all A to outputs
'    use other Hex value to set a combination of Inputs and Outputs
       master.WriteTo(0x20, Array As Byte(0x00, 0xFF)) 'Set all A to inputs
      master.WriteTo(0x20, Array As Byte(0x01, 0xFF)) 'B inputs
'
'    IOPOLA & B - IO polarity - set to 0xFF so that inputs = 1 when activated
    master.WriteTo(0x20, Array As Byte(0x02, 0xFF)) 'Invert all A inputs
    master.WriteTo(0x20, Array As Byte(0x03, 0xFF)) 'B input
'
    Delay(100)    'not sure if delays are needed but there was some earlier issues
'   
'    GPPUA & B -    set all pullup resistors to 'ON' - Inputs are held 'High' 
    master.WriteTo(0x20, Array As Byte(0x0C, 0xFF))    'Set all A Pull ups on
    master.WriteTo(0x20, Array As Byte(0x0D, 0xFF))    'Set all A Pull ups on
'
    Delay(100)
'    INTCONA & B - Interrupt configuration
    master.WriteTo(0x20, Array As Byte(0x08, 0x00)) 'doesn't work if set to FF ??
    master.WriteTo(0x20, Array As Byte(0x09, 0x00))
'
'    GPINTENA & B - Interupt on change -    set interrupt status =
    master.WriteTo(0x20, Array As Byte(0x04, 0xFF))
    master.WriteTo(0x20, Array As Byte(0x05, 0xFF))
    '
'    DEFVALA & B - Default comparison for interrupt (interrupts on opposite)
'    master.WriteTo(0x20, Array As Byte(0x06, 0xFF))
'    master.WriteTo(0x20, Array As Byte(0x07, 0xFF))
'   
'    INTCON - IO Configuration
'    master.WriteTo(0x20, Array As Byte(0x0A, 0x00))
'    master.WriteTo(0x20, Array As Byte(0x0B, 0x00))
'
    Delay(100)   
'
'    Setup listeners for interrupts
    IntA.Initialize(D1.D0, IntA.MODE_INPUT)
    IntA.AddListener("IntA_StateChanged")
'
    IntB.Initialize(D1.D5, IntB.MODE_INPUT)
    IntB.AddListener("IntB_StateChanged")
'

End Sub

'Keys from Bank A are 1,2,4,8,16,32,64 & 128
'Keys from Bank B have 255 added to thier value so 1 becomes 256, 2 = 257, 4 = 259, 8 = 263
'Each key 'Press' has 2 read operations and key 'Release' has 2 int operations.
'State 0 is when the key is pressed or released. State 1 is when the interrupt is read
'
 Sub IntA_StateChanged (State As Boolean)
'    Log("Int A Called - State = ",State)
    master.WriteTo(0x20, Array As Byte(0x0E))    ' read the interrupt flag register to see which key set the interupt
    Dim result() As Byte = master.RequestFrom(0x20, 1)
    Dim keyCode As Int = result(0)
'    Log ("Int A Flag = ",result(0))
'
    If State = False Then
        keyPressed(keyCode)
        master.WriteTo(0x20, Array As Byte(0x12))    ' read IO and reset the interupt
        Dim result() As Byte = master.RequestFrom(0x20, 1)       
    End If
'   
End Sub

'
Sub IntB_StateChanged (State As Boolean)
'    Log("Int B Called - State = ",State)   
    master.WriteTo(0x20, Array As Byte(0x0F))    ' read the interrupt flag register to see which interupt was set
    Dim result() As Byte = master.RequestFrom(0x20, 1)
    Dim keyCode As Int = result(0) + 255    ' add 255 to so I know this key is from bank 'B'
'    Log ("Int B Flag = ",keyCode)
'   
    If State = False Then
        keyPressed(keyCode)
        master.WriteTo(0x20, Array As Byte(0x13))    ' read IO and reset the interupt
        Dim result() As Byte = master.RequestFrom(0x20, 1)
    End If   
'   
End Sub

'
Sub keyPressed(key As Int)
    Select key
        Case 1    'CANCEL key
'            Log("key = CANCEL")
            If cancel = 0 Then
                cancel = 1
                Log("cancel - Key Down")
                'send key down command
            Else
                cancel  = 0
                Log("cancel - Key Up")
                'send key up commands
            End If
'           
        Case 4
            Log("Key = Y-")
'
        Case 8
            Log("Key = START")
        Case 16
            Log("Key = SET REF")
        Case 32
            Log("Key = X-")
        Case 64    'FAST key
'            Log("Key = FAST")
            If fast = 0 Then
                fast = 1
                Log("FAST - key down")
                'send key codes
            Else
                fast = 0
                Log("FAST - key up")
                'send key codes
            End If   
        Case 128
            Log("Key = X+")   
            
        Case 256
'            Log("Key = PLOT")
            If Plot = 0 Then
                Plot = 1
                Log("PLOT - key down")
                'send key codes
            Else
                Plot = 0
                Log("PLOT - key up")
                'send key codes           
            End If
        Case 259
            Log("Key = y+")
        Case 263
            Log("Key = HOME")       
        Case Else
                        
    End Select
'   
End Sub
 
Upvote 0
Top