You are on page 1of 10

NCP 516 – EMBEDDED SYSTEMS LABORATORY

EXPERIMENT #9 –THE I2C and SPI Bus

LEARNING OUTCOMES:
After completing this experiment the students will be able to:
1. Demonstrate the use of the I2C and SPI interface.
2. Apply data transfer from one Arduino board to another.
3. Implement the wire library and SPI library.

EXPERIMENT 9.A. I2C MASTER READER / SLAVE SENDER


COMPONENTS:
1. 2 x Arduino board

CIRCUIT & SCHEMATIC DIAGRAM:

Figure 1. Circuit diagram of Experiment 9.A Figure 2: Schematic diagram of experiment 9.A.

PROCEDURE
1. Connect pin 4 (the clock, or SCL, pin) and pin 5 (the data, or SDA, pin) on the master
Arduino to their counterparts on the slave board.
2. Make sure that both boards share a common ground. In order to enable serial
communication, the master Arduino must be connected to your computer via USB.
3. Plug your Arduino board to your computer and start the Arduino program.
4. Choose the Arduino board that you are you using in the Tools > Boards menu, then choose
the COM port you are using in the Tools > Serial Port menu.
5. Encode and verify the program below, if no errors occurred download the program into
your Arduino board.
6. Open the serial monitor and observe the output of the system.

*Image and other sources are taken from arduino.cc

1|Page
NCP 516 – EMBEDDED SYSTEMS LABORATORY

