diff --git a/README.md b/README.md index c5e116a..a2697f3 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,11 @@ sr.set(1, HIGH) Please find the detailed **documentation** at https://timodenk.com/blog/shift-register-arduino-library/. An **example** sketch can be found in this repository at [/examples/example/example.ino](https://github.com/Simsso/ShiftRegister74HC595/blob/master/examples/example/example.ino). + + + +New: + +to shift data via SPI define `SHIFT_REGISTER_USES_SPI_WITH_FREQUENCY 20000000UL` before you include ShiftRegister74HC595.h + +Arduino UNO uses pin 13 for CLOCK and pin 11 for MOSI (data) - latch pin - configurable. \ No newline at end of file diff --git a/examples/spi_example/example.ino b/examples/spi_example/example.ino new file mode 100644 index 0000000..9c9f668 --- /dev/null +++ b/examples/spi_example/example.ino @@ -0,0 +1,54 @@ +/* + ShiftRegister74HC595 - Library for simplified control of 74HC595 shift registers. + Developed and maintained by Timo Denk and contributers, since Nov 2014. + Additional information is available at https://timodenk.com/blog/shift-register-arduino-library/ + Released into the public domain. +*/ + +// 20000000UL <- your chip speed. if arduino cant handle that, it will work at max it can. On uno up to 8mhz. 20000000UL means 20Mhz +// MOSI to shift register DATA pin, SCLK to CLock pin, Latch pin configurable +#define SHIFT_REGISTER_USES_SPI_WITH_FREQUENCY 20000000UL +#include + +// create a global shift register object +// parameters: (latch pin) +ShiftRegister74HC595<1> sr(7); + +void setup() { +} + +void loop() { + + // setting all pins at the same time to either HIGH or LOW + sr.setAllHigh(); // set all pins HIGH + delay(500); + + sr.setAllLow(); // set all pins LOW + delay(500); + + + // setting single pins + for (int i = 0; i < 8; i++) { + + sr.set(i, HIGH); // set single pin HIGH + delay(250); + } + + + // set all pins at once + uint8_t pinValues[] = { B10101010 }; + sr.setAll(pinValues); + delay(1000); + + + // read pin (zero based, i.e. 6th pin) + uint8_t stateOfPin5 = sr.get(5); + sr.set(6, stateOfPin5); + + + // set pins without immediate update + sr.setNoUpdate(0, HIGH); + sr.setNoUpdate(1, LOW); + // at this point of time, pin 0 and 1 did not change yet + sr.updateRegisters(); // update the pins to the set values +} diff --git a/library.properties b/library.properties index 0b311d5..d31452c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ShiftRegister74HC595 -version=1.3.1 +version=1.3.2 author=Timo Denk (timodenk.com) maintainer=Timo Denk (timodenk.com) sentence=Simplifies usage of shift registers, designed for the 74HC595. diff --git a/src/ShiftRegister74HC595.cpp b/src/ShiftRegister74HC595.cpp index a3a27c1..cd5d864 100755 --- a/src/ShiftRegister74HC595.cpp +++ b/src/ShiftRegister74HC595.cpp @@ -7,3 +7,4 @@ #include #include "ShiftRegister74HC595.h" + diff --git a/src/ShiftRegister74HC595.h b/src/ShiftRegister74HC595.h index ac78fdf..93ad7d0 100755 --- a/src/ShiftRegister74HC595.h +++ b/src/ShiftRegister74HC595.h @@ -9,11 +9,19 @@ #include +#if defined(SHIFT_REGISTER_USES_SPI_WITH_FREQUENCY) +#include +#endif + template class ShiftRegister74HC595 { public: +#if !defined(SHIFT_REGISTER_USES_SPI_WITH_FREQUENCY) ShiftRegister74HC595(const uint8_t serialDataPin, const uint8_t clockPin, const uint8_t latchPin); +#else + ShiftRegister74HC595(const uint8_t latchPin); +#endif void setAll(const uint8_t * digitalValues); #ifdef __AVR__ @@ -26,13 +34,22 @@ class ShiftRegister74HC595 void setAllLow(); void setAllHigh(); uint8_t get(const uint8_t pin); + void order(uint8_t o); private: + #ifdef __AVR__ + uint8_t bo = MSBFIRST; + #else + BitOrder bo = MSBFIRST; + #endif uint8_t _clockPin; uint8_t _serialDataPin; uint8_t _latchPin; uint8_t _digitalValues[Size]; + + uint8_t *_port; + uint8_t _pinMask; }; #include "ShiftRegister74HC595.hpp" diff --git a/src/ShiftRegister74HC595.hpp b/src/ShiftRegister74HC595.hpp index cb88886..eaad840 100644 --- a/src/ShiftRegister74HC595.hpp +++ b/src/ShiftRegister74HC595.hpp @@ -5,6 +5,9 @@ Released into the public domain. */ + +#if !defined(SHIFT_REGISTER_USES_SPI_WITH_FREQUENCY) + // ShiftRegister74HC595 constructor // Size is the number of shiftregisters stacked in serial template @@ -15,6 +18,8 @@ ShiftRegister74HC595::ShiftRegister74HC595(const uint8_t serialDataPin, co _serialDataPin = serialDataPin; _latchPin = latchPin; + bo = MSBFIRST; + // define pins as outputs pinMode(clockPin, OUTPUT); pinMode(serialDataPin, OUTPUT); @@ -31,6 +36,40 @@ ShiftRegister74HC595::ShiftRegister74HC595(const uint8_t serialDataPin, co updateRegisters(); // reset shift register } +#else + +// ShiftRegister74HC595 constructor +// Size is the number of shiftregisters stacked in serial +template +ShiftRegister74HC595::ShiftRegister74HC595(const uint8_t latchPin) +{ + _latchPin = latchPin; + +#ifdef __AVR__ + _pinMask = digitalPinToBitMask(latchPin); + _port = portOutputRegister(digitalPinToPort(latchPin)); +#endif + + bo = MSBFIRST; + + // define pins as outputs + pinMode(latchPin, OUTPUT); + + // set pins low + digitalWrite(latchPin, LOW); + + // allocates the specified number of bytes and initializes them to zero + memset(_digitalValues, 0, Size * sizeof(uint8_t)); + + SPI.begin(); + SPI.beginTransaction(SPISettings(SHIFT_REGISTER_USES_SPI_WITH_FREQUENCY, bo, SPI_MODE0)); + + updateRegisters(); // reset shift register +} + + +#endif + // Set all pins of the shift registers at once. // digitalVAlues is a uint8_t array where the length is equal to the number of shift registers. template @@ -71,19 +110,38 @@ void ShiftRegister74HC595::set(const uint8_t pin, const uint8_t value) updateRegisters(); } + +#if !defined(SHIFT_REGISTER_USES_SPI_WITH_FREQUENCY) // Updates the shift register pins to the stored output values. // This is the function that actually writes data into the shift registers of the 74HC595. template void ShiftRegister74HC595::updateRegisters() { for (int i = Size - 1; i >= 0; i--) { - shiftOut(_serialDataPin, _clockPin, MSBFIRST, _digitalValues[i]); + shiftOut(_serialDataPin, _clockPin, bo, _digitalValues[i]); } digitalWrite(_latchPin, HIGH); digitalWrite(_latchPin, LOW); } - +#else +// Updates the shift register pins to the stored output values. +// This is the function that actually writes data into the shift registers of the 74HC595. +template +void ShiftRegister74HC595::updateRegisters() +{ + for (int i = Size - 1; i >= 0; i--) { + SPI.transfer(_digitalValues[i]); + } + #ifdef __AVR__ + *_port |= _pinMask; + *_port &= ~_pinMask; + #else + digitalWrite(_latchPin, HIGH); + digitalWrite(_latchPin, LOW); + #endif +} +#endif // Equivalent to set(int pin, uint8_t value), except the physical shift register is not updated. // Should be used in combination with updateRegisters(). template @@ -119,3 +177,9 @@ void ShiftRegister74HC595::setAllLow() } updateRegisters(); } + +template +void ShiftRegister74HC595::order(uint8_t o) +{ + bo = o; +}