SPI — синхронний послідовний протокол. Один master (ESP32), один чи більше slave (SX1276). Чотири лінії:
Лінія Хто керує Призначення
SCK master тактовий сигнал — кожен імпульс = один біт
MOSI master дані master → slave
MISO slave дані slave → master
CS (NSS) master вибір slave: LOW = «я говорю з тобою»
Ключові факти:
SPI — повний дуплекс: на кожен такт SCK один біт іде по MOSI і одночасно один біт приходить по MISO. «Прийняти байт» = «послати байт-пустушку і подивитись, що прийшло».
Немає адрес, немає ACK, немає start/stop бітів. Уся «рамка» — це рівень CS.
SPI mode — це два параметри: CPOL (рівень SCK у спокої) і CPHA (по якому фронту зчитувати біт). SX1276 працює в mode 0: CPOL=0 (SCK у спокої LOW), CPHA=0 (slave виставляє біт, master зчитує по передньому фронту SCK, зсув на наступний біт — по задньому).
Біти йдуть старшим уперед (MSB first).
Сигнал SPI GPIO ESP32
SCK 5
MISO 19
MOSI 27
CS (NSS) 18
RST радіо 23
Направлення: SCK, MOSI, CS — OUTPUT; MISO — INPUT. Стан у спокої: CS = HIGH, SCK = LOW (mode 0).
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
// ================================================================
// LILYGO LoRa32 V1.6.1 / SX1276
// ================================================================
#define SCK_PIN 5
#define MISO_PIN 19
#define MOSI_PIN 27
#define CS_PIN 18
#define RST_PIN 23
#define DIO0_PIN 26
#define DIO1_PIN 33
#define DIO2_PIN 32
// Регістри SX1276
#define REG_VERSION 0x42
// ================================================================
// 1. ІНІЦІАЛІЗАЦІЯ ПІНІВ
// ================================================================
void spi_init() {
pinMode(CS_PIN, OUTPUT);
pinMode(SCK_PIN, OUTPUT);
pinMode(MOSI_PIN, OUTPUT);
pinMode(MISO_PIN, INPUT);
pinMode(RST_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);
digitalWrite(SCK_PIN, LOW);
digitalWrite(MOSI_PIN, LOW);
// Скидання SX1276
digitalWrite(RST_PIN, LOW);
delay(10);
digitalWrite(RST_PIN, HIGH);
delay(10);
}
// ================================================================
// 2. Передача одного байта та одночасне читання
// SPI Mode 0, MSB First
// ================================================================
uint8_t spi_transfer_byte(uint8_t out) {
uint8_t in = 0;
for (uint8_t i = 0; i < 8; i++) {
// Виставляємо біт на MOSI
digitalWrite(MOSI_PIN, (out & 0x80) ? HIGH : LOW);
out <<= 1;
// Тактовий імпульс
digitalWrite(SCK_PIN, HIGH);
// Читаємо MISO
in <<= 1;
if (digitalRead(MISO_PIN) == HIGH) {
in |= 0x01;
}
digitalWrite(SCK_PIN, LOW);
}
return in;
}
// ================================================================
// 3. Читання регістра SX1276
// ================================================================
uint8_t read_register(uint8_t reg) {
uint8_t value;
// CS LOW -> початок SPI транзакції
digitalWrite(CS_PIN, LOW);
// Для читання старший біт адреси = 0
spi_transfer_byte(reg & 0x7F);
// Передаємо 0x00, щоб отримати відповідь від SX1276
value = spi_transfer_byte(0x00);
// CS HIGH -> кінець транзакції
digitalWrite(CS_PIN, HIGH);
return value;
}
// ================================================================
// 4. SETUP
// ================================================================
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println();
Serial.println("==============================");
Serial.println("LILYGO LoRa32 SX1276 TEST");
Serial.println("==============================");
spi_init();
Serial.println("SPI initialized");
// Читаємо регістр Version
uint8_t version = read_register(REG_VERSION);
Serial.print("SX1276 REG_VERSION = 0x");
if (version < 0x10) {
Serial.print("0");
}
Serial.println(version, HEX);
if (version == 0x12) {
Serial.println("SX1276/SX1278 знайдено!");
} else {
Serial.println("ПОМИЛКА: SX127x не знайдено.");
Serial.println("Перевір піни та підключення.");
}
}
// ================================================================
// 5. LOOP
// ================================================================
void loop() {
uint8_t version = read_register(REG_VERSION);
Serial.print("REG_VERSION = 0x");
if (version < 0x10) {
Serial.print("0");
}
Serial.println(version, HEX);
delay(1000);
}