一、系统概述
本方案基于STM32F103C8T6 微控制器与SX1278 Lora模块 ,实现点对点无线通信 ,支持自定义数据透传 、参数配置 和低功耗控制 。SX1278是Semtech推出的高性能Lora芯片,工作在Sub-GHz频段(433/868/915MHz),具备长距离(3-5km视距) 、低功耗 、强抗干扰特点,适用于物联网传感、远程抄表、工业监测等场景。
二、硬件设计
1. 核心组件
| 组件 | 型号/规格 | 功能说明 |
|---|---|---|
| 主控芯片 | STM32F103C8T6 | 32位ARM Cortex-M3,72MHz |
| Lora模块 | SX1278(Ra-01) | 433MHz频段,SPI接口,20dBm功率 |
| 晶振 | 8MHz+32.768kHz | 系统时钟+实时时钟 |
| 电源 | 3.3V LDO(AMS1117) | 为STM32和SX1278供电 |
| 天线 | 433MHz弹簧天线 | 50Ω阻抗,增益≥2dBi |
2. 硬件连接(SPI接口)
| SX1278引脚 | STM32引脚 | 功能说明 |
|---|---|---|
| SCK | PA5 (SPI1_SCK) | SPI时钟(模式0:CPOL=0,CPHA=0) |
| MISO | PA6 (SPI1_MISO) | SPI数据输入(SX1278→STM32) |
| MOSI | PA7 (SPI1_MOSI) | SPI数据输出(STM32→SX1278) |
| NSS | PA4 (GPIO) | 片选(低电平有效) |
| DIO0 | PB0 (EXTI0) | 中断输出(接收完成/发送完成) |
| RST | PB1 (GPIO) | 复位(低电平有效) |
| VCC | 3.3V | 电源(SX1278工作电压1.8-3.7V) |
| GND | GND | 地 |
三、软件设计(STM32CubeMX开发)
1. STM32CubeMX配置
(1)时钟与SPI
-
系统时钟:HSE=8MHz → PLL×9 → 72MHz SYSCLK;
-
SPI1:全双工主模式,8位数据,分频系数8(9MHz),CPOL=0,CPHA=0(模式0);
-
GPIO:PA4(NSS,推挽输出)、PB0(DIO0,外部中断下降沿触发)、PB1(RST,推挽输出)。
(2)中断与调试
-
启用EXTI0中断(DIO0触发),优先级中等;
-
启用USART1(PA9/TX,PA10/RX),用于调试信息输出(波特率115200)。
2. 核心代码实现
(1)SX1278驱动(sx1278.c)
寄存器定义与基础函数:
c
#include "sx1278.h"
#include "spi.h"
#include "gpio.h"
#include <string.h>
// SX1278寄存器地址(部分关键寄存器)
#define REG_FIFO 0x00
#define REG_OP_MODE 0x01
#define REG_FR_MSB 0x06
#define REG_FR_MID 0x07
#define REG_FR_LSB 0x08
#define REG_PA_CONFIG 0x09
#define REG_LNA 0x0C
#define REG_FIFO_ADDR_PTR 0x0D
#define REG_FIFO_TX_BASE 0x0E
#define REG_FIFO_RX_BASE 0x0F
#define REG_IRQ_FLAGS 0x12
#define REG_RX_NB_BYTES 0x13
#define REG_PKT_SNR 0x19
#define REG_PKT_RSSI 0x1A
#define REG_MODEM_CONFIG1 0x1D
#define REG_MODEM_CONFIG2 0x1E
#define REG_PAYLOAD_LEN 0x22
#define REG_SYNC_WORD 0x39
#define REG_DIO_MAPPING1 0x40
#define REG_VERSION 0x42 // 版本号(0x12=SX1278)
// 工作模式
#define MODE_SLEEP 0x00
#define MODE_STDBY 0x01
#define MODE_TX 0x03
#define MODE_RX_CONT 0x05
#define MODE_RX_SINGLE 0x06
// 全局变量
uint8_t sx1278_mode = MODE_STDBY;
uint8_t rx_buffer[256];
uint8_t rx_len = 0;
// SPI读写函数
static void SX1278_WriteReg(uint8_t reg, uint8_t data) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // NSS=0
uint8_t tx_buf[2] = {reg | 0x80, data}; // 写命令:最高位1
HAL_SPI_Transmit(&hspi1, tx_buf, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // NSS=1
}
static uint8_t SX1278_ReadReg(uint8_t reg) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
uint8_t tx_buf[2] = {reg, 0x00}; // 读命令:最高位0
uint8_t rx_buf[2] = {0};
HAL_SPI_TransmitReceive(&hspi1, tx_buf, rx_buf, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
return rx_buf[1];
}
初始化与参数配置:
c
// 复位SX1278
void SX1278_Reset(void) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); // RST=0
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); // RST=1
HAL_Delay(10);
}
// 初始化SX1278
uint8_t SX1278_Init(void) {
SX1278_Reset();
if (SX1278_ReadReg(REG_VERSION) != 0x12) return 0; // 检查版本号
// 配置为Lora模式
SX1278_WriteReg(REG_OP_MODE, MODE_SLEEP);
SX1278_WriteReg(REG_OP_MODE, 0x80 | MODE_SLEEP); // 进入Lora模式
HAL_Delay(10);
// 设置频率(433MHz:433e6 = 0x6C66666,Fstep=61.035Hz)
uint32_t freq = 433000000 / 61.03515625; // 0x6C6666
SX1278_WriteReg(REG_FR_MSB, (freq >> 16) & 0xFF);
SX1278_WriteReg(REG_FR_MID, (freq >> 8) & 0xFF);
SX1278_WriteReg(REG_FR_LSB, freq & 0xFF);
// 配置Lora参数:扩频因子SF=7,带宽BW=125kHz,编码率CR=4/5
SX1278_WriteReg(REG_MODEM_CONFIG1, 0x72); // BW=125kHz(0x70), CR=4/5(0x02)
SX1278_WriteReg(REG_MODEM_CONFIG2, 0x74); // SF=7(0x70), CRC使能(0x04)
// 设置PA输出功率(20dBm)
SX1278_WriteReg(REG_PA_CONFIG, 0x8F); // PA_BOOST=1, 功率=0x0F(20dBm)
// 设置同步字(0x12)
SX1278_WriteReg(REG_SYNC_WORD, 0x12);
// 设置DIO0映射(接收完成中断)
SX1278_WriteReg(REG_DIO_MAPPING1, 0x00); // DIO0=RxDone
// 进入待机模式
SX1278_SetMode(MODE_STDBY);
return 1;
}
// 设置工作模式
void SX1278_SetMode(uint8_t mode) {
SX1278_WriteReg(REG_OP_MODE, 0x80 | mode); // Lora模式+子模式
sx1278_mode = mode;
HAL_Delay(10);
}
数据发送与接收:
c
// 发送数据
void SX1278_Send(uint8_t *data, uint8_t len) {
SX1278_SetMode(MODE_STDBY);
SX1278_WriteReg(REG_FIFO_TX_BASE, 0x00); // FIFO基地址
SX1278_WriteReg(REG_FIFO_ADDR_PTR, 0x00); // 指针归零
SX1278_WriteReg(REG_PAYLOAD_LEN, len); // payload长度
// 写入FIFO
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
uint8_t tx_buf[1] = {REG_FIFO | 0x80};
HAL_SPI_Transmit(&hspi1, tx_buf, 1, 100);
HAL_SPI_Transmit(&hspi1, data, len, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
// 启动发送
SX1278_SetMode(MODE_TX);
while (SX1278_ReadReg(REG_IRQ_FLAGS) & 0x08 == 0); // 等待TxDone
SX1278_WriteReg(REG_IRQ_FLAGS, 0x08); // 清除TxDone标志
}
// 接收数据(中断触发后调用)
void SX1278_Receive(void) {
rx_len = SX1278_ReadReg(REG_RX_NB_BYTES); // 接收字节数
SX1278_WriteReg(REG_FIFO_ADDR_PTR, SX1278_ReadReg(REG_FIFO_RX_CURRENT)); // 指针指向当前数据
// 读取FIFO
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
uint8_t tx_buf[1] = {REG_FIFO};
HAL_SPI_Transmit(&hspi1, tx_buf, 1, 100);
HAL_SPI_Receive(&hspi1, rx_buffer, rx_len, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
SX1278_WriteReg(REG_IRQ_FLAGS, 0x40); // 清除RxDone标志
}
(2)主程序逻辑(main.c)
c
#include "main.h"
#include "spi.h"
#include "usart.h"
#include "sx1278.h"
#include <string.h>
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
// 初始化SX1278
if (!SX1278_Init()) {
char err[] = "SX1278 Init Failed!\r\n";
HAL_UART_Transmit(&huart1, (uint8_t*)err, strlen(err), 100);
while(1);
}
// 设置接收模式
SX1278_SetMode(MODE_RX_CONT);
char ok[] = "SX1278 Ready (Rx Mode)\r\n";
HAL_UART_Transmit(&huart1, (uint8_t*)ok, strlen(ok), 100);
while (1) {
// 主循环可添加其他任务,接收通过中断处理
HAL_Delay(1000);
}
}
// DIO0中断回调(接收完成/发送完成)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == GPIO_PIN_0) { // DIO0
uint8_t irq_flags = SX1278_ReadReg(REG_IRQ_FLAGS);
if (irq_flags & 0x40) { // RxDone
SX1278_Receive();
// 串口输出接收数据
char msg[32];
sprintf(msg, "Received: %s\r\n", rx_buffer);
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100);
} else if (irq_flags & 0x08) { // TxDone
SX1278_SetMode(MODE_RX_CONT); // 发送完成,切回接收模式
}
}
}
参考代码 lora sx1278 基于stm32程序 www.youwenfan.com/contentcss/182792.html
四、关键参数配置
| 参数 | 配置值(示例) | 说明 |
|---|---|---|
| 频率 | 433MHz(0x6C6666) | 中国ISM频段,需符合当地法规 |
| 扩频因子(SF) | 6-12(0x60-0x0C) | SF越大,距离越远,速率越低 |
| 带宽(BW) | 125kHz(0x70) | 可选7.8-500kHz |
| 编码率(CR) | 4/5(0x02) | 可选4/5、4/6、4/7、4/8 |
| 发射功率 | 20dBm(0x8F) | 最大20dBm,需PA_BOOST=1 |
五、测试与优化
1. 测试方法
-
硬件连接:按"硬件连接"表接线,确保SPI无虚焊,天线匹配;
-
调试工具:用串口助手(如XCOM)查看调试信息,用另一块SX1278模块作为接收端;
-
功能验证 :发送端调用
SX1278_Send("Hello", 5),接收端通过中断接收并打印。
2. 优化方向
-
低功耗 :空闲时进入
MODE_SLEEP,通过外部中断唤醒; -
重传机制:发送失败时(无Ack)重传3次;
-
数据校验:添加CRC16校验,提高数据可靠性;
-
多节点通信:通过地址过滤(Sync Word+Node ID)实现星型网络。
六、总结
本程序基于STM32实现了SX1278 Lora模块的基础通信功能,包括初始化、参数配置、数据收发,通过SPI驱动和中断处理确保实时性。用户可根据需求调整Lora参数(SF、BW、功率)以平衡距离与速率,适用于低功耗物联网场景。