LoRa 模块的驱动方法
1. 概述
LoRa 模块是一种低功耗、长距离的无线通信模块,它基于 LoRa 协议,具有低功耗、长距离、抗干扰等特点,广泛应用于物联网、智能电网、智能交通等领域。选择的lora模块使用的是芯片是: llcc68 , 此芯片是基于sx1268 的,所以使用的是sx1268的驱动代码的基础上进行修改的。
2. LoRa 模块的驱动代码
Lora模块的驱动: 下载 llcc68_driver: llcc68的驱动代码. 放入项目中的某个目录
修改接口驱动,完成移植: 在驱动源码中,有文件
sx126x-board.c和sx126x-board.h, 这两个文件是接口驱动,需要根据实际硬件进行修改.在项目中再添加两个文件:
lora.c和lora.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模块的消息,并调用回调函数.
