PDA

View Full Version : MCP23016 I2C serial I/O expander chip



GeoJoe
- 22nd October 2007, 22:47
Hi all,
Has anyone used the MCP23016 I/O expander with PBP? I can't seem to get the I2CREAD command to return anything. I'm using an 18F87J50. I have my LCD working and diagnostic LED's on my new board are all under control. I can see there is a bit stream on the data line that recurs on schedule. (I execute the I2CREAD command about every 5 seconds.)
Here is my code:

define osc 25
intcon = %10100000
intcon2 = %01000000
t0con = %11010101
rcon = %00000000
adcon0 = %00010001
adcon1 = %00001010

define lcd_dreg portd
define lcd_dbit 0
define lcd_rsreg porte
define lcd_rsbit 0
define lcd_ereg porte
define lcd_ebit 1
low porte.2
pause 500
define adc_bits 10

insin var word
insin = 0

Loop:
lcdout $fe, 1
lcdout "The lcd is working"
I2Cread portc.4, portc.3, %01000000, insin, noitwoc
lcdout $fe, $c0
lcdout dec insin
pause 5000
goto loop:

noitwoc:
lcdout $fe, 1
lcdout "no i2c ack"
pause 2000
goto loop

I have checked the schematic time and time again. It matches the I/O expander data sheet. and the data/clock pins match the code. I have measured the RC clock and it is running correctly. I have only tried the 3.9k and 33pF RC combo. I never get to the noitwoc loop so I ass'u'me I am recieving the acknowledge from the 23016. The 23016 spec sheet states that the chip is default to all inputs. But the variable insin never changes from 0 even if one or all pins are set high or low?

I am fairly certain that my problem is not hardware.

Any advice? Oh by the way the SFR's setup here work well with the 18F4525 setup to work with the LAB-X1 experimenter board. Except the dbit is 4 on the X1.

Thanks,
Joe

GeoJoe
- 22nd October 2007, 22:51
http://ww1.microchip.com/downloads/en/DeviceDoc/20090C.pdf

GeoJoe
- 23rd October 2007, 18:44
Below is modified code.
After re-reading (tfm) the spec i noticed that the 23016 requires: adress, command,adress (again), data, data,....
No on reset I get the no i2c ack display and I see on my oscope that there aren't quite enough bits on the data line. Then the next time the loop executes I get all expected bits on the data line, but the last two byte which I expect to be reflective of the I/O pins on the 23016 never change and are always low?

Here is the full code again:

INTCON = %10100000 ' Enable TMR0 interrupts
INTCON2 = %01000000 ' ENABLES PORTB PULL UPS
T0CON = %11010101 ' ENABLES TM0 AND SET PRESCALER
RCON = %00000000 ' IPEN RCON.7 INTERUPT PRIORITY LEVEL DISABLED
ADCON0 = %00010001 ' ATOD CH 4 CONVERTER ENABLED
ADCON1 = %00001010 ' VSS AND VDD REF LEVELS A0-A4 ANALOG A5-A12 DIG
'ADCON2 = %10000110 ' RIGHT JUST RESULT 0 TAD FOSC/64
'define I2C_SCLOUT 1 ' just messing around trying to see if I can get it to work. No change with this line included
'DEFINE I2C_HOLD 1 ' just messing around trying to see if I can get it to work. No change with this line included

DEFINE LCD_DREG PORTD ' PortD is the data port
DEFINE LCD_DBIT 0 ' PORTD.4
DEFINE LCD_RSREG PORTE ' PortE contains the Reset/Enable port
DEFINE LCD_RSBIT 0 ' PORTE.0 = reset bit
DEFINE LCD_EREG PORTE ' PortE contains the Reset/Enable port
DEFINE LCD_EBIT 1 ' PORTE.1 = ENABLE BIT

Low PORTE.2 ' LCD R/W line low (W)
Pause 500 ' Wait for LCD to start up
DEFINE ADC_BITS 10 ' Set number of bits in result
INSin var word
insin = 0
addr var byte
addr = 0
'i2cwrite portc.4, portc.3, %01000000, insin, noitwoc
LOOP:
i2cWRITE portc.4, portc.3, %01000001, $00, %01000001, insin, noitwoc
pause 10
LCDOUT $FE, 1
lcdout "IM ALIVE"
lcdout $fe, $c0
lcdout dec insin
'output porte.6
HIGH PORTJ.1
pause 250
low PORTJ.1
HIGH PORTJ.0
PAUSE 250
LOW PORTJ.0
HIGH PORTJ.2
PAUSE 250
LOW PORTJ.2
HIGH PORTJ.3
PAUSE 250
LOW PORTJ.3
HIGH PORTJ.4
PAUSE 250
LOW PORTJ.4
HIGH PORTJ.5
PAUSE 250
LOW PORTJ.5
HIGH PORTJ.6
PAUSE 250
LOW PORTJ.6
HIGH PORTJ.7
PAUSE 250
LOW PORTJ.7
HIGH PORTE.6
PAUSE 250
LOW PORTE.6
HIGH PORTE.7
PAUSE 250
LOW PORTE.7
HIGH PORTE.5
PAUSE 250
LOW PORTE.5
HIGH PORTE.4
PAUSE 250
LOW PORTE.4
HIGH PORTE.3
PAUSE 250
LOW PORTE.3
GOTO LOOP
noitwoc:
lcdout $fe, 1
lcdout "no i2c ack"
pause 2000
goto loop
END

Dave
- 25th October 2007, 13:12
GeoJoe, Where is your I2CREAD statement?

GeoJoe
- 25th October 2007, 15:45
My mistake. I've been changing the code and trying all kinds of different stuff. I had tried the write command just to see what happened and didn't change it back when I posted that reply. However I have the write command in there now. I don't think the clock is correct. It isn't idling high. I am still working on this so if anyone has any wisdom to share please do. This is a really sweet chip set, the pic has a bunch of i/o's, on board USB and huge instruction memory space of 128k; the i/o expanders add an extra 16 gpio's each. I have 3 on my board. This left the other pic pins open for things like wireless modem, a maxstream zigbee module, LCD, and left many of the ATOD's open.

Any advice on this???????????

GeoJoe
- 25th October 2007, 15:45
read command that is.

GeoJoe
- 28th October 2007, 02:17
Thanks Jeff.............
An email to melabs support got me the answer. Here it is:
I2Cread portc.4, portc.3, %01000000, command, [insin], noitwoc

Where command is what register you want to read 0 or 1. Now I get the value of the I/O expansion chip into the variable insin. Just missed the brackets around the variable name!

Now I'm trying to figure out the write command. Some difficulties, I'll post my results. Hope this helps someone. This is a nice chip set. The I/O's on pics go fast. Faster and faster the deeper I get into designing with them.

Joe

GeoJoe
- 31st October 2007, 16:39
i2cwrite portc.4, portc.3, %01000010, %00000111, [%00000000] ' SET U9 PORT 1 TO OUTPUTS
i2cwrite portc.4, portc.3, %01000010, %00000011, [acout] ' WRITE VARIABL ACout TO U9 PORT 1 LATCH REGISTER
insin = 0
i2cread portc.4, portc.3, %01000000,[insin]', noitwoc ' READ U8 PORT 0 AND 1 PIN STATES
i2cread portc.4, portc.3, %01000010, %00000000, [inson] ' READ U9 PORT 0 PIN STATES

Here are the write and read lines I've found to be successful with the MCP23016 I/O expander chip.

Use in good health.