LoRaWAN网关与节点代码实战

LoRaWAN 网关的代码实现与解析

硬件准备

  • 单通道网关硬件通常基于树莓派+LoRa模块(如SX1276/SX1278)或专用网关板(如RAK831)。
  • 软件依赖:wiringPi(GPIO控制)、lora_gateway(基础驱动)、post-processing(数据包处理)。

关键代码模块

  1. GPIO与射频初始化
// SX1278 初始化示例(SPI通信)
int sx1278_init() {
    wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED);
    pinMode(RESET_PIN, OUTPUT);
    digitalWrite(RESET_PIN, HIGH);
    delay(100);
    // 设置LoRa模式、频率(如868MHz)
    write_reg(REG_OP_MODE, MODE_LORA | MODE_SLEEP);
    write_reg(REG_FRF_MSB, 0xD9); // 868.1 MHz
}

  1. 数据包接收处理
void receive_packet() {
    while (digitalRead(DIO0_PIN) == LOW); // 等待中断
    uint8_t payload[256];
    size_t len = read_reg(REG_RX_NB_BYTES);
    spi_read(REG_FIFO, payload, len);
    // 转发到服务器(如通过MQTT)
    mqtt_publish("gateway/uplink", payload, len);
}

  1. 下行链路发送
void send_downlink(uint8_t *data, size_t len) {
    write_reg(REG_OP_MODE, MODE_LORA | MODE_STDBY);
    write_reg(REG_FIFO_ADDR_PTR, 0x00);
    spi_write(REG_FIFO, data, len);
    write_reg(REG_OP_MODE, MODE_LORA | MODE_TX);
}


STM32L072+SX1262 节点代码实现

硬件连接

  • STM32L072通过SPI连接SX1262,DIO1用于中断,NRESET为硬件复位。

关键步骤

  1. SX1262 初始化
void SX1262_Init() {
    HAL_GPIO_WritePin(NRESET_GPIO_Port, NRESET_Pin, GPIO_PIN_RESET);
    HAL_Delay(20);
    HAL_GPIO_WritePin(NRESET_GPIO_Port, NRESET_Pin, GPIO_PIN_SET);
    // 设置LoRa参数
    SX1262_WriteCommand(RADIO_SET_PACKETTYPE, 0x01); // LoRa模式
    SX1262_WriteRegister(REG_LR_SYNCWORD, 0x34); // LoRaWAN SyncWord
}

  1. 发送数据(OTAA入网)
