蓝桥杯
Contents
LoRa模块概述
模块描述
工作模式
数据FIFO
HAL库LoRa编程
CubeMX配置
SPI_WriteRead
函数封装
LoRa API使用
使用示例
MCU型号:STM32L071KBU SDK:HAL库 工具:CubeMX + MDK
1 LoRa模块概述
1.1 模块描述
LoRa (Long Range , 远距离)模块收发器型号为SX1278 ,可以完成点对点的数据通信功能,属于半双工通信,其原理图与引脚描述如下图所示:
▲ Lora模块原理图
▲ Lora模块引脚描述
Lora竞赛板中引出了以下引脚:
- PA5~7:一般配置为硬件SPI通信引脚
- PA4:片选引脚,一般选择软件片选
- PA9:复位引脚,无需复位时,初始化时拉高即可
- PA10:DIO0外部中断引脚,当接收端接收到数据之后,DIO0 将触发上升沿信号,可编程在EXTI中断中处理接收数据
1.2 工作模式
SX1278 寄存器在任何模式下都可以读,但仅在睡眠和待机模式下可写。
1.3 数据FIFO
LoRa数据FIFO共256 字节,用于发送和接收数据,除睡眠模式外,其他模式下均可读写,在切换到新的接收模式时,自动清除旧内容,如下图所示:
▲ LoRa 数据FIFO
调制器用于发送数据,解调器用于接收数据
- 发送时,首先进入待机模式,将FIFO SPI 地址
FifoAddrPtr 设置为FIFO调制器基地址FifoTxBaseAddr ,将负载长度PayloadLength 设置为发送字节数,将数据写入FIFO,然后切换到发送模式,等待发送完成,发送完成后芯片自动返回到待机模式,切换到连续接收模式等待接收,如下图所示:
▲ LoRa发送流程
- 连续接收时,首先切换到接收模式,等待接收完成,接收完成后将FIFO SPI 地址
FifoAddrPtr 设置为FIFO接收开始地址FifoRxCurrentAddr ,然后从FIFO读取RxNbBytes 个字节数据,如下图所示:
▲ LoRa接收流程
芯片不同模式之间转换时FIFO 的状态:
2 HAL库LoRa编程
2.1 CubeMX配置
将PA5~7 配置为硬件SPI通信引脚:
根据官方手册给出的LoRa模块SPI通信要求配置的参数:
- 全双工通信
- SPI 主机采用模式0,CPOL=0 和CPHA=0
- 数据长度8 位,MSB 通信
- SPI 速度需要小于10M(主频32M / 4 = 8M)
此外,还需要初始化PA9 复位引脚和PA4 片选引脚,配置成通用推挽输出,将它们拉高。
将PA10 配置为外部中断触发引脚,上升沿触发:
使能EXTI4_15中断:
2.2 SPI_WriteRead函数封装
uint8_t SPI_WriteRead(uint8_t addr, uint8_t data)
{
uint8_t tx_data[2], rx_data[2];
tx_data[0] = addr;
tx_data[1] = data;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, tx_data, rx_data, 2, 10);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
return rx_data[1];
}
2.3 LoRa API使用
2.3.1 LoRa初始化
void LORA_Init(void)
{
SPI_WriteRead(0x81, 0);
SPI_WriteRead(0x81, 0x80);
SPI_WriteRead(0x81, 1);
LORA_SetRFFrequency(434);
LORA_SetRFPower(10);
SPI_WriteRead(0x9E, 7 << 4);
LORA_SetBW(7);
LORA_SetCR(1);
SPI_WriteRead(0x81, 5);
}
一般只需要设置LoRa模式(必须在睡眠模式下设置)和射频功率/频率即可,其他使用默认值。
射频功率在10mW 可提供超过25KM 视距传输。
注意:注意:LoRa模块间频率、带宽、扩频因子和前导码长度等参数相同才能通信。
2.3.2 发送数据
void LORA_Tx(unsigned char *pucBuf, unsigned char ucSize)
{
unsigned int i;
unsigned char ret;
SPI_WriteRead(0x81, 1);
ret = SPI_WriteRead(0x0E, 0);
SPI_WriteRead(0x8D, ret);
SPI_WriteRead(0xA2, ucSize);
for(i = 0; i < ucSize; i++)
SPI_WriteRead(0x80, pucBuf[i]);
SPI_WriteRead(0x81, 3);
i = 65535;
do
{
ret = SPI_WriteRead(0x12, 0);
i--;
}while(((ret & 8) == 0) && (i != 0));
SPI_WriteRead(0x92, 8);
SPI_WriteRead(0x81, 5);
}
pucBuf :指向发送数据缓冲区的指针ucSize :待发送数据的字节数(数据FIFO最大256 字节,因此单次发送数据超过256字节后的数据会被截断)
每次发送完数据后,LoRa模块都会切换到连续接收模式,等待数据的接收。
2.3.3 接收数据
unsigned char LORA_Rx(unsigned char *pucBuf)
{
unsigned char i, ret;
ret = SPI_WriteRead(0x12, 0);
if(ret & 0x40)
{
SPI_WriteRead(0x81, 1);
SPI_WriteRead(0x92, 0x40);
ret = SPI_WriteRead(0x10, 0);
SPI_WriteRead(0x8D, ret);
ret = SPI_WriteRead(0x13, 0);
for(i = 0; i < ret; i++)
pucBuf[i] = SPI_WriteRead(0, 0);
SPI_WriteRead(0x81, 5);
}
else
ret = 0;
return ret;
}
pucBuf :指向接收缓冲区的指针- 返回值:接收到的数据长度(unit:字节)
每次接收完数据后,LoRa模块都会切换到连续接收模式,继续等待数据的接收。
2.4 使用示例
按下USER按键发送数据:
uint8_t tx_data[2] = {0x12, 0x34};
uint8_t rx_data[2];
void lora_send(void)
{
LORA_Tx(tx_data, sizeof(tx_data));
}
在外部中断EXTI4_15_IRQHandler 回调函数中打印接收到的数据:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_10)
{
uint8_t data_length = LORA_Rx(rx_data);
printf("size: %d, rx1:%x, rx2:%x\r\n", data_length, rx_data[0], rx_data[1]);
}
}
实验结果:LoRa模块都能正常发送数据,且均能收到对方发送的数据。
END
|