Actually, I'm tempted to unpack this a little more. I've found that if I use SPI.end and SPI.begin to bracket my uses of the hardware SPI pin(s) as GPIO I
can get it to work with the original pinout but it doesn't seem to need the end and begin around every use and it's really confusing me. This is all to drive
HCMS style LED displays.
My original pin setup:
Code:
//My LED Display
byte dataPin = 2; // connects to the display's data in, use hadware SPI
byte clockPin = 1; // the display's clock pin, use hardware SPI
byte chipEnable = 3; // the display's chip enable pin
byte registerSelect = 4; // the display's register select pin
byte resetPin = 0; // the display's reset pin
On the Teensy 2.0 SS is actually 0 and pin 3 is MISO. I didn't need MISO so I assigned it as a GPIO for chip enable. All are set up as outputs.
If I swap chipEnable to 0 and resetPin to 3 and make a corresponding wiring change the displays work. That was the pinout change in the cable I described above. But it occurs to me today that in this situation I'm still using the same Hardware SPI pins as GPIO, just using them differently so why would it work? Leaving them with the original assignment the screens never update. I couldn't get my head around why that would be.
So I started messing around. First thing to say is that never toggling the reset pin doesn't seem to matter. I commented out every use and see no behavior changes. So that's half of why one pinout works and one doesn't. Combining this fact with my pin swap observation above, I conclude pin zero can be used arbitrarily but 3 can't. Having reset on 3 never mattered, having CE on 3 is not workable, having CE on 0 works fine.
For chip enable on pin 3 to work I need to end SPI before changing the pin... sometimes. You can see here that I toggle CE low before the transfer and toggle high after. On the preceding pull low, without the SPI.end, the screens don't receive. And obviously without the SPI.begin the transfer won't happen at all. But after the transfer when I toggle the CE pin high it doesn't require the end/begin to work here. I figured maybe hardware SPI just defaults this pin to high after transfer and I'm getting the high state I need for free but removing that toggle line altogether causes malfunction (glitchy incomplete characters on screen). I put some delays in to give my meter a shot at seeing the changes and CE does in fact change states. It does need to be told to go high here but I don't understand why I can tell it.
Code:
void writeDotRegisterToDisplay()
{
//load dot register with character data
int maxData = displayLength * 5;
// select the dot register:
digitalWrite(registerSelect, LOW);
// enable writing to the display:
SPI.end(); // Needed to toggle the CE pin
digitalWrite(chipEnable, LOW);
SPI.begin(); //Needed or SPI won't run and the program halts here
// shift the data out:
for (int i = 0; i < maxData; i++) {
SPI.transfer(dotRegister[i]);
}
// disable writing:
digitalWrite(chipEnable, HIGH); // I don't seem to need to end SPI before this pin use but I do need the line
}
So, in adding this all up I'm immensely curious as to why the hardware behaves this way. Both for general academic curiosity but also so I know how to budget these pins in the future. It seems I can use SS (pin 0) as a toggled pin for peripherals but I can't use MISO for anything without suspending SPI to get access
sometimes. If anyone has theory on why it will let me command it high after a transfer without suspending SPI I'd love to hear it.