Shop OBEX P1 Docs P2 Docs Learn Events
FemtoBasic I2C operation? — Parallax Forums

FemtoBasic I2C operation?

Duane C. JohnsonDuane C. Johnson Posts: 955
edited 2013-01-13 10:47 in Propeller 1
Hi Mike:

I have been experimenting with your I2C command with MCP23017 I2C Buss Expanders and don't under stand something.
This is my personal working copy of your "FemtoBasic Manual" as a text file.
This is my entry associated with the I2C statement:
X = I2C [ < expr  >,<       expr       >,<expr> ]
    I2C [ < expr  >,<       expr       >,<expr> ] = <expr>
          <SCL Pin> <Device Select Code> <expr>

X = I2C [ < expr  >,<       expr       >,<expr>,<   expr   > ]
    I2C [ < expr  >,<       expr       > <expr>,<   expr   > ] = <expr>
          <SCL Pin> <Device Select Code> <expr> <Which Byte>

This writes bytes 1 to 4 (in LSB..MSB order) to an I2C device.
The 1st <expr> is the pin number of the clock (SCL) signal.
The data signal is connected to the next numerically higher pin.  
For the boot EEPROM  I2C bus, this would be 28 (and 29).
The 2nd <expr> is the device select code.
The read/write bit is ignored and will be set appropriately for
the operation involved.
If four <expr> are provided, the 3rd <expr> is the 8-bit address.
The last <expr> in the brackets is the number of bytes to be written.
The data to be written is taken from the <expr> on the right of the
equal sign.
( I don't understand the 3 expression nor the 4 expression  versions
  with values other than 1. Probably only useful for memory
  operations or sequential register transfers. )
1. I don't seem to be able to get the 3 expression version to work.
2. I'm only able to use the 4 expression version to work if the last expression 1.

I guess I don't understand what is going on with the forth expression?

I assume the 1st byte sent is the Least Significant Byte, LSB, of the expression.
Is the next byte the Next Least Significant Byte of the expression and so forth?
But that doesn't seem to work.

Do you have a concise description of this statement?

