Question on SPI Transactions

Status
Not open for further replies.

tonton81

Well-known member
I am writing a library for the MCP23S17 8x port expanders being tested on a UK board made for the rasbpi but I have it wired to the Teensy4.

When I do multiple SPI calls, after I deassert the line, I have endTransaction inbetween each call. I figure, if it's within the same function toggling the GPIO, I'd remove the additional beginTransaction and endTransaction in between. However when I do this the GPIOs don't seem to change state (on expanders) because the register didn't update (debug output shows nothing changed on port). Leaving beginTransaction and endTransaction between calls to the same chip works fine. Is it because the GPIO is toggling too fast that when I introduce additional beginTransaction and endTransaction in between it allows the chip to see the assertion signal?

Example:

Code:
    [COLOR="#008000"]bus->beginTransaction(SPISettings(speed,MSBFIRST,SPI_MODE0));[/COLOR] /* read port register */
    ::digitalWriteFast(chipSelect, LOW);
    bus->transfer16(((0x41 | (i << 1)) << 8) | 0x12);
    uint16_t data = bus->transfer16(0xFFFF);
    ::digitalWriteFast(chipSelect, HIGH);
    [COLOR="#FF0000"]bus->endTransaction();[/COLOR]

    data = (data & ~(1UL << pin)) | (level << pin); /* set new pin state */

    [COLOR="#FF0000"]bus->beginTransaction(SPISettings(speed,MSBFIRST,SPI_MODE0));[/COLOR] /* write port register */
    ::digitalWriteFast(chipSelect, LOW);
    bus->transfer16(((0x40 | (i << 1)) << 8) | 0x12);
    bus->transfer16(data);
    ::digitalWriteFast(chipSelect, HIGH);
    [COLOR="#008000"]bus->endTransaction();[/COLOR]
 
Last edited:
it's sequential registers, each read or write needs a new assertion. I will try delay again later, working on the event interrupts..


EDIT, commented out the red transaction lines and put a delay(50) in between. It correctly sees the toggle perhaps because the chip is updating fine now.... I think the gpio is just too fast? :p Kinda painful to put a delay, I'll just leave the transactions in place for now :eek:
 
Last edited:
If that is the assertion of CS then that makes sense. Glancing at the SPI_END/BEGIN I wasn't sure of the #ifdef path in use or the effect of that fiddling in the BEGIN case. Not sure what Teensy is in use - if it matters - as that doesn't seem to tie the CS on the Master side with the transaction code to take it offline? It could just be the CS toggle is too fast for slave and a delayMicroseconds() might fix the timing. @tonton81 - after your SPITransfer code you certainly have better idea of what each side is looking for - and timing on the slave side.
 
True, I just hate the idea of adding delays to fine tune things just to make things slightly slower :p

Now I know why people have interrupt issues with these chips. During debugging (8 chip register printouts in serial monitor), I noticed the behaviour of the chips. I implemented RISING, FALLING, and CHANGE for interrupt checking.
On RISING and FALLING, the INTF are set for AS LONG AS the pin is in that state, which means the INT pin is always set and never reset until it's shifts back to opposite value and reread.
For CHANGING, the INTF is never set, although I didn't check to see if the actual physical interrupt pin is getting toggled, the INTCAP register just changes with the new value of the port (INTCAP changes for all FALLING/RISING/CHANGE) but the INTF interrupt flag for CHANGE is never set in register, while RISING/FALLING are ALWAYS set until the value shifts back to previous. Might have to just keep a copy of INTCAP registers to an array to compare and just ignore the silly interrupt flag :p
 
Status
Not open for further replies.
Back
Top