目录
- lora简介
- 硬件设备
- 源码分析
-
- `sender`
- 两种调制方式
详细的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)misospi数据输出mosispi数据输入sckspi时钟输入nssspi片选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 << 19) / 32000000;
writeregister(reg_frf_msb, (uint8_t)(frf >> 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 < 0) {
level = 0;
} else 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
呼~写累啦,下一篇再具体介绍lora调制的具体方式
加油!ヾ(◍°∇°◍)ノ゙