I accidentally asked this question on the Sensors forum, and got no response in 24 hours. Then I realized this is where SPI questions belong, which may explain the lack of replies before. This time, I'm going to ask it in more general terms.
A long while back, I tried to place two SPI devices on the same Nano, which didn't work. After googling, I found that one of them (CC3000) didn't play well with others.
So being a sucker, I tried again, combining an SPI transceiver (RFM22B) and an SPI RFID tag reader (RFC522). Of course, if all is well, these are hooked up in parallel except for their chip select lines. But I find that if I init the radio in Setup(), but don't initialize the RFC522, the radio initializes properly, and works. But, if I initalize the radio and then after that, I initialize the RFC522, the radio does not initialize properly, even though the radio init instructions precede the RFC5cc init.
So, can anyone explain why code that come later can affect the outcome of code that comes earlier, and has anyone actually gotten two SPI devices working on the same bus?
Thanks in advance for your interest.
Hi,
First I never used those two devices... but yes, I've successfully used multiple devices on the same SPI Bus by having a CS dedicated to each with no problem at all. As you mentioned, some devices might not play nice but even if the slave does respect the CS you still need to follow some basic rules to minimise issues:
-
Have a Pull-up on each CS line. Basically a 10K or 100K resistor from each CS to the VCC. This will make sure all devices are not selected, independent of the initial PIN state.
-
In your libraries, it's important to ALWAYS configure the SPI device before using the it. Also make sure you do restore all SPI configuration later. Some badly written libraries might define the Speed, Order, Mode only once during the initialisation (and that's fine if you have only one device on the SPI bus). The problem appears if later another library comes and change the SPI config again, putting the SPI in an unknown state for the first Lib. For example, on your "select()" and "unselect()" routines you could use something like:
uint8_t _SPCR;
uint8_t _SPSR;
select(uint8_t cs_pin) {
noInterrupts();
_SPCR = SPCR;
_SPSR = SPSR;
digitalWrite(cs_pin, LOW);
}
unselect(uint8_t cs_pin) {
digitalWrite(cs_pin, HIGH);
interrupts();
SPCR = _SPCR;
SPSR = _SPSR;
}
- Try to use the "new" SPI beginTransaction() and endTransaction() or make sure you disable interrupts before talking over SPI and re-enable it later (Atomic transactions). Note that even using the beginTransaction(), you still need to run SPI.begin() at the beginning of your code to set the MISO, MOSI and SCK appropriately.
Some good reference here: Better SPI Bus Design in 3 Steps
musskopf,
Thank you very much for the information and the link. I already have a pcb wired for this project, and I certainly didn't want to abandon it. I'll be seriously climbing this learning curve, because SPI is just about everywhere.
I am happy to report that issue is resolved. The pullups on the two chip select lines at least allowed both components to initialize, but when the radio was being polled for incoming traffic, the RFID reader wouldn't read. Down in the fine print of the RFM22B library, it stated that if the radio was used with other SPI devices, interrupts should be disabled during the read/writes to the other device. That cleaned up the problem.