#define SPI_MASTER_SLAVE_SEL_PIN (2) // ใช้ขา 2 เพืÉอตรวจวาเป็น ่ Master หรือSlave
#define SS_PIN (53) // Slave Select Pin (ใน Arduino Megaคือขา53)
boolean is_spi_master; // flag เช็ควาเราทํ ่ างานเป็น Master (true/false)
volatile boolean slave_received = false;
volatile uint8_t slave_recv_data = 0xff; // ตัวแปรเก็บข้อมูลทีÉSlaveรับเข้ามา
//slave_receivedและslave_recv_data ใช้ในโหมดSlave เพืÉอระบุวามีข้ ่ อมูลใหม่เข้ามาแล้วหรือไม่และเก็บข้อมูลทีÉรับมา
void setup() {
Serial.begin(115200);
//กาหนดขา ํ SPI_MASTER_SLAVE_SEL_PIN เป็น INPUT_PULLUP
pinMode( SPI_MASTER_SLAVE_SEL_PIN, INPUT_PULLUP );
//อ่านสถานะจากขาSPI_MASTER_SLAVE_SEL_PIN เพืÉอตัÊงเป็น Master/Slave
// SPI_MASTER_SLAVE_SEL_PIN จะมีค่า= low เนืÉองจากpin 2 ต่อกบั GNDif ( digitalRead(SPI_MASTER_SLAVE_SEL_PIN) == LOW) {
is_spi_master = true;-
} else {
is_spi_master = false;
}
if (is_spi_master) {
// ---กรณีเป็น Master ---
pinMode( SS_PIN, OUTPUT );
digitalWrite( SS_PIN, HIGH ); // เริÉมแรกให้SSเป็น HIGH (disable Slave)
// เริÉมต้นใช้งาน SPI
SPI.begin();
SPI.setDataMode( SPI_MODE0 ); // เลือกโหมด0 (ขาสัญญาณ Clock ปกติเป็น LOW,จับข้อมูลขาขึÊน)
SPI.setBitOrder( MSBFIRST ); // ส่งบิตทีÉมีค่าสูงสุด(MSB)ก่อน
SPI.setClockDivider( SPI_CLOCK_DIV16 ); // ตัÊงความเร็วนาฬิกาSPI
Serial.println( F("SPI Master...") );
delay(100);
}
else {
// ---กรณีเป็น Slave ---
pinMode( MISO, OUTPUT ); // Slave ต้องส่งข้อมูลออกผาน่ MISOpinMode( SS_PIN, INPUT_PULLUP ); // SSเป็นขาเข้าสําหรับกรณีSlave
// ตัÊงค่ารีจิสเตอร์ของSPI สําหรับโหมดSlave
SPDR = 0xFF; //ค่าเริÉมต้นใน SPI Data Register
SPCR &= ~_BV(MSTR); // เคลียร์บิต MSTR เพืÉอเป็น Slave
SPCR &= ~_BV(CPOL); // ตัÊงโหมดclockเป็น 0
SPCR &= ~_BV(CPHA); // ตัÊงโหมดจับข้อมูลขาขึÊน
SPCR &= ~_BV(DORD); // MSB first
SPCR |= _BV(SPE); // Enable SPI
slave_received = false;
SPI.attachInterrupt(); // เปิ ดใช้งาน interrupt เมืÉอมีข้อมูลเข้ามาในโหมดSlave
Serial.println( F("SPI Slave...") );
}
void loop() {
if ( is_spi_master ) {
static uint8_t send_data = 0x00, recv_data;
Serial.print( F("Master> sent: 0x") );
Serial.print( send_data, HEX );
digitalWrite( SS_PIN, LOW ); // เลือกใช้Slave (active low)
recv_data = SPI.transfer( send_data );
// เรียกSPI.transfer(send_data) เป็นคําสังที É Éจะส่งค่าผาน่ MOSIและในขณะเดียวกนจะรับค ั ่าจากSlaveผาน่ MISOกลับมา
เก็บใน recv_data
digitalWrite( SS_PIN, HIGH ); // ปลดSlave
Serial.print( F(", received: 0x") );
Serial.println( recv_data, HEX );
send_data += 1; // ส่งข้อมูลครัÊงถัดไปเพิÉมขึÊนไปเรืÉอยๆ
delay( 1000 );
}
else {
if ( slave_received ) { //ถ้าตัวแปรslave_receivedเป็น trueแสดงวามีข้ ่ อมูลจาก Master ส่งมา
SPDR = slave_recv_data; // ตอบกลับไปทางSPDR เมืÉอ Master เรียกSPI.transfer()
slave_received = false;
Serial.print( F("Slave: received 0x") );
Serial.println( slave_recv_data, HEX );
}
delay(1);
}
}
ISR(SPI_STC_vect) {
slave_recv_data = SPDR; //อ่านข้อมูลจากSPDR
slave_received = true; // ตัÊง flagวา่ Slave มีข้อมูลใหม่เข้ามา
}