基于STM32F103与LoRa模块实现无线通信

基于STM32F103与LoRa模块(以SX1278为例)实现无线通信


一、硬件连接方案

1. 接口映射

STM32引脚 SX1278引脚 功能说明
PA4 (NSS) NSS SPI片选信号
PA5 (SCK) SCK SPI时钟
PA6 (MISO) MISO SPI主入从出
PA7 (MOSI) MOSI SPI主出从入
PB0 (RST) RESET 模块复位
PB1 (DIO0) DIO0 中断信号

2. 电路设计要点

  • 电源滤波:在3.3V和GND间添加10μF电解电容+0.1μF陶瓷电容
  • 信号保护:在SPI总线和DIO0引脚串联1kΩ电阻
  • 天线匹配:连接50Ω阻抗天线,建议使用外置螺旋天线

二、软件开发环境

1. 开发工具链

  • IDE:STM32CubeIDE (基于Keil MDK)
  • HAL库版本:V1.8.3
  • LoRa驱动库:Semtech SX127x驱动V4.4.2

2. 关键配置

// 在CubeMX中配置:
- SPI1: 主模式,时钟频率32MHz,数据格式8bit
- GPIO: PA4为GPIO_Output(NSS手动控制)
- EXTI: PB1配置为外部中断(上升沿触发)

三、驱动代码实现

1. SPI底层驱动

// SPI初始化(CubeMX生成)
void MX_SPI1_Init(void)
{
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  HAL_SPI_Init(&hspi1);
}

// SPI读写函数
uint8_t SPI_Transfer(uint8_t *txData, uint8_t *rxData, uint16_t len)
{
  HAL_SPI_TransmitReceive(&hspi1, txData, rxData, len, 1000);
  return HAL_SPI_GetState(&hspi1);
}

2. LoRa模块初始化

#define SX1278_RST_PIN    PB0
#define SX1278_DIO0_PIN   PB1

// 硬件复位
void SX1278_Reset(void)
{
  HAL_GPIO_WritePin(GPIOB, SX1278_RST_PIN, GPIO_PIN_RESET);
  HAL_Delay(10);
  HAL_GPIO_WritePin(GPIOB, SX1278_RST_PIN, GPIO_PIN_SET);
  HAL_Delay(100);
}

// 寄存器操作
void SX1278_WriteReg(uint8_t addr, uint8_t data)
{
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 拉低NSS
  SPI_Transfer(&addr, NULL, 1);
  SPI_Transfer(&data, NULL, 1);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 释放NSS
}

uint8_t SX1278_ReadReg(uint8_t addr)
{
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
  SPI_Transfer(&addr, NULL, 1);
  uint8_t data;
  SPI_Transfer(&data, NULL, 1);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
  return data;
}

// 初始化流程
void SX1278_Init(void)
{
  SX1278_Reset();
  
  // 设置频率433MHz
  SX1278_WriteReg(REG_FRF_MSB, 0x6C);
  SX1278_WriteReg(REG_FRF_MID, 0x80);
  SX1278_WriteReg(REG_FRF_LSB, 0x00);
  
  // 配置扩频因子SF12,带宽125kHz
  SX1278_WriteReg(REG_MODEM_CONFIG_2, 0x74); // SF12, BW125kHz
  SX1278_WriteReg(REG_MODEM_CONFIG_1, 0x0A); // 编码率4/5
  
  // 设置发射功率20dBm
  SX1278_WriteReg(REG_PA_CONFIG, 0x81);
}

四、数据收发实现

1. 发送数据

void LoRa_SendPacket(uint8_t *data, uint8_t len)
{
  // 进入待机模式
  SX1278_WriteReg(REG_OP_MODE, 0x01); // STDBY
  
  // 配置FIFO
  SX1278_WriteReg(REG_FIFO_ADDR_PTR, 0x00);
  SX1278_WriteReg(REG_PAYLOAD_LENGTH, len);
  
  // 写入数据
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
  SPI_Transfer(REG_FIFO, data, len);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
  
  // 进入发射模式
  SX1278_WriteReg(REG_OP_MODE, 0x03); // TX
  while((SX1278_ReadReg(REG_IRQ_FLAGS) & 0x08) == 0); // 等待发送完成
}

2. 接收数据(中断方式)

volatile uint8_t rxBuffer[256];
volatile uint8_t rxCount = 0;

// EXTI中断服务函数
void EXTI0_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_LINE0) != RESET)
  {
    HAL_GPIO_EXTI_Callback(GPIO_PIN_0);
    
    // 读取数据长度
    uint8_t irqFlags = SX1278_ReadReg(REG_IRQ_FLAGS);
    uint8_t len = SX1278_ReadReg(REG_PAYLOAD_LENGTH);
    
    // 读取FIFO数据
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    SPI_Transfer(REG_FIFO, rxBuffer, len);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    
    rxCount = len;
    SX1278_ClearIRQFlags(0x04); // 清除RXDONE标志
  }
}

// 接收回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == GPIO_PIN_0)
  {
    // 处理接收到的数据
    printf("Received data: ");
    for(int i=0; i<rxCount; i++) printf("%02X ", rxBuffer[i]);
    printf("\r\n");
  }
}

五、关键参数配置

1. 通信参数设置

