Skip to content

LoRa 模块的驱动方法

1. 概述

LoRa 模块是一种低功耗、长距离的无线通信模块,它基于 LoRa 协议,具有低功耗、长距离、抗干扰等特点,广泛应用于物联网、智能电网、智能交通等领域。选择的lora模块使用的是芯片是: llcc68 , 此芯片是基于sx1268 的,所以使用的是sx1268的驱动代码的基础上进行修改的。

2. LoRa 模块的驱动代码

  1. Lora模块的驱动: 下载 llcc68_driver: llcc68的驱动代码. 放入项目中的某个目录

  2. 修改接口驱动,完成移植: 在驱动源码中,有文件 sx126x-board.csx126x-board.h , 这两个文件是接口驱动,需要根据实际硬件进行修改.

  3. 在项目中再添加两个文件: lora.clora.h , 这两个文件是Lora模块的封装,用于简化使用.

(1). lora.c的源文件

c

#include "FreeRTOS.h"
#include "main.h"
#include "stm32f1xx_hal_gpio.h"
#include "stm32f1xx_hal_uart.h"
#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>
#include "task.h"
#include "string.h"
#include "radio.h"
#include "lora.h"


// 这是define
#define USE_MODEM_LORA
#define REGION_CN779
// #define RF_FREQUENCY 433000000 // Hz
#define RF_FREQUENCY 420000000 // 起始值420M
#define TX_OUTPUT_POWER 22

#define LORA_BANDWIDTH 0        // [0: 125 kHz,
                                //  1: 250 kHz,
                                //  2: 500 kHz,
                                //  3: Reserved]
#define LORA_SPREADING_FACTOR 9 // [SF7..SF12]
#define LORA_CODINGRATE 4       // [1: 4/5,
                                //  2: 4/6,
                                //  3: 4/7,
                                //  4: 4/8]
#define LORA_PREAMBLE_LENGTH 8  // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0   // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON 0
#define LORA_IQ_INVERSION_ON 0

// #define RX_TIMEOUT_VALUE 1000
#define RX_TIMEOUT_VALUE 0
#define BUFFER_SIZE 64 // Define the payload size here
// uint8_t TX_Buffer[BUFFER_SIZE];
// uint8_t RX_Buffer[BUFFER_SIZE];

// 这是定义变量
extern bool IrqFired;
static RadioEvents_t RadioEvents;
extern const struct Radio_s Radio;
// States_t State = LOWPOWER;

int8_t RssiValue = 0;
int8_t SnrValue = 0;

void (*msg_handler)(uint8_t, uint8_t *, int16_t, int8_t);


void Lora_init(uint8_t channel, uint8_t power)
{
    uint32_t Work_Frequency = RF_FREQUENCY; // RF_FREQUENCY;
    uint8_t tx_power = power + 7;
    Work_Frequency += channel * 250000;

    // msg_handler = NULL;
    RadioEvents.TxDone = OnTxDone;
    RadioEvents.RxDone = OnRxDone;
    RadioEvents.TxTimeout = OnTxTimeout;
    RadioEvents.RxTimeout = OnRxTimeout;
    RadioEvents.RxError = OnRxError;

    Radio.Init(&RadioEvents);
    Radio.SetChannel(Work_Frequency); // 接收端的频率是一样的
    Radio.SetTxConfig(MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                      LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                      LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                      false, 0, 0, LORA_IQ_INVERSION_ON, 3000);
    Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                      LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                      LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                      0, false, 0, 0, LORA_IQ_INVERSION_ON, false);
    printf("lora工作频道: %d  功率:%d  频率:%lu\r\n", channel, tx_power, Work_Frequency);
}
// 传递一个函数指针,用于处理数据
void Lora_setMsgHandler(void (*msghandler)(uint8_t, uint8_t *, int16_t, int8_t))
{
    msg_handler = msghandler;
}

// lora发送数据
void Lora_Send(uint8_t *data, uint16_t len)
{
    Radio.Standby();
    Radio.Send(data, len);
}

void Lora_Process()
{
    Radio.IrqProcess();
}

void Lora_setRxMode()
{
    Radio.Standby();
    Radio.Rx(RX_TIMEOUT_VALUE); // 进入接收
}

void OnTxDone(void)
{
    printf("OnTxDone\r\n");
    Lora_setRxMode();
}

void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
    if (msg_handler != NULL)
        msg_handler((uint8_t)size, payload, rssi, snr);
    Lora_setRxMode();
}

void OnTxTimeout(void)
{
    printf("OnTxTimeout\r\n");
    Lora_setRxMode();
}

void OnRxTimeout(void)
{
    printf("OnRxTimeout\r\n");
    Lora_setRxMode();
}

void OnRxError(void)
{
    printf("OnRxError\r\n");
    Lora_setRxMode();
}

(2). lora.h文件源文件

h

#ifndef INC_LORA_H_
#define INC_LORA_H_


#define RX485_BUF_SIZE 127

void Lora_init(uint8_t channel, uint8_t power);
void Lora_setMsgHandler(void (*msghandler)(uint8_t a, uint8_t *b, int16_t c, int8_t d));
void Lora_Send(uint8_t *data, uint16_t len);
void Lora_Process();
void Lora_setRxMode();
void OnTxDone(void);
void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
void OnTxTimeout(void);
void OnRxTimeout(void);
void OnRxError(void);

// 这里是具体的频率

typedef enum
{
    LOWPOWER,
    RX,
    RX_TIMEOUT,
    RX_ERROR,
    TX,
    TX_TIMEOUT,
} States_t;



#endif /* INC_LORA_H_ */

3. Lora模块的使用方法

c
    Lora_init(LORA_CHANNEL_VAL, LORA_POWER_VAL);
    Lora_setMsgHandler(Lora_Message_Handler);
    Lora_setRxMode();

以上代码是启动Lora模块,让模块处于接收状态,并设置了接收消息的回调函数.

c
void Lora_Message_Handler(uint8_t len, uint8_t *data, int16_t rssi, int8_t snr){
     printf("len: %d rssi: %d snr: %d data: ", len, rssi, snr);
     for(int i = 0; i < len; i++){
         printf("%02x ", data[i]);
     }
     printf("\n");
}

在回调函数中,一定要再次设置接收模式,否则模块将无法接收消息.

c
  for (;;) {
    // 延时1秒
    vTaskDelay(2);
    Lora_Process();

  }

在主循环中,调用 Lora_Process() 函数,该函数会处理Lora模块的消息,并调用回调函数.