arduino / arduino/ArduinoCore-API
shiftIn and shiftOut do not work with SPI_MODE 3 and 4
- Lingua principale
- C++
- Stelle
- 306
- Fork
- 150
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
The solution described here might well fix several other problems in this thread where bits go missing or additional bits appear...
I was trying to use the standard Arduino shiftIn and shiftOut to operate a 74HC165 shift register. I found that it always clocked one too many bits, and therefore shifted all the bits to the left, losing the top one. This did not happen when I used hardware SPI (the SPI library).
I therefore took a close look at the source code for shiftIn and shiftOut in (wiring_shift.c) and soon spotted the problem: shiftIn and shiftOut assume a clock polarity of 0. _**They will therefore only work with SPI_MODE0 and 1.**_
This can be fixed by inverting the clock signal if the SPI_MODE is 3 or 4. I give my solution below. The functions require the SPI mode as an additional parameter, using the Arduino standard definitions SPI_MODE0 etc.
While I was at it, I gained a little speed by taking the test for MSBFIRST or LSBFIRST outside the bit loop and by declaring the method ‘inline’.
I have tested NEWshiftIn with the 74HC165 shift register (SPI_MODE3) and it works fine. I have not tested NEWshiftOut yet as I do not have a MOD3 or 4 device output to test it with. I have also not tested the timings to see if there is a real improvement, as I do not have access to the necessary equipment at the moment. I will be happy to hear from anyone who does any of these tests.
Happy shifting in SPI_MODES 3 and 4!
```cpp
// ===============================================================================================================================
// New version of shiftIn() and shiftOut with the clock polarity bug removed
// Requires SPI_MODE as a parameter
// Also speeded up by taking the bit direction test out of the loop
// Andrew W Symons 9-Aug-2018
//
// SHIFT IN
//
inline uint8_t NEWshiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t spiMode )
{
uint8_t value = 0;
uint8_t i;
uint8_t clock_polarity = spiMode >> 1 ;
switch ( bitOrder )
{
case LSBFIRST:
{
for (i = 0; i < 8; ++i)
{
digitalWrite(clockPin, HIGH ^ clock_polarity );
value |= digitalRead(dataPin) << i;
digitalWrite(clockPin, LOW ^ clock_polarity );
} ;
} ;
break ;
case MSBFIRST:
{
for (i = 0; i < 8; ++i)
{
digitalWrite(clockPin, HIGH ^ clock_polarity );
value |= digitalRead(dataPin) << (7 - i);
digitalWrite(clockPin, LOW ^ clock_polarity );
} ;
} ;
break ;
} ;
return value;
} ;
//
// ===============================================================================================================================
// SHIFT OUT
//
inline void NEWshiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val, uint8_t spiMode )
{
uint8_t i;
uint8_t clock_polarity = spiMode >> 1 ;
switch ( bitOrder )
{
case LSBFIRST:
{
digitalWrite(dataPin, !!(val & (1 << i)));
digitalWrite(clockPin, HIGH ^ clock_polarity );
digitalWrite(clockPin, LOW ^ clock_polarity );
} ;
break ;
case MSBFIRST:
{
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
digitalWrite(clockPin, HIGH ^ clock_polarity );
digitalWrite(clockPin, LOW ^ clock_polarity );
} ;
break ;
} ;
} ;
//
// ===============================================================================================================================
// END OF FILE
//
```
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Direzione di ricerca
Inizia in wiring_shift.c e confronta shiftIn() e shiftOut() con la gestione delle modalità SPI da parte della SPI library. Riproduci il comportamento segnalato di 74HC165 nelle modalità di clock interessate, quindi verifica che il comportamento standard di shift rimanga corretto per le modalità e gli ordini dei bit esistenti. Il lavoro è completato quando le funzioni software gestiscono le modalità segnalate senza perdere né aggiungere bit.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- cpp
- Ambito
- embedded-iot
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 42/100