// 设置扩频因子
void SX1278_SetSF(uint8_t sf)
{
  uint8_t val = SX1278_ReadReg(REG_MODEM_CONFIG_2);
  val = (val & 0x0F) | (sf << 4);
  SX1278_WriteReg(REG_MODEM_CONFIG_2, val);
}

// 设置带宽
void SX1278_SetBW(uint8_t bw)
{
  uint8_t val = SX1278_ReadReg(REG_MODEM_CONFIG_1);
  val = (val & 0xF0) | (bw & 0x0F);
  SX1278_WriteReg(REG_MODEM_CONFIG_1, val);
}

2. 错误处理机制

// CRC校验
uint8_t CheckCRC(uint8_t *data, uint8_t len)
{
  uint8_t crc = 0x00;
  for(int i=0; i<len; i++) {
    crc ^= data[i];
    for(int j=0; j<8; j++) {
      crc = (crc & 0x80) ? (crc << 1) ^ 0x31 : crc << 1;
    }
  }
  return crc;
}

// 自动重传机制
void AutoResend(uint8_t *data, uint8_t len, uint8_t maxRetry)
{
  uint8_t retry = 0;
  while(retry < maxRetry) {
    LoRa_SendPacket(data, len);
    HAL_Delay(1000); // 等待ACK
    
    if(CheckACK()) {
      return; // 发送成功
    }
    retry++;
  }
  printf("发送失败,重试次数:%d\r\n", retry);
}

六、调试与优化

1. 信号质量检测

// 获取RSSI值
int8_t GetRSSI(void)
{
  SX1278_WriteReg(REG_IRQ_FLAGS, 0x80); // 清除RSSI标志
  while((SX1278_ReadReg(REG_IRQ_FLAGS) & 0x80) == 0);
  return -127 + (SX1278_ReadReg(REG_RSSI_WIDEBAND) >> 1);
}

// 信号强度指示
void ShowSignalStrength(void)
{
  printf("RSSI: %ddBm, SNR: %d\r\n", GetRSSI(), GetSNR());
}

2. 动态参数调整

// 根据距离自动调整参数
void AutoAdjustParameters(float distance)
{
  if(distance > 5000) { // 5km以上
    SX1278_SetSF(12);
    SX1278_SetBW(62500); // 62.5kHz
  } else if(distance > 2000) {
    SX1278_SetSF(10);
    SX1278_SetBW(125000);
  } else {
    SX1278_SetSF(7);
    SX1278_SetBW(500000);
  }
}

七、完整工程结构

LoRa_Demo/
├── Core/
│   ├── Inc/
│   │   ├── main.h
│   │   ├── spi.h
│   │   └── lora.h
│   └── Src/
│       ├── main.c
│       ├── spi.c
│       └── lora.c
├── Drivers/
│   ├── CMSIS/
│   └── STM32F1xx_HAL_Driver/
└── Middlewares/
    └── LoRa_Driver/
        ├── sx1276.c
        └── sx1276.h

参考代码 STM32F103配合lora通讯 www.youwenfan.com/contentcnk/70072.html

八、常见问题解决

现象 解决方案 参考来源
无法进入接收模式 检查DIO0中断配置是否正确
数据包丢失 增加CRC校验和重传机制
通信距离短 调整扩频因子和发射功率
功耗过高 优化休眠模式唤醒策略

九、扩展功能实现

1. 点对多点通信

// 多节点地址配置
#define NODE1_ADDR 0x01
#define NODE2_ADDR 0x02

// 广播发送
void BroadcastMessage(uint8_t *data, uint8_t len)
{
  SX1278_WriteReg(REG_NODE_ADDR, 0x00); // 广播地址
  LoRa_SendPacket(data, len);
}

// 定向发送
void DirectedSend(uint8_t addr, uint8_t *data, uint8_t len)
{
  SX1278_WriteReg(REG_NODE_ADDR, addr);
  LoRa_SendPacket(data, len);
}

2. 加密通信

// AES加密配置
void EnableEncryption(uint8_t *key)
{
  SX1278_WriteReg(REG_CRYPTO_KEY_0, key[0]);
  SX1278_WriteReg(REG_CRYPTO_KEY_1, key[1]);
  SX1278_WriteReg(REG_CRYPTO_KEY_2, key[2]);
  SX1278_WriteReg(REG_CRYPTO_KEY_3, key[3]);
  SX1278_WriteReg(REG_CRYPTO_KEY_4, key[4]);
  SX1278_WriteReg(REG_CRYPTO_KEY_5, key[5]);
  SX1278_WriteReg(REG_CRYPTO_KEY_6, key[6]);
  SX1278_WriteReg(REG_CRYPTO_KEY_7, key[7]);
}

// 加密数据发送
void SendEncrypted(uint8_t *data, uint8_t len)
{
  uint8_t encrypted[256];
  AES_Encrypt(data, encrypted, len, key);
  LoRa_SendPacket(encrypted, len);
}

通过上述方案,可实现STM32F103与LoRa模块的稳定通信。建议使用逻辑分析仪捕获SPI波形验证时序,并通过串口助手测试数据收发功能。实际部署时需根据环境调整天线位置和通信参数。

posted @ 2025-10-30 16:15  躲雨小伙  阅读(13)  评论(0)    收藏  举报