MCU型号:
STM32L071KBU
SDK:HAL库
工具:CubeMX + MDK
1 LoRa模块概述
1.1 模块描述
LoRa (Long Range
, 远距离)模块收发器型号为SX1278
,可以完成点对点的数据通信功能,属于半双工通信,其原理图与引脚描述如下图所示:
Lora竞赛板中引出了以下引脚:
- PA5~7:一般配置为硬件SPI通信引脚
- PA4:片选引脚,一般选择软件片选
- PA9:复位引脚,无需复位时,初始化时拉高即可
- PA10:DIO0外部中断引脚,当接收端接收到数据之后,DIO0 将触发上升沿信号,可编程在EXTI中断中处理接收数据
1.2 工作模式
SX1278
寄存器在任何模式下都可以读,但仅在睡眠和待机模式下可写。
1.3 数据FIFO
LoRa数据FIFO共256
字节,用于发送和接收数据,除睡眠模式外,其他模式下均可读写,在切换到新的接收模式时,自动清除旧内容,如下图所示:
调制器用于发送数据,解调器用于接收数据
- 发送时,首先进入待机模式,将FIFO SPI 地址
FifoAddrPtr
设置为FIFO调制器基地址FifoTxBaseAddr
,将负载长度PayloadLength
设置为发送字节数,将数据写入FIFO,然后切换到发送模式,等待发送完成,发送完成后芯片自动返回到待机模式,切换到连续接收模式等待接收,如下图所示:
- 连续接收时,首先切换到接收模式,等待接收完成,接收完成后将FIFO SPI 地址
FifoAddrPtr
设置为FIFO接收开始地址FifoRxCurrentAddr
,然后从FIFO读取RxNbBytes
个字节数据,如下图所示:
芯片不同模式之间转换时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); /* 设置LoRa模式 */
SPI_WriteRead(0x81, 1); /* 设置待机模式 */
LORA_SetRFFrequency(434); /* 设置射频频率(137~525MHz) */
LORA_SetRFPower(10); /* 设置射频功率(2~20dBm) */
SPI_WriteRead(0x9E, 7 << 4); /* 设置扩频因子(7~12) */
LORA_SetBW(7); /* 设置信号带宽(0~9) */
LORA_SetCR(1); /* 设置纠错编码率(1~4) */
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); /* 读取FifoTxBaseAddr */
SPI_WriteRead(0x8D, ret); /* 设置FifoAddrPtr */
SPI_WriteRead(0xA2, ucSize); /* 设置PayloadLength */
for(i = 0; i < ucSize; i++) /* 写数据到FIFO */
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); /* 读取FifoRxCurrentAddr */
SPI_WriteRead(0x8D, ret); /* 设置FifoAddrPtr */
ret = SPI_WriteRead(0x13, 0); /* 读取RxNbBytes */
for(i = 0; i < ret; i++)
pucBuf[i] = SPI_WriteRead(0, 0);/* 从FIFO读数据 */
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