Shop OBEX P1 Docs P2 Docs Learn Events
MCP23017 help please — Parallax Forums

MCP23017 help please

basicstampedebasicstampede Posts: 214
edited 2006-07-27 17:19 in BASIC Stamp
Hello.

Has anyone used MCP23017 with Stamp?

The code below sort of works.·

The only problem is that GPIOB (Port B) is not working as expected.· The output data shows up in GPIOA for some reason.·
Data sent to GPIOA correctly shows up in Port A.

The schematic is simple.· The chip is properly connected as specified by Microchip with GPIOA and GPIOB configured as output.· Both ports are connected to the INEX board's 16 LEDs, with GPIOA connected to LED0-7 and GPIOB connected to LED8-15 on INEX board.

I just want to·output (%11111111)·on LED0-7·GPIOA·and LED8 (%10101010)·to LED15 using GPIOB.·

However, what happens·is that·LED0-7 is the only thing that is·being lit.
It appears to me that because of the mysterious·8 bit vs. 16 bit allowed by MCP23017, GPIOA is "lost" somehow.

The low level routines and medium level routines·correct (I've used this many times before).

When wired, the LED0-7 show %11111111·then 2 second pause, then LED0-7 shows·%10101010.

I was hoping that it would show %11111111 on LED8-15 then 2 second pause, then LED0-7 would be lit with %10101010 (with LED8-15 staying on as %11111111).

What is wrong?· Below is the code.·

'{$STAMP BS2p}
'{$PBASIC 2.0}
SDA CON 1
SCL CON 0
SDAin VAR IN1
MCP23017 CON %0100 << 4
Addr23017_1 CON %000 << 1
Wr_23017_1 CON MCP23017 | Addr23017_1 | 0
Rd_23017_1 CON MCP23017 | Addr23017_1 | 1
ACK CON 0
NAK CON 1
IOCON CON 10 'address in default bank = 0, 16 bit mode
'For bank = 0··········· 16 bit mode...do not use
'GPIOA CON 18
'GPIOB CON 19
'OLATA CON 20
'OLATB CON 21
'IPOLA CON 2
'IPOLB CON 3
'IODIRA CON 0
'IODIRB CON 16
'For bank = 1, 8 bit mode
GPIOA CON 18
GPIOB CON 19
OLATA CON 10
OLATB CON 26
IPOLA CON 1
IPOLB CON 17
IODIRA CON 0
IODIRB CON 16
i2cSDA VAR Nib
i2cData VAR Byte
i2cWork VAR Byte
i2cAck VAR Bit
Reg VAR Nib
outVal VAR Byte
inVal VAR Byte
obyte VAR Byte
ibyte VAR Byte
N VAR Nib
b VAR Bit

CRSRXY CON 2
Initialize:
PAUSE 250
i2cSDA =SDA
'Set up for bank = 1
Reg = IOCON 'IOCON address is 10 since chip defaults to bank 0
i2cData = %10000000· 'bank = 1, seqop = 1, all others as default
GOSUB Write_23017
Reg = 5 'address of IOCON in Bank = 1 (8 bit mode)
i2cData = %10100000
GOSUB Write_23017
'Set up GPIOB as output
Reg = IODIRB
i2cData = %00000000
GOSUB Write_23017
'Set up GPIOA as output
Reg = IODIRA
i2cData = %00000000
GOSUB Write_23017
Main:
'output to LED...sort of works...it outputs to GPIOB!!!· Why???
· Reg = OLATA
· i2cData = %11111111
· GOSUB Write_23017
· PAUSE 2000
'Works well.· It outputs to GPIOB as expected
· Reg = OLATB
· i2cData = %10101010
· GOSUB Write_23017
END
Write_23017:
· GOSUB I2C_Start
· i2cWork = Wr_23017_1
· GOSUB I2C_TX_Byte
· GOSUB Get_Ack
· IF (i2cAck = NAK) THEN Write_23017
· i2cWork = Reg
· GOSUB I2C_TX_Byte
· GOSUB Get_Ack
· i2cWork = i2cData
· GOSUB I2C_TX_Byte
· GOSUB Get_Ack
· GOSUB I2C_Stop
· DEBUG CR, "Wrote ", IBIN8 i2cData, " to output", CR
· RETURN
Read_23017:
· GOSUB I2C_Start
· i2cWork = Wr_23017_1
· GOSUB I2C_TX_Byte
· GOSUB Get_Ack
· IF (i2cAck = NAK) THEN Read_23017
· i2cWork = Reg
· GOSUB I2C_TX_Byte
· GOSUB Get_Ack
· GOSUB I2C_Start
· i2cWork = Rd_23017_1
· GOSUB I2C_TX_Byte
· GOSUB Get_Ack
· GOSUB I2C_RX_Byte
· GOSUB Send_NAK
· GOSUB I2C_Stop
· i2cData = i2cWork
· RETURN
I2C_Start:
· LOW SCL
· INPUT SDA
· INPUT SCL
· LOW SDA
· Clock_Hold:
· IF (INS.LOWBIT(SCL) = 0 ) THEN Clock_Hold
· LOW SCL
· RETURN
I2C_TX_Byte:
· LOW SCL
· OUTPUT SDA
· obyte = i2cWork
· FOR N=0 TO 7
··· b = (obyte >> 7) & 1
··· IF (b=1) THEN Out_1
··· LOW SDA
··· INPUT SCL
··· LOW SCL
··· GOTO nextb
· Out_1:
··· INPUT SDA
··· INPUT SCL
··· LOW SCL
·Nextb:
··· obyte = obyte << 1
··· NEXT
· RETURN

Get_Ack:
· LOW SCL
· INPUT SDA
· INPUT SCL
· b = SDAin
· 'INPUT SCL···· 'This line could be used in lieu of above line.· Both works.· This is why SHIFTIN works.
· LOW SCL
· i2cAck = b
·RETURN

I2C_RX_Byte:
· LOW SCL
· INPUT SDA
· ibyte = 0
· FOR N = 0 TO 7
··· INPUT SCL
··· ibyte = (ibyte <<1) | SDAin
··· LOW SCL
· NEXT
· i2cWork = ibyte
· RETURN
Send_NAK:
· LOW SCL
· INPUT SDA
· INPUT SCL
· LOW SCL
· RETURN
Send_ACK:
· LOW SCL
· OUTPUT SDA
· LOW SDA
· INPUT SCL
· LOW SCL
· RETURN
I2C_Stop:
· LOW SCL
· LOW SDA
· INPUT SCL
· INPUT SDA
· LOW SCL
· RETURN

Comments

  • basicstampedebasicstampede Posts: 214
    edited 2006-07-27 13:50
    Sorry, I meant to say:

    I was hoping that it would show %11111111 on LED0-7 then 2 second pause, then LED8-15 would be lit with %10101010 (with LED0-7 staying on as %11111111).

    NOT

    I was hoping that it would show %11111111 on LED8-15 then 2 second pause, then LED0-7 would be lit with %10101010 (with LED8-15 staying on as %11111111).
  • basicstampedebasicstampede Posts: 214
    edited 2006-07-27 14:03
    The Main program below has correct comments.

    OLATA (%11111111) is correctly shown on LED0-7.

    Then 2 sec. pause.

    Then OLATB (%10101010) shows up on LED0-7 (instead of on LED8-15 as I hoped).

    Any ideas?

    Main:

    'output to LED...works...LED0-7 shows %11111111
    · Reg = OLATA
    · i2cData = %11111111
    · GOSUB Write_23017

    · PAUSE 2000· '2 sec. pause

    'Why is this output to·LED0-7 again?· I was hoping to light up LED8-15
    · Reg = OLATB
    · i2cData = %10101010
    · GOSUB Write_23017
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2006-07-27 14:21
    basicstampede -

    I may or may not have a thought for you, but I'll be darned if I can find where (at what location, in which table) IOCON.BANK is defined in the data sheet. I KNOW I need to get new glasses, but I didn't think it had gotten this bad!

    I see where it's referenced, and what it means, I just can't find where it "lives". Give me that much an I may have a thought.

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    <!--StartFragment -->
  • basicstampedebasicstampede Posts: 214
    edited 2006-07-27 14:33
    Bruce,

    IOCON.Bank is register 10.· This is true when it powers up and defaults to 16 bit mode (IOCON.BANK = 0).·

    This is shown on Table 1-6 of MCP23017's datasheet.·

    My program sets the IOCON to 10 (see below).· Then I change bank to 1 and seqop to 1 (I want 8 bit mode without auto register increment).

    IOCON CON 10 'address in default bank = 0, 16 bit mode

    'For bank = 0··········· 16 bit mode...do not use
    'GPIOA CON 18
    'GPIOB CON 19
    'OLATA CON 20
    'OLATB CON 21
    'IPOLA CON 2
    'IPOLB CON 3
    'IODIRA CON 0
    'IODIRB CON 16

    'For bank = 1, 8 bit mode
    GPIOA CON 18
    GPIOB CON 19
    OLATA CON 10
    OLATB CON 26
    IPOLA CON 1
    IPOLB CON 17
    IODIRA CON 0
    IODIRB CON 16

    'Then I change bank to 1, and seqop to 1 (for 8 bit mode without auto increment).·

    'Set up for bank = 1
    Reg = IOCON 'IOCON address is 10 since chip defaults to bank 0
    i2cData = %10000000· 'bank = 1, seqop = 1, all others as default
    GOSUB Write_23017

    - - - - - - - - - -
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2006-07-27 14:46
    basicstampede -

    Fair enough, I flat out missed it <sigh>. Now, where does one specify 8 vs 16 bit access? Is it just a matter of setting that BANK code? Sorry to seem like I'm so dense, but that's a very confusing data sheet.

    In the mean time, you may want to take a gander at Nut and Volts Article 109 by Jon Williams "Expansion Made Easy" (link below). Although it's for the MCP23016, it may give you some hints or pointers, as I'd expect the control registers are similar or the same:
    http://www.parallax.com/html_pages/downloads/nvcolumns/Nuts_Volts_Downloads_V5.asp

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    <!--StartFragment -->
  • basicstampedebasicstampede Posts: 214
    edited 2006-07-27 15:15
    Bruce, you asked "Now, where does one specify 8 vs 16 bit access? Is it just a matter of setting that BANK code?"

    That is precisely what is confusing to me also.· I thought by setting IOCON.BANK to 1, then it is in 8 bit mode, and I should be able to operate it much like MCP23008 or MCP23016 (both of which I have used successfully).

    However, what is baffling me is that the data that I send out to GPIOB (connected to LED8-15 on INEX) actually gets outputted to LED0-7 (which is what GPIOA is connected to).

    Any ideas?· If there is a Microchip "expert" here that would greatly help.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2006-07-27 15:55
    basicstampede -

    Here I thought you knew something that I didn't AGAIN smile.gif

    I reeally didn't get that impression, that setting IOCON.BANK to 1, places it is in 8 bit mode, but I couldn't find any other direct reference in one of the tables. My interpretation was that IOCON.BANK = 0 put it in "byte mode" but NOT as oppsed to WORD mode, if you understand my meaning, and if I may borrow from the PBASIC Reference Manual.

    I had HOPED to see something in the control registers as simple as "single/double", "8/16", or even something as cryptc as "A,B";"A+B" representing the data width. Life is not so simple though.

    WHOA! There are TWO IOCONs, one at $0A and one at $0B according to Table 1-6. I'll bet you set one, or the other, or both, for PORTA (8 bit access), PORTB (8 bit access) or PORTA + PORTB (16 bit access)! Give that a shot.

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    <!--StartFragment -->

    Post Edited (Bruce Bates) : 7/27/2006 4:52:31 PM GMT
  • basicstampedebasicstampede Posts: 214
    edited 2006-07-27 17:19
    Bruce, thanks.· I tried all combinations and permutations I could think of.· Either it doesn't work at all, or the best situation is what I described above.· i.e. GPIOA is correctly displayed as %11111111 on LED0-7, then GPIOB is displayed on LED0-7 again (bit pattern %10101010 is correct, but wrong LEDs).

    It is very frustrating.
Sign In or Register to comment.