基于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波形验证时序,并通过串口助手测试数据收发功能。实际部署时需根据环境调整天线位置和通信参数。

浙公网安备 33010602011771号