Multiple LCD CS Lines & Port Expanders (MCP23S17) Question

Thundercat

Well-known member
Hi all, I've got a MIDI fader/pot box I'm building that will have a bunch of buttons, faders, pots, as well as 9 LCDs. 8 will be small "scribble strips" and one larger LCD to tie it all together. MCU is Teensy 4.1

With such a large project I'm using two SPI port expanders (MCP23S17) to save on precious MCU pins. The MCP23S17s will handle a bunch of buttons, and LCDs. I'm also using different hardware addresses for each MCP23S17, but I'm not sure this matters with SPI. Seems a bit complex to implement but maybe it's easy.

Here's the relevant proposed schematic detail:

Port Expander & CS lines.jpg

I'm just wondering if I'm implementing this correctly - the two port MCP23S17s will each have their own dedicated Teensy pin for CS lines (CS_DPE1/2). Then the 9 different LCD screens will have each their own pin from the second MCP23S17 (CS0-7, CS_MAIN_LCD).

Will this cause conflicts on the SPI bus? My understanding is the CS lines are what determine which device is communicated with, so I should be able pull a CS line low, send a command, and pull it high again, per device (right?). Also is it a bad idea to use the port expanders which use CS lines to control other CS lines? Are the pull-ups necessary? Found some info on the net that says yes they are needed.

This unit maxes out at 10MHz, and is this an issue with LCDs?

Finally, if anyone has experience with the MCP23S17, how should I wire/configure the interrupts? Are they necessary?

I've been over the data sheets, but understanding the technical details is a bit overwhelming to me at the moment.

Thank you for any insights and suggestions. I am so deeply grateful to all of you for your brilliance, but beyond that, for your compassion. This is one of the best technical boards on the internet because everyone is so kind to each other.

Thank you again,

Mike
 
I have some experience with 23S17. If you have a separate CS to each 23S17, then you don't need to use the address lines. Those allow you to share a CS between multiple 23S17 and address them from within the SPI data. That's a hardware option in the 23S17 that is disabled by default. I don't see why you can't use one 23S17 to generate chip selects. Rob Tillart's 23S17 library is good.
 
I have some experience with 23S17. If you have a separate CS to each 23S17, then you don't need to use the address lines. Those allow you to share a CS between multiple 23S17 and address them from within the SPI data. That's a hardware option in the 23S17 that is disabled by default. I don't see why you can't use one 23S17 to generate chip selects. Rob Tillart's 23S17 library is good.
Hi Joe, that's super helpful - thank you! Yes it seems to me like using the hardware addresses just adds more complexity, when I could just use two CS pins instead of one on the Teensy. I'm sure I have an extra pin I can use for this, and it might even make it faster and easier to use in the library, less conflicts...Thanks also for the lib recommendation too. I was planning on using that one anyway, but thanks for the confirmation that it's a decent one.

Thank you for your expertise!

Mike
 
That library supports the hardware address feature, so if you find you do need it, it should be easy to use. BTW, I haven't used interrupts on the 23S17. For your purposes, they don't seem necessary. You are using all pins as outputs. Seems like they would be mostly for notifying the CPU that a pin configured as input had changed state.
 
Thanks again Joe. For the CS lines, then yes, all outputs, driving the pins high/low. For the first 23S17, they have a bunch of buttons, so they would be input pins.

Would it be necessary to add external pull-up resistors to those button lines, or can I do that in software as I normally do with buttons attached directly to the Teensy using INPUT_PULLUP command when defining them?

I've used interrupts for buttons in past, but then discovered that I didn't need them since the Teensy 4.1 is so fast I can just poll the pins. Do you think polling here is a good idea or since there's so many pins perhaps this becomes a bad idea?

Thanks!
 
The MCP23S17 supports activating internal pull-ups when a pin is configured for input.
Thank you Marsh. I saw that in the data sheet but I'm always a little leery of internal pull-ups. In any case, many thanks.

In your experience is simple polling of two devices like this going to slow down the sketch, or are interrupts a good idea?

Thanks again,

Mike
 
If handling user input is part of the Teensy's "main job" then I wouldn't bother with interrupts, i.e. only if it was spending most of its time on some other task that would prevent it responding in a reasonable way.
 
If handling user input is part of the Teensy's "main job" then I wouldn't bother with interrupts, i.e. only if it was spending most of its time on some other task that would prevent it responding in a reasonable way.
Totally reasonable. Thank you 🙏
 
I'm also using different hardware addresses for each MCP23S17, but I'm not sure this matters with SPI. Seems a bit complex to implement but maybe it's easy.
You can use different chip-selects, or share the chip-select and different hardware addresses. Not sure why you are using both techniques. The hardware addressing is inherited from the MCP23017 (the I2C version of the chip), meaning you can address 128 GPIO lines from a single 4-wire SPI bus using 8 MCP23S17's

Note the MCP23x17 chips don't source or sink that much current, should be fine for what you want, but don't expect it to drive 20mA into an LED directly...
 
You can use different chip-selects, or share the chip-select and different hardware addresses. Not sure why you are using both techniques. The hardware addressing is inherited from the MCP23017 (the I2C version of the chip), meaning you can address 128 GPIO lines from a single 4-wire SPI bus using 8 MCP23S17's

