详细的LoRaWAN协议解析在这里
本文主要介绍LoRa在Arduino上的实现过程,从而学习LoRa协议的实现。
硬件设备
包括传统的GFSK调制技术以及LoRa(远程)扩频技术
这里说一下啥叫LoRa扩频技术
扩频通信的基本思想:根据香农公式**C = W * log2(1 + S / N)
**,为了提高信号的传输速率C,可以增加带宽W或者提高信噪比S/N,即当传输速率一定时,带宽与信噪比可以互换。扩频通信就是用带宽换信噪比。
LoRa目前主要在ISM频段运行,包括433、868、915MHz等。LoRa的优势在于长距离能力,单个网关或基站可以覆盖数百平方公里范围
管脚定义
PIN | 描述 |
---|---|
GND | 信号地 |
DIO(1/2/3/4/5/6) | 数字IO,可自定义 |
VCC | 电源(1.8V~3.6V) |
MISO | SPI数据输出 |
MOSI | SPI数据输入 |
SCK | SPI时钟输入 |
NSS | SPI片选 |
ANT | 天线接口 |
Sender
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("LoRa Sender");
if (!LoRa.begin(915E6)) {
Serial.println("Starting LoRa failed!");
while (1);
}
}
核心初始化设置为:LoRa.begin
函数声明:
int begin(long frequency);
接收的参数为频率,也就是说上述发送的频率为915E6
,595430(十进制)
具体操作在这里:
int LoRaClass::begin(long frequency)
{
#if defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310)
pinMode(LORA_IRQ_DUMB, OUTPUT);
digitalWrite(LORA_IRQ_DUMB, LOW);
// Hardware reset
pinMode(LORA_BOOT0, OUTPUT);
digitalWrite(LORA_BOOT0, LOW);
pinMode(LORA_RESET, OUTPUT);
digitalWrite(LORA_RESET, HIGH);
delay(200);
digitalWrite(LORA_RESET, LOW);
delay(200);
digitalWrite(LORA_RESET, HIGH);
delay(50);
#endif
// setup pins
pinMode(_ss, OUTPUT);
// set SS high
digitalWrite(_ss, HIGH);
if (_reset != -1) {
pinMode(_reset, OUTPUT);
// perform reset
digitalWrite(_reset, LOW);
delay(10);
digitalWrite(_reset, HIGH);
delay(10);
}
// start SPI
_spi->begin();
// check version
uint8_t version = readRegister(REG_VERSION);
if (version != 0x12) {
return 0;
}
// put in sleep mode
sleep();
// set frequency
setFrequency(frequency);
// set base addresses
writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
// set LNA boost
writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03);
// set auto AGC
writeRegister(REG_MODEM_CONFIG_3, 0x04);
// set output power to 17 dBm
setTxPower(17);
// put in standby mode
idle();
return 1;
}
下面逐步分析这个初始化函数都干了些神马
检测是否定义了ARDUINO_SAMD_MKRWAN1300
:
这是一个内置了LoRa功能的Arduino开发板
管脚设置
第一步:将_ss
设置为输出,找到这个变量定义的是
_ss(LORA_DEFAULT_SS_PIN)
...
#define LORA_DEFAULT_SS_PIN LORA_IRQ_DUMB
也就是用作LoRa的中断引脚
下一步将这个_ss
管脚置高,也就是输出高电平
第二步:如果复位引脚不等于-1,就将复位引脚置为输出,并且输出一个10us的脉冲
#define LORA_DEFAULT_RESET_PIN -1
......
_reset(LORA_DEFAULT_RESET_PIN)
第三步:开启SPI
#define LORA_DEFAULT_SPI SPI
.......
_spi(&LORA_DEFAULT_SPI)
第四步:读取版本信息
uint8_t LoRaClass::readRegister(uint8_t address){
return singleTransfer(address & 0x7f, 0x00);
}
这个函数只是简单的调用了一下singleTransfer()
这个函数,该函数的定义就在下面
uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value)
{
uint8_t response;
digitalWrite(_ss, LOW); // 使能从机
_spi->beginTransaction(_spiSettings);
_spi->transfer(address);
response = _spi->transfer(value);
_spi->endTransaction();
digitalWrite(_ss, HIGH); // 复位从机
return response;
}
首先_spiSettings
是配置
_spiSettings(LORA_DEFAULT_SPI_FREQUENCY, MSBFIRST, SPI_MODE0),
默认的SPI频率为:
#define LORA_DEFAULT_SPI_FREQUENCY 8E6 // 2278
第二个参数MSBFIRST
表示dataOrder,只有两种选项,另一种是LSBFIRST
,分别是Most Significant Bit(ADDR[31:0]
),和Lest Significant Bit(ADDR[0:31]
)
第三个参数SPI_MODE0
表示dataMode,可选SPI_MODE0, SPI_MODE1, SPI_MODE2, or SPI_MODE3
除了频率,SPI传输需要设置Clock polarity and phase(CPOL & CPHA)
CPOL=0
:时钟空闲时候电平为低电平(SCLK有效为高)
CPOL=1
:时钟空闲时候电平为高电平(SCLK有效为低)
CPHA=0
:第一个边沿采样
CPHA=1
:第二个边沿采样
_spi->transfer(address);
SPI传输基于同时发送与接收,主机传送字节,并返回从从机接收的字节
而version的信息位于:
也就是判断所用的LoRa模块必须是SX12系列的
第五步:设置睡眠模式
void LoRaClass::sleep()
{
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
}
用到的参数:
#define REG_OP_MODE 0x01
#define MODE_LONG_RANGE_MODE 0x80
#define MODE_SLEEP 0x00
void LoRaClass::writeRegister(uint8_t address, uint8_t value)
{
singleTransfer(address | 0x80, value);
}
注意读取寄存器,用的是address & 0x7f
,而写寄存器用的是address | 0x80
。
第六步:设置频率
void LoRaClass::setFrequency(long frequency)
{
_frequency = frequency;
uint64_t frf = ((uint64_t)frequency <> 16));
writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
}
首先为什么要左移19位
#define REG_FRF_MSB 0x06
#define REG_FRF_MID 0x07
#define REG_FRF_LSB 0x08
第七步:写TX与RX FIFO
SX12系列配备了一个256字节的RAM作为数据缓存区,仅在LoRa模式下可用,对其的所用访问都要都过SPI接口完成,可以在除睡眠模式之外的所有模式下访问FIFO,会自动清除旧的内容。
第八步:设置前端的低噪放
这里是读取原来LNA寄存器中的值,将此值与'b00000011
做或运算,然后再写回去。可以看到一定取得最后两位表示LnaBoostHf
SX1276/77/78 feature three distinct RF power amplifiers. Two of those, connected to RFO_LF and RFO_HF, can deliver up to +14 dBm, are unregulated for high power efficiency and can be connected directly to their respective RF receiver inputs via a pair of passive components to form a single antenna port high efficiency transceiver. The third PA, connected to the PA_BOOST pin and can deliver up to +20 dBm via a dedicated matching network. Unlike the high efficiency PAs, this high-stability PA covers all frequency bands that the frequency synthesizer addresses.
SX12系列包括三个不同的RF功率放大器,其中两个连接到RFO_LF and RFO_HF,可以提供高达+14dBm的功率,并且无需调节,第三个连接到PA_BOOST 引脚,可以通过专用匹配网络,获得高达+20dBm的功率
第九步:设置自动增益放大器
#define REG_MODEM_CONFIG_3 0x26
第十步:设置发射功率
void LoRaClass::setTxPower(int level, int outputPin)
{
if (PA_OUTPUT_RFO_PIN == outputPin) {
// RFO
if (level 14) {
level = 14;
}
writeRegister(REG_PA_CONFIG, 0x70 | level);
} else {
// PA BOOST
if (level > 17) {
if (level > 20) {
level = 20;
}
// subtract 3 from level, so 18 - 20 maps to 15 - 17
level -= 3;
// High Power +20 dBm Operation (Semtech SX1276/77/78/79 5.4.3.)
writeRegister(REG_PA_DAC, 0x87);
setOCP(140);
} else {
if (level < 2) {
level = 2;
}
//Default value PA_HF/LF or +17dBm
writeRegister(REG_PA_DAC, 0x84);
setOCP(100);
}
writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2));
}
}
最后一步:设置为空闲模式,等待发送操作
#define PA_OUTPUT_RFO_PIN 0
#define PA_OUTPUT_PA_BOOST_PIN 1
void LoRaClass::idle()
{
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
}
两种调制方式
LoRa