CODE:
}
FOR MASTER:
#include <Wire.h> FOR SLAVE:
#include <Wire.h>
void setup() {
Wire.begin(); void setup() {
Serial.begin(9600); Wire.begin(2);
} Wire.onRequest(requestEvent);
}
void loop() {
Wire.requestFrom(2, 30); void loop() {
while(Wire.available()) delay(100);
{ }
char c = Wire.read();
Serial.print(c); void requestEvent() {
} Wire.write("This is from the
Serial.println(); slave device!");
delay(500); }

OBSERVATION
The following experiment demonstrates how two Arduino UNO boards can communicate and
exchange data between each other. The following experiment elaborates the circuit connection
as well as the code of how to utilize I2C effectively. The I2C connection determines which Arduino
UNO will be the master device as well as the slave device, which is essential in determining who
will receive data and display it as well as which codes should be inputted to which device. The
following set of codes for the master and the slave device demonstrates a simple print statement
to the slave device when the request to the master device is fulfilled.

*Image and other sources are taken from arduino.cc

2|Page
NCP 516 – EMBEDDED SYSTEMS LABORATORY

EXPERIMENT 9.B. I2C MASTER WRITER / SLAVE RECEIVER


COMPONENTS:
1. 2 x Arduino board

CIRCUIT & SCHEMATIC DIAGRAM:

Figure 3. Circuit diagram of Experiment 9.B Figure 4. Circuit diagram of Experiment 9.B.

PROCEDURE:
1. Connect pin 5 (the clock, or SCL, pin) and pin 4 (the data, or SDA, pin) on the master
Arduino to their counterparts on the slave board.
2. Make sure that both boards share a common ground. In order to enable serial
communication, the slave Arduino must be connected to your computer via USB.
3. Plug your Arduino board to your computer and start the Arduino program.
4. Choose the Arduino board that you are you using in the Tools > Boards menu, then choose
the COM port you are using in the Tools > Serial Port menu.
5. Encode and verify the program below, if no errors occurred download the program into
your Arduino board.
6. Open the serial monitor and observe the output of the system.

CODE:
FOR MASTER: Wire.write("Data: ");
#include <Wire.h> Wire.write(data);
Wire.endTransmission();
void setup() { data++;
Wire.begin(); delay(500);
} }
byte data = 0;

void loop() {
Wire.beginTransmission(4);

*Image and other sources are taken from arduino.cc

3|Page
NCP 516 – EMBEDDED SYSTEMS LABORATORY

FOR SLAVE: }
#include <Wire.h>
void setup() { void receiveEvent(int howMany) {
Wire.begin(4); while(1 < Wire.available()) {
Wire.onReceive(receiveEvent); char c = Wire.read();
Serial.begin(9600); Serial.print(c);
} }
int x = Wire.read();
void loop() { Serial.println(data);
delay(100); }

OBSERVATION
The following experiment shows a similar circuit setup as well as function to utilize the I2C for two
Arduino UNO devices. The following displays a varying data which is different compared to the
prior experiment wherein the slave device is tasked to display data within the device itself while
the master device asks for availability in communication. The following experiment takes data
from the master device for display on the slave device, the data is incremented in the master
device and then displayed to the slave device.
EXPERIMENT 9.C. SPI MASTER WRITER / SLAVE RECEIVER
COMPONENTS:
1. 2 x Arduino board

CIRCUIT & SCHEMATIC DIAGRAM:

Figure 5. Circuit diagram of Experiment 9.C Figure 6. Circuit diagram of Experiment 9.C

PROCEDURE:
1. Connect pin 13 (the SCLK, pin), pin 12 (the MISO pin), pin 11 (the MOSI pin) and pin 10
(the SS pin) on the master Arduino to their counterparts on the slave board.
2. Make sure that both boards share a common ground. In order to enable serial
communication, the slave Arduino must be connected to your computer via USB.
3. Plug your Arduino board to your computer and start the Arduino program.

*Image and other sources are taken from arduino.cc

4|Page
NCP 516 – EMBEDDED SYSTEMS LABORATORY

4. Choose the Arduino board that you are you using in the Tools > Boards menu, then choose
the COM port you are using in the Tools > Serial Port menu.
5. Encode and verify the program below, if no errors occurred download the program into
your Arduino board.
6. Open the serial monitor and observe the output of the system.

CODE:
FOR MASTER: Serial.begin (115200); //
#include <SPI.h> debugging
// turn on SPI in slave mode
void setup (void) SPCR |= bit (SPE);
{ // have to send on master in,
digitalWrite(SS, HIGH); // *slave out*
ensure SS stays high for now pinMode(MISO, OUTPUT);
// Put SCK, MOSI, SS pins into // get ready for an interrupt
output mode pos = 0; // buffer empty
// also put SCK, MOSI into LOW process_it = false;
state, and SS into HIGH state. // now turn on interrupts
// Then put SPI hardware into SPI.attachInterrupt();
Master mode and turn SPI on } // end of setup
SPI.begin ();
// Slow down the master a bit

SPI.setClockDivider(SPI_CLOCK_DIV8)
;
} // end of setup

void loop (void)


{
char c;
// enable Slave Select
digitalWrite(SS, LOW); // SS
is pin 10
// send test string // SPI interrupt routine
for (const char * p = "NCP ISR (SPI_STC_vect)
3102\n" ; c = *p; p++) {
SPI.transfer (c); byte c = SPDR; // grab byte from
// disable Slave Select SPI Data Register
digitalWrite(SS, HIGH); // add to buffer if room
delay (1000); // 1 seconds delay if (pos < (sizeof (buf) - 1))
} // end of loop buf [pos++] = c;
// example: newline means time to
FOR SLAVE: process buffer
#include <SPI.h> if (c == '\n')
process_it = true;
char buf [100]; } // end of interrupt routine
volatile byte pos; SPI_STC_vect
volatile boolean process_it; // main loop - wait for flag set in
interrupt routine
void setup (void) void loop (void)
{ {
if (process_it)

*Image and other sources are taken from arduino.cc

5|Page
NCP 516 – EMBEDDED SYSTEMS LABORATORY

{ process_it = false;
buf [pos] = 0; } // end of flag set
Serial.println (buf); } // end of loop
pos = 0;
OBSERVATION
The following experiment is different from the first two experiments as this experiment aim to
demonstrate and show how SPI communication protocol works. SPI is a synchronous serial
communication protocol and is also known as the Serial Peripheral Interface which is used to
transfer data in both directions at the same time. The circuit design for the SPI communication
protocol is different from the I2C protocol in terms of wiring. While the I2C communication protocol
uses two analog wires for the master and the slave device, the SPI communication protocol uses
four wires for the slave and the master device connected in parallel which serves as the MOSI,
MISO, SCK, and the CS/SS. In this experiment, the master sends one character at a time to form
the word “NCP 3102” to the slave device for display. The output is displayed one by one and
creates a new line if the word is completed, the use of interrupts and buffers were used to make
SPI communication possible.
EXPERIMENT 9.D. SPI MASTER READER / SLAVE SENDER
COMPONENTS:
1. 2 x Arduino board

CIRCUIT & SCHEMATIC DIAGRAM:

Figure 7. Circuit diagram of Experiment 9.D Figure 8. Circuit diagram of Experiment 9.D

PROCEDURE:
1. Connect pin 13 (the SCLK, pin), pin 12 (the MISO pin), pin 11 (the MOSI pin) and pin 10
(the SS pin) on the master Arduino to their counterparts on the slave board.
2. Make sure that both boards share a common ground. In order to enable serial
communication, the master Arduino must be connected to your computer via USB.

*Image and other sources are taken from arduino.cc

6|Page
NCP 516 – EMBEDDED SYSTEMS LABORATORY

3. Plug your Arduino board to your computer and start the Arduino program.
4. Choose the Arduino board that you are you using in the Tools > Boards menu, then choose
the COM port you are using in the Tools > Serial Port menu.
5. Encode and verify the program below, if no errors occurred download the program into
your Arduino board.
6. Open the serial monitor and observe the output of the system.

CODE:
FOR MASTER: digitalWrite(SS, HIGH);
#include <SPI.h> Serial.println ("Adding
results:");
void setup (void) Serial.println (a, DEC);
{ Serial.println (b, DEC);
Serial.begin (115200); Serial.println (c, DEC);
Serial.println (); Serial.println (d, DEC);
digitalWrite(SS, HIGH); // // enable Slave Select
ensure SS stays high for now digitalWrite(SS, LOW);
// Put SCK, MOSI, SS pins into transferAndWait ('s'); //
output mode subtract command
// also put SCK, MOSI into LOW transferAndWait (10);
state, and SS into HIGH state. a = transferAndWait (17);
// Then put SPI hardware into b = transferAndWait (33);
Master mode and turn SPI on c = transferAndWait (42);
SPI.begin (); d = transferAndWait (0);
// Slow down the master a bit // disable Slave Select
digitalWrite(SS, HIGH);
SPI.setClockDivider(SPI_CLOCK_DIV8) Serial.println ("Subtracting
; results:");
} // end of setup Serial.println (a, DEC);
Serial.println (b, DEC);
byte transferAndWait (const byte Serial.println (c, DEC);
what) Serial.println (d, DEC);
{ delay (1000); // 1 second delay
byte a = SPI.transfer (what); } // end of loop
delayMicroseconds (20);
return a; FOR SLAVE:
} // end of transferAndWait #include <SPI.h>
volatile byte command = 0;
void loop (void)
{ void setup (void)
byte a, b, c, d; {
// enable Slave Select // have to send on master in,
digitalWrite(SS, LOW); *slave out*
transferAndWait ('a'); // add pinMode(MISO, OUTPUT);
command // turn on SPI in slave mode
transferAndWait (10); SPCR |= _BV(SPE);
a = transferAndWait (17); // turn on interrupts
b = transferAndWait (33); SPCR |= _BV(SPIE);
c = transferAndWait (42); } // end of setup
d = transferAndWait (0);
// disable Slave Select // SPI interrupt routine

*Image and other sources are taken from arduino.cc

7|Page
NCP 516 – EMBEDDED SYSTEMS LABORATORY

ISR (SPI_STC_vect) // subtract from incoming byte,


{ return result
byte c = SPDR; case 's':
switch (command) SPDR = c - 8; // subtract 8
{ break;
// no command? then this is the } // end of switch
command } // end of interrupt service
case 0: routine (ISR) SPI_STC_vect
command = c;
SPDR = 0; void loop (void)
break; {
// add to incoming byte, return // if SPI not active, clear
result current command
case 'a': if (digitalRead (SS) == HIGH)
SPDR = c + 15; // add 15 command = 0;
break; } // end of loop

OBSERVATION
The following experiment also demonstrates the use of SPI communication protocol wherein the
master device is the reader while the slave device is the sender of data. It demonstrates addition
and subtraction based on the given bit and displays its results in a loop. The following circuit
employs the slave device to add and subtract from incoming bytes and return the results to the
master device for the result.
EXPERIMENT 9.E. SPI MASTER READER / SLAVE SENDER USING INTERRUPT
COMPONENTS:
1. 2 x Arduino board

CIRCUIT & SCHEMATIC DIAGRAM:

Figure 9. Circuit diagram of Experiment 9.D Figure 10. Circuit diagram of Experiment 9.D

PROCEDURE:

*Image and other sources are taken from arduino.cc

8|Page
NCP 516 – EMBEDDED SYSTEMS LABORATORY

1. Connect pin 13 (the SCLK, pin), pin 12 (the MISO pin) and pin 11 (the MOSI pin) on the
master Arduino to their counterparts on the slave board, while pin 10 (the SS pin) of the
master Arduino is connected to the pin 2 (Interrupt 0 pin) of the slave board.
2. Make sure that both boards share a common ground. In order to enable serial
communication, the master Arduino must be connected to your computer via USB.
3. Plug your Arduino board to your computer and start the Arduino program.
4. Choose the Arduino board that you are you using in the Tools > Boards menu, then choose
the COM port you are using in the Tools > Serial Port menu.
5. Encode and verify the program below, if no errors occurred download the program into
your Arduino board.
6. Open the serial monitor and observe the output of the system.

CODE:
FOR MASTER: // enable Slave Select
#include <SPI.h> digitalWrite(SS, LOW);
transferAndWait ('a'); // add
void setup (void) command
{ transferAndWait (10);
Serial.begin (115200); a = transferAndWait (17);
Serial.println (); b = transferAndWait (33);
digitalWrite(SS, HIGH); // c = transferAndWait (42);
ensure SS stays high for now d = transferAndWait (0);
// Put SCK, MOSI, SS pins into // disable Slave Select
output mode digitalWrite(SS, HIGH);
// also put SCK, MOSI into LOW Serial.println ("Adding
state, and SS into HIGH state. results:");
// Then put SPI hardware into Serial.println (a, DEC);
Master mode and turn SPI on Serial.println (b, DEC);
SPI.begin (); Serial.println (c, DEC);
// Slow down the master a bit Serial.println (d, DEC);
// enable Slave Select
SPI.setClockDivider(SPI_CLOCK_DIV8) digitalWrite(SS, LOW);
; transferAndWait ('s'); //
} // end of setup subtract command
transferAndWait (10);
byte transferAndWait (const byte a = transferAndWait (17);
what) b = transferAndWait (33);
{ c = transferAndWait (42);
byte a = SPI.transfer (what); d = transferAndWait (0);
delayMicroseconds (20); // disable Slave Select
return a; digitalWrite(SS, HIGH);
} // end of transferAndWait Serial.println ("Subtracting
results:");
void loop (void) Serial.println (a, DEC);
{ Serial.println (b, DEC);
byte a, b, c, d; Serial.println (c, DEC);

*Image and other sources are taken from arduino.cc

9|Page
NCP 516 – EMBEDDED SYSTEMS LABORATORY

Serial.println (d, DEC); // SPI interrupt routine


delay (1000); // 1 second delay ISR (SPI_STC_vect)
} // end of loop {
byte c = SPDR;
FOR SLAVE: switch (command)
#include<SPI.h> {
byte command = 0; // no command? then this is the
command
// start of transaction, no command case 0:
yet command = c;
void ss_falling () SPDR = 0;
{ break;
command = 0; // add to incoming byte, return
} // end of interrupt service result
routine (ISR) ss_falling case 'a':
SPDR = c + 15; // add 15
void setup (void) break;
{ // subtract from incoming byte,
// have to send on master in, return result
*slave out* case 's':
pinMode(MISO, OUTPUT); SPDR = c - 8; // subtract 8
// turn on SPI in slave mode break;
SPCR |= _BV(SPE); } // end of switch
// turn on interrupts } // end of interrupt service
SPCR |= _BV(SPIE); routine (ISR) SPI_STC_vect
// interrupt for SS falling edge
attachInterrupt (0, ss_falling, void loop (void)
FALLING); {
} // end of setup // all done with interrupts
} // end of loop
OBSERVATION
The following experiment is similar to the prior experiment that employs the master device to
read and the slave device as a sender. The experiment also has similar display as it displays
the result of the added and subtracted values from the bytes received and sent by the slave
device. The major difference of the two experiments is that this experiment uses interrupts to
perform the code and display the needed results to the serial monitor.

*Image and other sources are taken from arduino.cc

10 | P a g e

You might also like