Note the MCP23x17 chips don't source or sink that much current, should be fine for what you want, but don't expect it to drive 20mA into an LED directly...
I’m prototyping. Not sure which way is better. Can’t use both at once as you pointed out.

I’m leaning towards just using different CS lines and not using the hardware addressing.

I’m not driving LEDs - just some buttons and LCDs.

Many thanks for your support Mark!
 
A couple issues have come up with other projects involving several displays connected to SPI. These may or may not be a problem for you.

Some displays don't properly turn off their MISO pin output driver when their CS pin is high. You can test your display by connecting two 10K resistors to MISO, one to GND and the other to 3.3V. When nothing is driving the MISO pin, the resistors should cause about 1.6 volts. Just use the display for a while and while CS is high, measure the MISO voltage to check it really is 1.6V. If the displays you're using drive MISO to 0 or 3.3V when CS is high, your 2 options are to not connect MISO at all to those displays (if the display can even work that way - many but not all can), or to connect a tri-state buffer chip to each display. Hopefully the displays you have don't have this problem. But if they do, finding out sooner rather than later can save a lot of frustration!

The other issue is signal quality when you have "long" wires for MOSI, SCLK, MISO which connect to so many places. There are 2 ways to deal with this problem. The simplest which oftens works pretty well is just adding 100 resistors between Teensy and the MOSI and SCLK signals (the ones Teensy drives), and maybe also a 100 ohm resistor between each MISO output and the long wire. The other way involves adding buffer chips, so you bread the long wire into smaller parts, each driven by its own buffer.
 
A couple issues have come up with other projects involving several displays connected to SPI. These may or may not be a problem for you.

Some displays don't properly turn off their MISO pin output driver when their CS pin is high. You can test your display by connecting two 10K resistors to MISO, one to GND and the other to 3.3V. When nothing is driving the MISO pin, the resistors should cause about 1.6 volts. Just use the display for a while and while CS is high, measure the MISO voltage to check it really is 1.6V. If the displays you're using drive MISO to 0 or 3.3V when CS is high, your 2 options are to not connect MISO at all to those displays (if the display can even work that way - many but not all can), or to connect a tri-state buffer chip to each display. Hopefully the displays you have don't have this problem. But if they do, finding out sooner rather than later can save a lot of frustration!

The other issue is signal quality when you have "long" wires for MOSI, SCLK, MISO which connect to so many places. There are 2 ways to deal with this problem. The simplest which oftens works pretty well is just adding 100 resistors between Teensy and the MOSI and SCLK signals (the ones Teensy drives), and maybe also a 100 ohm resistor between each MISO output and the long wire. The other way involves adding buffer chips, so you bread the long wire into smaller parts, each driven by its own buffer.
Hi Paul, that is SO helpful! Thank you so much!

When you mention adding the 100R resistors, I'm assuming you mean in-line (serial) with the data lines?

I will take your suggestions on board and test things out.

Sometimes I wonder if you ever sleep ;)

EDIT: I just checked - 8 of the 9 displays do not use the MISO line at all; only the 9th main display does. So that should mitigate this first issue? Or should I still test the main LCD in this case?

Thank you!
 
A couple issues have come up with other projects involving several displays connected to SPI. These may or may not be a problem for you.

Some displays don't properly turn off their MISO pin output driver when their CS pin is high. You can test your display by connecting two 10K resistors to MISO, one to GND and the other to 3.3V. When nothing is driving the MISO pin, the resistors should cause about 1.6 volts. Just use the display for a while and while CS is high, measure the MISO voltage to check it really is 1.6V. If the displays you're using drive MISO to 0 or 3.3V when CS is high, your 2 options are to not connect MISO at all to those displays (if the display can even work that way - many but not all can), or to connect a tri-state buffer chip to each display. Hopefully the displays you have don't have this problem. But if they do, finding out sooner rather than later can save a lot of frustration!

The other issue is signal quality when you have "long" wires for MOSI, SCLK, MISO which connect to so many places. There are 2 ways to deal with this problem. The simplest which oftens works pretty well is just adding 100 resistors between Teensy and the MOSI and SCLK signals (the ones Teensy drives), and maybe also a 100 ohm resistor between each MISO output and the long wire. The other way involves adding buffer chips, so you bread the long wire into smaller parts, each driven by its own buffer.
Hi again Paul, I've added the resistors - can you just let me know if I put them in the right place and understood you correctly?

There's also a MISO line on the main LCD so I included that in the schematic snippet below.

Kind thanks!

Mike

100R Resistors 3.jpg


EDIT: mixed up MOSI/MISO. Schematic above corrected.
 

Attachments

  • 100R Resistors.jpg
    100R Resistors.jpg
    111.1 KB · Views: 36
Last edited:
Don't forget a 100 ohm resistor on SCK. Of all the signals where you would want that resistor, SCK is probably the most important.
Thank you!

I added it at the Teensy pin instead of the source - see below. Will this work? Or should it be at the other end?

SCK and MOSI.jpg


Also, correction from previous post - I got MOSI/MISO lines mixed up.

100R Resistors 3.jpg
 
Back
Top