Skip to content

Commit 1a01926

Browse files
author
Craig Ringer
committed
Extend arduino tutorial CIRC05 to support hardware SPI
1 parent 2f49af5 commit 1a01926

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* An extended version of Arduino example CIRC05
3+
* to use hardware SPI support in the Arduino:
4+
*
5+
* http://blog.ringerc.id.au/2012/01/extending-arduino-example-circ-05-to.html
6+
*
7+
*/
8+
9+
#include <SPI.h>
10+
11+
/* ---------------------------------------------------------
12+
* | Arduino Experimentation Kit Example Code |
13+
* | (Altered to use hardware SPI by Craig Ringer) |
14+
* | CIRC-05 .: 8 More LEDs :. (74HC595 Shift Register) |
15+
* ---------------------------------------------------------
16+
*
17+
* We have already controlled 8 LEDs however this does it in a slightly
18+
* different manner. Rather than using 8 pins we will use just three
19+
* and an additional chip.
20+
*
21+
* This version of the example has been altered to show hardware SPI
22+
* use as well. It requires you to use output 11 where the wiring diagram
23+
* says to use output 2, and use output 13 instead of 3. No changes to the
24+
* wiring on the breadboard are required, just plug the wires into the
25+
* different digital outputs on the Arduino as specified above.
26+
*
27+
*/
28+
29+
boolean useSPI = true;
30+
31+
// Control pin Definitions
32+
//
33+
// The 74HC595 uses a serial communication link (SPI) which uses three pins: data, clock and latch.
34+
//
35+
// For compatibility with the Arduino's hardware SPI pins 11 and 13 are used for data and clock,
36+
// though you can use any pins you like if you're using the software-only signalling shown
37+
// in updateLEDs().
38+
//
39+
int data = 11; // SPI MOSI ; use this instead of pin 2
40+
int clock = 13; // SPI SCLK ; use this instead of pin 3
41+
int latch = 4; // SPI SS
42+
43+
int delayTime = 100; //the number of milliseconds to delay between LED updates
44+
45+
/*
46+
* setup() - this function runs once when you turn your Arduino on
47+
* We set the three control pins to outputs
48+
*/
49+
void setup()
50+
{
51+
pinMode(latch, OUTPUT);
52+
digitalWrite(latch, LOW);
53+
if (useSPI) {
54+
// Transmit most significant bit first when sending data with SPI
55+
SPI.setBitOrder(MSBFIRST);
56+
SPI.begin();
57+
} else {
58+
pinMode(data, OUTPUT);
59+
pinMode(clock, OUTPUT);
60+
}
61+
}
62+
63+
/*
64+
* loop() - this function will start after setup finishes and then repeat
65+
* we set which LEDs we want on then call a routine which sends the states to the 74HC595
66+
*/
67+
void loop() // run over and over again
68+
{
69+
for(byte i = 0; i < 256; i++){
70+
if (useSPI) {
71+
updateLEDsSPI(i);
72+
} else {
73+
updateLEDs(i);
74+
//updateLEDsLong(i);
75+
}
76+
delay(delayTime);
77+
}
78+
}
79+
80+
81+
82+
/*
83+
* updateLEDs() - sends the LED states set in ledStates to the 74HC595
84+
* sequence
85+
*/
86+
void updateLEDs(byte value){
87+
digitalWrite(latch, LOW); //Pulls the chips latch low
88+
shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register
89+
digitalWrite(latch, HIGH); //Pulls the latch high displaying the data
90+
}
91+
92+
/*
93+
* updateLEDsLong() - sends the LED states set in ledStates to the 74HC595
94+
* sequence. Same as updateLEDs except the shifting out is done in software
95+
* so you can see what is happening.
96+
*/
97+
void updateLEDsLong(byte value){
98+
digitalWrite(latch, LOW); //Pulls the chips latch low
99+
for(int i = 0; i < 8; i++){ //Will repeat 8 times (once for each bit)
100+
byte bit = value & B10000000; //We use a "bitmask" to select only the eighth
101+
//bit in our number (the one we are addressing this time through
102+
value = value << 1; //we move our number up one bit value so next time bit 7 will be
103+
//bit 8 and we will do our math on it
104+
if(bit == 128){
105+
digitalWrite(data, HIGH);
106+
} //if bit 8 is set then set our data pin high
107+
else
108+
{
109+
digitalWrite(data, LOW);
110+
} //if bit 8 is unset then set the data pin low
111+
digitalWrite(clock, HIGH); //the next three lines pulse the clock pin
112+
delay(1); // Make really, really sure the chip sees the change. Not really necessary.
113+
digitalWrite(clock, LOW);
114+
}
115+
digitalWrite(latch, HIGH); //pulls the latch high shifting our data into being displayed
116+
}
117+
118+
// The Arduino's SPI can be used to drive the IC instead of doing signalling
119+
// in software with the shiftOut(...) library routine. SPI is faster and supports
120+
// multiplexing multiple devices using shared data and clock signal pins.
121+
// The Arduino platform provides built-in support for SPI.
122+
// See http://arduino.cc/en/Reference/SPI
123+
//
124+
// This routine is functionally same as updateLEDs() in that it raises the latch,
125+
// then for each bit sets the data pin and pulses the clock. It lowers
126+
// the latch when all 8 bits are sent to apply the changes.
127+
//
128+
// The difference is that updateLEDs() uses the "transfer(...)" routine, a software
129+
// routine in the Arduino library that sends that data using digitalWrite(...)
130+
// calls. updateLEDsSPI() instead uses support for SPI built in to the
131+
// microcontroller in the Arduino to transmit the data, which is a LOT faster.
132+
//
133+
// To see just how much faster this is, comment out the delay() call in the main
134+
// loop then compare how fast the LEDs flash with and without useSPI. With SPI
135+
// you won't even be able to tell the LED for the most significant bit is
136+
// flashing without adding a delay, it happens so fast.
137+
//
138+
139+
void updateLEDsSPI(byte value) {
140+
// Select the IC to tell it to expect data
141+
digitalWrite(latch, HIGH);
142+
// Send 8 bits, MSB first, pulsing the clock after each bit
143+
SPI.transfer(value);
144+
// Lower the latch to apply the changes
145+
digitalWrite(latch, LOW);
146+
}
147+

0 commit comments

Comments
 (0)