BX24 Interface with a Microchip MCP23016 16-bit IO Expander

copyright, Peter H Anderson, Baltimore, MD, May, '03


A more complete description and additional routines will appear shortly.

' MCP23016_1.Bas
'
' Illustrates an interface with the MCP23016 16-bit I/O Expander.  This is inteneded to illustrate all features of the
' MCP23016 other than the capture feature; writing a byte to a register, reading a byte from a register and similarly writing
' and reading a bit at a specified bit position in a register.
'
' The MCP23016 is set up for high speed sampling by writing a 1 to register IOCON0, bit 0.  Port0 is set up for outputs by
' writing zeros to all eight bits of IODIR0.  Similarly Port1 is setup for all inputs by writing zeros to all eight bits of
' IODIR1.  The polarity of GP1.0 is inverted by writing a 1 to register IOPOL1, bit 0.
'
' The program continually loops, reading the state on input GP1.0.  If at logic zero, the LED on OLAT0.0 is turned on and off.
'
' Note that the reading of the input state of the GP1.0 bit involves reading the entire GP1 byte and determining the state of
' the specified bit.  Note that writing the bit to OLAT0.0 involves reading register OLAT0 and setting the specified bit to
' the specified state.
'
'
'      BX24 							MCP23016
'                 Note 1
'      Term 9 ------------------------ SDA (term 15) ----------- To other I2C devices
'      Term 8 ------------------------ SCL (term 14) -----------
'
'                               GRD --- A2 (term 16)
'                               GRD --- A1 (term 17)
'                               GRD --- A0 (term 18)
'
'
'                          GRD -- \---- GP1.0 (term 2)
'                                                                    LED
'                                       GP0.0 (term 21) ----- 330 ---->|--- GRD
'
'	Note 1.  4.7K resistor to +5 VDC on SDA, SCL and GP1.0.
'
'   CLK circuitry on CLK (term 9) consists of a 4.7K resistor and a 20 pFd capacitor.
'
'
' coyright, Peter H. Anderson, Baltimore, MD, May, '03

const SCL as byte=8
const SDA as byte=9

const GP0 as Byte = &H00
const GP1 as Byte = &H01
const OLAT0 as Byte = &H02
const OLAT1 as Byte = &H03
const IPOL0 as Byte = &H04
const IPOL1 as Byte = &H05
const IODIR0 as Byte = &H06
const IODIR1 as Byte = &H07
const INTCAP0 as Byte = &H08
const INTCAP1 as Byte = &H09
const IOCON0 as Byte = &H0A
const IOCON1 as Byte = &H0B


Sub Main()

   Call Sleep(1.0)			' to avoid download problems

   Debug.Print "..............."	' to see that something is happening

   Call MCP23016WriteBit(0, IOCON0, 0, 1)		' set to high sampling frequency
   Call MCP23016WriteByte(0, IODIR0, &H00)	' make Port0 outputs
   Call MCP23016WriteByte(0, IODIR1, &Hff)	' Port1 are inputs
   Call MCP23016WriteBit(0, IPOL1, 0, 1)		' input 0 on Port1 inverted.

   Do
      If (MCP23016ReadBit(0, GP1, 0) = 1) Then
         Call FlashLed()
      End If
   Loop

End Sub


Sub FlashLED()
   Call MCP23016WriteBit(0, OLAT0, 0, 1)	' turn LED on
   Call Sleep(0.25)
   Call MCP23016WriteBit(0, OLAT0, 0, 0)	' turn LED off
   Call Sleep(0.25)
End Sub

Sub MCP23016WriteByte(ByVal Dev as Byte, ByVal Reg as Byte, ByVal Val as Byte)
   Call I2CStart()
   Call I2COutByte(bx0100_0000 OR (Dev * 2))
   Call I2COutByte(Reg)
   Call I2COutByte(Val)
   Call I2CStop()
End Sub

Sub MCP23016WriteBit(ByVal Dev as Byte, ByVal Reg as Byte, ByVal BitPos as Byte, ByVal BitVal as Byte)
   Dim Val as Byte
   Val = MCP23016ReadByte(Dev, Reg)
   Call PutBit(Val, BitPos, BitVal)
   Call MCP23016WriteByte(Dev, Reg, Val)
End Sub

Function MCP23016ReadByte(ByVal Dev as Byte, ByVal Reg as Byte) as Byte
   Dim Val as Byte
   Call I2CStart()
   Call I2COutByte(bx0100_0000 OR (Dev * 2))
   Call I2COutByte(Reg)

   Call I2CStart()
   Call I2COutByte(bx0100_0000 OR (Dev * 2) + bx0000_0001)
   Val = I2CInByte(0)
   Call I2CStop()

   MCP23016ReadByte = Val
End Function

Function MCP23016ReadBit(ByVal Dev as Byte, ByVal Reg as Byte, ByVal BitPos as Byte) as Byte
   Dim Val as Byte
   Dim BitVal as Byte
   Val = MCP23016ReadByte(Dev, Reg)
   MCP23016ReadBit = GetBit(Val, BitPos)
End Function

Sub I2CStart()
   Call PutPin(SCL,0)
   Call PutPin(SDA,2)
   Call PutPin(SCL,2)
   Call PutPin(SDA,0)
   Call PutPin(SCL,0)
End Sub


Sub I2CStop()
   Call PutPin(SCL, 0)
   Call PutPin(SDA, 0)
   Call PutPin(SCL,2)
   Call PutPin(SDA,2)
End Sub


Sub I2COutByte(ByVal X as Byte)

   Dim N as Integer

   For N=1 to 8

     If((x AND &H80) <> 0) Then
       Call PutPin(SDA,2)
'      Call PutByte(Asc("1"))   ' used for debugging
     Else
       Call PutPin(SDA,0)
'      Call PutByte(Asc("0"))	' used for debugging
    End If

    Call PutPin(SCL,2)
    Call PutPin(SCL,0)
    x=x*2

   Next

'  Call NewLine()		' used for debugging

   Call PutPin(SDA,2)
   Call PutPin(SCL,2)
   Call PutPin(SCL,0)
   Call PutPin(SDA,2)

End Sub

Function I2CInByte(ByVal Ack as Byte) as Byte

   Dim N as Integer
   Dim X as Byte

   FOR N=1 to 8

    Call PutPin(SCL,2)
    If(GetPin(SDA)=1) Then
      X = X * 2 +1
    Else
      X = X * 2
    End If
    Call PutPin(SCL, 0)
   NEXT

   If (Ack <> 0) Then
      Call PutPin(SDA, 0)
   Else
      Call PutPin(SDA,2)

   End If

   Call PutPin(SCL,2)
   Call PutPin(SCL,0)
   Call PutPin(SDA,0)
   I2CInByte = X

End Function