I am using the SPI interrupt example I found on this forum. I have a Mega as an SPI slave, it receives 160 characters for display on an LCD then it needs to send a decoded keypad press back on the same SPI. I have an UNO sending the 160 LCD characters. How would I program both master and slave to transfer the keypress over SPI? My code below does not actually decode any keypad, just want to send a test character for now. I am successfully receiving the 160 lcd characters and displaying on the LCD.
Master:
#include <SPI.h>
#include "pins_arduino.h"
volatile byte c;
void setup (void)
{
// Put SCK, MOSI, SS pins into output mode
// also put SCK, MOSI into LOW state, and SS into HIGH state.
// Then put SPI hardware into Master mode and turn SPI on
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV8);
SPI.beginTransaction(SPISettings(1000000, LSBFIRST, SPI_MODE0));
Serial.begin(38400);
Serial.println("begin");
//
} // end of setup
ISR (SPI_STC_vect)
{
c = SPDR; // grab byte from SPI Data Register
} // end of interrupt routine SPI_STC_vect
void loop (void)
{
// enable Slave Select
digitalWrite(SS, LOW); // SS is pin 10
// send test string
SPI.transfer (0x5f);
for (int a = 0; a <= 2; a++){
for (const char * p = "1234567890123456789012345678901234567890" ; c = *p; p++)
SPI.transfer (c);
}
char millc[40];
sprintf(millc,"%08lu X",millis());
for (int a= 0; a <= 39; a++) SPI.transfer(millc[a]);
SPI.transfer (0x7f);
//not sure here. I just sent the 160 lcd characters, now I need to get the keypad press response from the slave
delay(1);
//SPCR |= _BV(SPE);
SPI.attachInterrupt();
delay(1);
//SPCR |= _BV(SPE);
SPI.detachInterrupt();
//????
Serial.println(c,HEX);//c is volitile byte captured in interrupt
delay(1);
// disable Slave Select
digitalWrite(SS, HIGH);
delay (100);
} // end of loop
Slave:
/*
The circuit:
* LCD RS (7) pin to digital pin 9
* LCD RW (5)pin to digital pin 8
* LCD Enable (9)Top 2 lines pin to digital pin 7
* LCD Enable (3)Bottom 2 lines pin to digital pin 6
* LCD D4 (19)pin to digital pin 5
* LCD D5 (21)pin to digital pin 4
* LCD D6 (23)pin to digital pin 3
* LCD D7(25) pin to digital pin 2
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
*
* Lindsay LCD Pinout:
* 1 NC 2 NC
* 3 E2 4 V0
* 5 RW 6 NC
* 7 RS 8 VSS
* 9 E1 10 VSS
* 11 DBO 12 VSS
* 13 DB1 14 VSS
* 15 DB2 16 VSS
* 17 DB3 18 VSS
* 19 DB4 20 VSS
* 21 DB5 22 VDD
* 23 DB6 24 VDD
* 25 DB7 26 NC
* I took a photo and put it in this directory
*/
#include <Arduino.h>
#include <LiquidCrystal.h>
#include <Wire.h>
#include <SPI.h>
int forceSSpin = 30;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcdT(9, 8, 7, 5, 4, 3, 2);//set up top 2 lines
LiquidCrystal lcdB(9, 8, 6, 5, 4, 3, 2);//set up bottom 2 lines
char buf [200];
char lcd [200];
volatile byte pos,clrlcd;
volatile boolean process_it;
volatile int npos,got5f;
int lcdLatch = 0;
unsigned long td = 0;
void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}
void setup (void)
{
Serial.begin (115200); // debugging
pinMode(forceSSpin,OUTPUT);
digitalWrite(forceSSpin,HIGH);
// have to send on master in, *slave out*
pinMode(MISO, OUTPUT);
SPI.detachInterrupt();
// turn on SPI in slave mode
pos = 0; // buffer empty
process_it = false;
init_lcd();
delay(2000);
// now turn on interrupts
SPI.beginTransaction(SPISettings(1500000, LSBFIRST, SPI_MODE0));
SPCR |= _BV(SPE);
// get ready for an interrupt
Serial.println("Begin");
td = millis();
SPI.attachInterrupt();
delay(100);
digitalWrite(forceSSpin,LOW);
Serial.println(pos);
Serial.println(got5f);
Serial.println(process_it);
} // end of setup
// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR; // grab byte from SPI Data Register
// add to buffer if room
if (pos < sizeof buf)
{
if (got5f) buf [pos++] = c;
if (c == 0x5f && !got5f){
pos = 0;
got5f = 1;
}
// example: newline means time to process buffer
if (got5f && c == 0x7f){
process_it = true;
npos = pos;
pos = 0;
got5f = 0;
}
} // end of room available
else{
pos = 0;
clrlcd = 1;
}
} // end of interrupt routine SPI_STC_vect
// main loop - wait for flag set in interrupt routine
void loop (void)
{
if (millis() > td + 2000) {
digitalWrite(forceSSpin,HIGH);
delay(100);
digitalWrite(forceSSpin,LOW);
process_it = true;
td = millis();
}
if (process_it)
{
SPI.transfer (millis() & 0xff);//not sure here, I just received 160 lcd character and need to send 1 byte keypress back on SPI
td = millis();
lcdLatch = 0;
SPI.detachInterrupt();
process_it = false;
int p = 0;
int a;
for (a = 0; a < npos; a++){
//if (buf[a] < 0x10) Serial.print('0');
//Serial.print(buf[a],HEX);
//Serial.print(' ');
lcd[p++] = buf[a];//( & 0xF) | (buf[a+1] << 4);
}
lcd[a-1] = 0;
String lcdp = lcd;
pos = 0; // buffer empty
got5f = 0;
npos = 0;
//DateTime now = rtc.now();
char line[50];
String line1;
line1 = lcdp.substring(0,40);
line1.toCharArray(line,41);
lcdT.setCursor(0,0);//column,row
lcdT.print(line);
lcdT.display();
Serial.println(line);
line1 = lcdp.substring(40,80);
line1.toCharArray(line,41);
lcdT.setCursor(0,1);//column,row
lcdT.print(line);
lcdT.display();
Serial.println(line);
line1 = lcdp.substring(80,120);
line1.toCharArray(line,41);
lcdB.setCursor(0,0);//column,row
lcdB.print(line);
lcdB.display();
Serial.println(line);
line1 = lcdp.substring(120,160);
line1.toCharArray(line,41);
lcdB.setCursor(0,1);//column,row
lcdB.print(line); // write something to the internal memory
lcdB.display();
Serial.println(line);
SPI.attachInterrupt();
} // end of flag set
} // end of loop
void init_lcd(){
// set up the LCD's number of columns and rows:
lcdT.begin(40, 2);
lcdB.begin(40, 2);
// Print a message to the LCD.
lcdT.clear();
lcdB.clear();
lcdT.setCursor(0,2);//column,row
lcdT.print("Initialization Done...");
lcdT.display();
delay(200);
lcdT.clear();
lcdB.clear();
lcdT.setCursor(0,0);
lcdB.setCursor(0,0);
}