蓝桥杯物联网设计与开发基础模块7-Lora
目录
一、Lora
(1)资源介绍
🔅Lora 特点:
🔅SX1278 介绍:
🔅SX1278 工作方式:
🔅原理图:
(2)STM32CubeMX 软件配置
(3)代码编写
(4)实验现象
二、踩坑日记
(1)引脚配置
一、Lora
(1)资源介绍
Lora 是属于线性调制扩频技术的一种,用于创建长距离通信连接的物理层无线调制技术,它在保留传统无线系统所使用的频移键控(FSK)调制的低功耗特性的基础上,增加了通信的距离。Lora 扩频技术就是通过注入一个更高频信号将基带信号扩展到更宽的频带,使得其传输信息所用信号的带宽远大于信息本身的带宽。
🔅Lora 特点:
- 传输距离远:2km ~ 20km,速度越低,传输距离越长;
- 低功耗:解决功耗于传输距离难覆盖的问题;
- 成本低:具有容量大的特点,可以节省模块及布线成本;
- 灵敏度高:在相同数据速率下,它的扩频调制技术的灵敏度比传统的频移键控(FSK)调制方式高 8 ~ 10dB;
- 调制方式先进:基于扩频技术,采用直接序列扩频,具有前向纠错(FEC)的能力;
- 抗干扰能力强:对于同频干扰及各种噪声的干扰具有较强的抑制能力;
- 发射功率密度低:不易对其它设备造成干扰;
- 保密性高:被截获的可能性极低,采用 AES128 加密;
- 具有极好的抗多径衰落和多普勒效应性能:在城市中多径效应很明显,信号会因为多径叠加导致严重失真,移动的物体会带来多普勒效应,对无线接收端带来了很大的挑战,而 Lora 通信就能很好的克服这两点;
🔅SX1278 介绍:
物联网竞赛实训平台上继承了一个 SPI 接口的 Lora 模块,收发器型号为 SX1278,SX1278 是一个半双工传输的低中频收发器,由射频前端(包括低噪声放大器 LNA 和功率放大器 PA 等)、上下变频、Lora 和 FSK / OOK 调制解调器,数据 FIFO、寄存器和 SPI 接口等部分组成;
SX1278 收发数据前,需要通过 SPI 接口对寄存器进行配置。寄存器在任何模式下都可以读,但仅在睡眠和待机模式下可写:
🔅SX1278 工作方式:
Lora 的初始化包括设置 Lora 模式(必须在睡眠模式下设置)、设置射频频率和功率、设置扩频因子、信号带宽和纠错编码率等。除了必须设置 Lora 模式和射频功率外,其它设置都可以省略(使用默认值);
Lora 数据 FIFO 的 256 字节可完全由用户定制,用于发送或接收数据。除睡眠模式外,其它模式下均可读写,在切换到新的接收模式时,自动清除旧内容;

🔅原理图:

查看局部射频收发模块原理图可知,MCU 与 SX1278 通过引脚 PA5、PA6、PA7、PA4 进行数据交互传输,而这四个引脚的第二功能为 MCU 的硬件 SPI1;SX1278 复位引脚 NRESET(复位触发输入,低电平有效)与 PA9 相连接,数字 IO 引脚 DIO0 引脚与 PA10 相连接;

(2)STM32CubeMX 软件配置
🔅“工程建立、时钟树配置、Debug 串行线配置、代码生成配置” 在下文中有讲解,这里不再赘述❗️
【蓝桥杯——物联网设计与开发】基础模块1- GPIO输出https://blog.csdn.net/m0_63116406/article/details/135604705?spm=1001.2014.3001.5502
1️⃣点击引脚 PC15 → 选择 GPIO_Output 模式(此处默认为推挽输出);

2️⃣点击 "GPIO" → 点击引脚 PC15 → 将 "GPIO output level" 栏修改为 "High",即将 PC15 引脚初始化为高电平;
⚠️此处修改不是必须的,应当根据题意要求进行配置,这里默认为上电熄灭;

3️⃣点击左侧 "Connectivity" → 选择 "SPI1" → 模式选择 "Full-Duplex Master" (全双工主机模式),不使能 "Hardware NSS Signal"(硬件片选信号);

4️⃣点击引脚 PA4 → 选择 GPIO_Output 模式;

5️⃣点击引脚 PA9 → 选择 GPIO_Output 模式;

6️⃣点击引脚 PA10 → 选择 GPIO_Input 模式;

7️⃣生成代码即可;
8️⃣将赛点资源数据包中的参考代码:"lora.h"、"lora.c"添加到工程;

(3)代码编写
🟡️MX_SPI1_Init 函数代码补全
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
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_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 拉高 PA4,取消片选
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET); // 拉高 PA9,防止触发收发模块复位
/* USER CODE END SPI1_Init 2 */
}
🟡️SPI_WriteRead 函数代码实现
unsigned char SPI_WriteRead(unsigned char ucAddr, unsigned char ucData)
{
uint8_t pTxData[2], pRxData[2];
pTxData[0] = ucAddr;
pTxData[1] = ucData;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 片选收发模块
HAL_SPI_TransmitReceive(&hspi1, pTxData, pRxData, 2, 10); // SPI 发送接收
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 取消片选
return pRxData[1];
}
🟢️NODE_A main 函数
/* USER CODE BEGIN Includes */
#include "lora.h"
#include "string.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
uint8_t puc_lora[10];
/* USER CODE END PV */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
LORA_Init(); // 初始化 Lora 模块
puc_lora[0] = '*';
puc_lora[1] = 'A';
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
LORA_Tx(puc_lora, 2); // 发送字符串
HAL_Delay(1000); // 间隔 1s
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
🟢️NODE_B main 函数
/* USER CODE BEGIN Includes */
#include "lora.h"
#include "string.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
uint8_t puc_lora[10];
/* USER CODE END PV */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
LORA_Init(); // 初始化 Lora 模块
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(LORA_Rx(puc_lora) == 2) // Lora 接收
{
if(strcmp((char *)puc_lora, "*A") == 0) // 比较字符串
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_15); // 翻转 LED 电平
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
(4)实验现象
节点 B,每间隔 1s,LED 电平翻转一次;
二、踩坑日记
(1)引脚配置
作者:逝灮