void send_join_request() {
    uint8_t devEui[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
    uint8_t joinEui[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    uint8_t appKey[16] = {...};
    // 构造JoinRequest
    lorawan_mac_join_request(devEui, joinEui, appKey, buffer);
    SX1262_SendBuffer(buffer, 23); // 发送23字节JoinRequest
}

  1. 接收下行数据
void handle_rx() {
    if (HAL_GPIO_ReadPin(DIO1_GPIO_Port, DIO1_Pin)) {
        uint8_t rx_len = SX1262_ReadRegister(REG_RX_PAYLOAD_LENGTH);
        SX1262_ReadBuffer(rx_buffer, rx_len);
        // 处理MAC命令(如JoinAccept)
        lorawan_process_downlink(rx_buffer, rx_len);
    }
}


LoRaWAN 网络搭建步骤

服务器配置

  1. 安装ChirpStackTTN服务器:
# ChirpStack 安装示例
docker-compose up -d postgresql redis chirpstack

  1. 配置网关:
  • 在服务器界面添加网关,填写Gateway EUI(如从硬件读取)。
  • 设置网关频率计划(如EU868)。

节点注册

  1. 创建应用(Application)并添加设备(Device)。
  2. 选择激活模式(OTAA或ABP),填写DevEUI、AppKey等参数。

频率与法律合规

  • 根据地区选择频段(如CN470、EU868),需遵守当地无线电法规。

调试与优化

网关调试

  • 使用tcpdump监控网关与服务器的通信:
sudo tcpdump -i eth0 port 1700 -vv

节点功耗优化

  • 配置STM32低功耗模式(STOP模式),SX1262进入休眠:
SX1262_WriteCommand(RADIO_SET_SLEEP, 0x01);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

通信可靠性

  • 调整SX1262的发射功率(REG_PA_CONFIG)和扩频因子(SF)。
  • 启用ADR(自适应速率)功能:
uint8_t adr_enable = 1;
lorawan_mac_command(LINK_ADR_REQ, &adr_enable, 1);

移植LoRaWAN节点代码到CH583芯片(基于RISC-V架构)需要结合CH583的硬件特性和LoRaWAN协议栈进行适配。以下是详细的移植步骤和关键代码实现:


硬件驱动层移植

SPI驱动适配
CH583的SPI控制器需配置为与LoRa射频模块(如SX1276/SX1262)通信。以下为SPI初始化代码示例:

void SPI_Init(void) {
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // 启用SPI1时钟
    GPIO_Init(GPIOA, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7, GPIO_Mode_AF_PP); // SCK/MOSI/MISO
    SPI1->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR; // 主模式,软件NSS
    SPI1->CR1 |= SPI_CR1_SPE; // 使能SPI
}

射频模块控制引脚
需实现Reset、NSS、DIO0等引脚的控制:

#define RF_NSS_PIN    GPIO_Pin_4
#define RF_RESET_PIN  GPIO_Pin_3

void RF_GPIO_Init(void) {
    GPIO_Init(GPIOB, RF_NSS_PIN, GPIO_Mode_Out_PP); // NSS引脚
    GPIO_Init(GPIOA, RF_RESET_PIN, GPIO_Mode_Out_PP); // Reset引脚
    GPIO_SetBits(GPIOB, RF_NSS_PIN); // 初始置高
}


定时器适配

LoRaWAN协议栈依赖精确计时
CH583的定时器需配置为毫秒级 tick:

void Timer_Init(void) {
    SysTick_Config(SystemCoreClock / 1000); // 1ms中断
}

uint32_t HAL_GetTick(void) {
    return systick_counter; // 全局变量记录tick
}


协议栈移植

Radio接口实现
需重写LoRaMAC层的Radio接口函数:

RadioEvents_t RadioEvents;

void Radio_Init(void) {
    RadioEvents.TxDone = OnTxDone;
    Radio.Init(&RadioEvents);
}

void OnTxDone(void) {
    LoRaMacMcpsConfirm(); // 通知协议栈发送完成
}

低功耗管理
CH583支持低功耗模式,需适配LoRaWAN的休眠逻辑:

void BoardLowPowerHandler(void) {
    __WFI(); // 进入待机模式
}


示例主循环

任务调度与事件处理
主循环需整合协议栈任务和硬件事件:

int main(void) {
    HardwareInit();
    LoRaMacInitialization();
    
    while(1) {
        LoRaMacProcess(); // 处理协议栈任务
        HandleRadioIrq(); // 处理射频中断
        if (IsJoinRequestNeeded()) {
            LoRaMacMcpsRequest(&join_request);
        }
    }
}


注意事项

  1. 时钟配置
    CH583需配置外部高速时钟(HSE)以确保SPI和定时器精度。

  2. 中断优先级
    射频模块的DIO0中断需设置为较高优先级,避免丢包。

  3. 内存管理
    LoRaWAN协议栈可能动态分配内存,需检查CH583的堆空间是否充足。

  4. 认证与加密
    确保加密算法(如AES)在RISC-V架构上的运行效率,必要时使用硬件加速。

完整代码需结合具体LoRaWAN协议栈(如Semtech或LoRaMAC-node)的API实现。移植后需通过OTAA或ABP入网测试验证功能。

LoRaWAN 单通道网关架构概述

基于 CH583 MCUSX1262 LoRa模块 的LoRaWAN单通道网关架构采用简化设计,适合低功耗、低成本场景。网关通过单频点接收节点数据,并通过以太网/WiFi转发至LoRaWAN服务器(如ChirpStack)。节点采用ABP(激活By Personalization)模式入网,直接与网关通信。


网关端实现

硬件连接
  • SX1262CH583 通过SPI通信,引脚配置如下:
    • SCK: GPIO_PIN_13
    • MISO: GPIO_PIN_14
    • MOSI: GPIO_PIN_15
    • NSS: GPIO_PIN_16
    • RESET: GPIO_PIN_17
    • BUSY: GPIO_PIN_18
代码实现(基于Arduino库适配)
#include <SPI.h>  
#include <LoRa.h>  // 需适配SX1262驱动  

#define LORA_FREQ 868000000  // 欧洲频段  

void setup() {  
  Serial.begin(115200);  
  SPI.begin();  
  LoRa.setPins(16, 17, 18);  // NSS, RESET, BUSY  
  if (!LoRa.begin(LORA_FREQ)) {  
    Serial.println("LoRa init failed!");  
    while (1);  
  }  
  LoRa.setSpreadingFactor(7);  // SF7  
  LoRa.enableCrc();  
}  

void loop() {  
  int packetSize = LoRa.parsePacket();  
  if (packetSize) {  
    char packet[256];  
    int i = 0;  
    while (LoRa.available()) {  
      packet[i++] = (char)LoRa.read();  
    }  
    packet[i] = '\0';  
    Serial.println("Received: " + String(packet));  
    // 转发至服务器(伪代码)  
    sendToServer(packet);  
  }  
}  

服务器通信

网关通过HTTP/MQTT将数据转发至LoRaWAN服务器。示例使用HTTP POST:

void sendToServer(String data) {  
  WiFiClient client;  
  HTTPClient http;  
  http.begin(client, "http://chirpstack.example.com/api/gateways/upload");  
  http.addHeader("Content-Type", "application/json");  
  String json = "{\"data\":\"" + data + "\"}";  
  int code = http.POST(json);  
  http.end();  
}  


节点端实现

硬件连接

节点硬件与网关类似,需额外配置 ABP参数(DevAddr/NwkSKey/AppSKey)。

代码实现
#include <LoRa.h>  

// ABP参数  
const uint32_t devAddr = 0x260BABCD;  
const uint8_t nwkSKey[16] = {0x01, 0x02, ...};  
const uint8_t appSKey[16] = {0x01, 0x02, ...};  

void setup() {  
  LoRa.setPins(16, 17, 18);  
  if (!LoRa.begin(868E6)) {  
    Serial.println("LoRa init failed!");  
    while (1);  
  }  
  LoRa.setTxPower(20);  
}  

void loop() {  
  String message = "Hello, Gateway!";  
  LoRa.beginPacket();  
  LoRa.write((uint8_t*)&devAddr, 4);  // 添加DevAddr  
  LoRa.print(message);  
  LoRa.endPacket();  
  delay(5000);  
}  

数据加密

节点需使用 LoRaMAC-Node 库实现完整LoRaWAN协议栈。关键加密函数:

void encryptPayload(uint8_t* payload, uint8_t size) {  
  AES_CMAC(nwkSKey, payload, size, encryptedPayload);  
}  


调试与优化

  1. 频谱扫描:使用 LoRa.scanNetworks() 确认频段无冲突。
  2. 功耗测试:节点进入低功耗模式(LoRa.sleep()),CH583配置为休眠模式。
  3. 服务器对接:验证ChirpStack的Gateway Profile配置为单通道模式。

注意事项

  • 单通道网关仅支持 单一频点,需与服务器频段配置一致。
  • ABP模式需手动管理 帧计数器(FCnt),避免重复攻击。
  • 实际部署需通过 MIC校验(Message Integrity Code)确保数据安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值