Thanks
Duane J

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2013-01-11 13:12
    The first two parameters are straightforward. The first is the (even) number of the I/O pin used for SCL. SDA is always the next higher numbered I/O pin. For the boot EEPROM I2C bus, this would be 28. The 2nd parameter is the I2C device select code. This is always a 7-bit value shifted left one bit. For the first device on the I2C bus, this would be %xxxx0000 where xxxx is a device specific code. For the 2nd device, this would be %xxxx0010. The first MCP23017 would be %01000000.

    Some I2C devices (like the MCP23017) expect an 8-bit (single byte) register address while some I2C devices don't use an address byte (to select a register). If there's an address byte needed, that would be the 3rd parameter. All I2C[] calls require a byte count which is the last parameter (whether there are 3 or 4 parameters). This count is in the range of 1 to 4. Most devices only supply a single data byte, so this count would usually be 1. Some devices, like the MCP23017 will accept (or provide) up to 2 bytes of data. For this to work properly, you have to use Bank = 0 (the default) so that the various registers are paired up in successive register addresses (see the Microchip datasheet for details).

    For an MCP23017 on I/O pins 28/29 and a newly reset MCP23017, you'd set the direction registers with:

    I2C[28, %01000000, $00, 2] = %1111000000001111

    This would set IODIRA to %00001111 and IODIRB to %11110000.

    I2C[28, %01000000, $14, 2] = %0101000010100000

    This would set OLATA to %10100000 and OLATB to %01010000

    X = I2C[28, %01000000, $12, 2]

    This would read GPIOA and GPIOB to the variable X with GPIOA in the LSB and GPIOB in the next significant byte.
  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2013-01-12 08:54
    Hi Mike;

    Thanks for the clarification on the I2C operation. I finally got things working correctly with multiple byte transfers.

    I think my problem with getting things to work was caused by a technical detail in the MCP23017 operation of the IOCON register. Since I had been changing the Bank bit to a 1 with a different experiment I could now not reliably change it back to 0.
    I now don't have confusion because I understand the problem.
    See:
    Page 17
    It is important to take care when changing the BANK bit
    as the address mapping changes after the byte is
    clocked into the device. The address pointer may point
    to an invalid location after the bit is modified.
    For example, if the device is configured to
    automatically increment its internal Address Pointer,
    the following scenario would occur:
    • BANK = 0
    • Write 80h to address 0Ah (IOCON) to set the
    BANK bit
    • Once the write completes, the internal address
    now points to 0Bh which is an invalid address
    when the BANK bit is set.
    For this reason, it is advised to only perform byte writes
    to this register when changing the BANK bit.
    After Power On Reset, POR/RST, IOCON contains %0000_0000 which is initially in the "Sequential" addressing mode. No writing to IOCON is required during initialization. Fair enough.

    However, what if the IOCON Bank bit somehow got changed to a 1. Maybe due to a noise pulse, (or ineptitude as in my case). How can one recognize this condition and regain control of the MCP23017? Since the addressing for the registers is different between sequential and non-sequential modes this doesn't seem to work.

    One method would be to incorporate the reset pin but this would require an extra line to the expander array. Not so good.

    Is there a prescribed method to test the IOCON state and take appropriate action?

    Duane J
  • Mike GreenMike Green Posts: 23,101
    edited 2013-01-12 12:26
    If you always do single byte transfers, the state of the IOCON Bank bit doesn't matter for that. Remember that the register addresses for most of the registers changes depending on the Bank bit setting. I think the only way you can control this would be to ensure that the MCP23017 is reset before you try to access it. It's not a very good design, but that doesn't help you.
  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2013-01-13 05:53
    Ya, I suspect I'm making a mountain out of a mole hill.
    It seems it would be hard to flip the bank bit due to noise.
    So, if I never write to IOCON after powering up there is no problem as this will always be using bank=0.

    I got the multiple byte transfers working nicely. Even 4 byte transfers for some registers with sequential addresses such as IPOL & IODIR. Very cool.

    Ok, I switch back to unsolved, though, because the 3 expression version doesn't work.
    Is this a transfer with a default of 1 byte?
    Or something else not appropriate to the MC23017 or PCA9555/PCA9554. Maybe a triggering command with no bytes transfered?
    10  D=%01000000 ' "FFFF_CCC_x" Fixed Device Select Code + Hardware Select Code + space for the R/W bit
    20  A = 2 ' Device Address
    30  V = $0F ' Byte to be sent
    40 I2C [28,D+2*2,$12] =  V
    RUN
    IN LINE 40 Syntax Error
    ' Bad
    
    10  D=%01000000 ' "FFFF_CCC_x" Fixed Device Select Code + Hardware Select Code + space for the R/W bit
    20  A = 2 ' Device Address
    30  V = $0F ' Byte to be sent
    40 I2C [28,D+2*2,$12,1] =  V
    RUN
    ' Good
    

    Duane J
  • Mike GreenMike Green Posts: 23,101
    edited 2013-01-13 09:47
    The PCA9554 calls the address byte a "command byte". The PCA8574A I/O Expander is one example of a device that doesn't use an address byte and would work with the 3 parameter version of I2C.

    The Syntax Error is due to your using a byte count other than 1 through 4. You can use an expression there, but the value still has to be in the range of 1 through 4.
  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2013-01-13 10:47
    Mike Green wrote: »
    The PCA9554 calls the address byte a "command byte". The PCA8574A I/O Expander is one example of a device that doesn't use an address byte and would work with the 3 parameter version of I2C.

    The Syntax Error is due to your using a byte count other than 1 through 4. You can use an expression there, but the value still has to be in the range of 1 through 4.
    I don't understand?
    The third, $12, and last parameter is the register address. Of course its greater than 4.
    What else would it be if I was sending a single byte, $0F, to register $12 in the MCP23017.

    Isn't the phantom 4th parameter simply a byte count of 1?

    Duane J
Sign In or Register to comment.