基于STM32的Lora SX1278程序设计与实现

一、系统概述

本方案基于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、功率)以平衡距离与速率,适用于低功耗物联网场景。

相关推荐
永霖光电_UVLED6 小时前
意法半导体:华虹40nm代工生产的STM32 MCU开启交付
stm32·单片机·嵌入式硬件
冲,干,闯7 小时前
LVGL_按钮部件(LV_btn)
单片机
Zevalin爱灰灰8 小时前
零基础入门学用物联网(ESP8266) 第一部分 基础知识篇(六)
单片机·物联网·嵌入式·esp8266
爱喝纯牛奶的柠檬9 小时前
STM32红外遥控解码,NEC协议驱动
单片机·嵌入式硬件
羽获飞9 小时前
从零开始学嵌入式之STM32——30.使用触发输入和从模式测量PWM信号的占空比
stm32·单片机·嵌入式硬件
技术民工之路9 小时前
Keil MDK 5.40:STM32 工程编译 + 调试完整教程
stm32·单片机·嵌入式硬件
小马学嵌入式~10 小时前
linux开发深度学习-时钟
linux·arm开发·嵌入式硬件·学习
LCG元11 小时前
STM32嵌入式开发:基于STM32F103的智能语音识别系统
stm32·嵌入式硬件·语音识别
项目題供诗11 小时前
51单片机入门-直流电机(十四)
单片机·嵌入式硬件·51单片机