1、Lora模块
LoRa模块为基于LPWAN的远距离无线通信模块,支持LORAWAN标准协议,串口数据透传双向通讯,主要应用在智能抄表、智慧路灯、智慧农业、智能停车、智能安防等领域。LoRa技术具有远距离、低功耗、多节点、低成本的特性基于LoRaWAN的网络能够提供安全的数据传输距离远的双向通信,并且用最少的网络基础设施覆盖城市区域,LoRa技术在智慧农业、智慧建筑、智慧物流等多种应用场景中都将得到广泛应用。
2、应用场景
家庭安防报警及远程无钥匙进入;
智能家居以及工业传感器等l;
无线报警安全系统;
楼宇自动化解决方案;
无线工业级遥控器;
智能智能农业、油田方案;医疗保健产品;
高级抄表架构(AMI);
汽车行业应用。
3、引脚定义
Lora可配置参数
Lora设置模式下可以连续发送6个字节进行功能的设置,将功能封装为结构体
typedef struct{
uint8_t head;
uint8_t addh;
uint8_t addl;
uint8_t sped;
uint8_t chan;
uint8_t option;
}Lora_WorkParameter;//工作参数
其中:
head 为C0时设参数掉电保存 为C2时掉电不保存
addh 模块地址高字节
addl 模块地址低字节
sped 7 6位控制串口通信模式 5 4 3 设置串口速率 2 1 0 设置无线空中速率
chan 7 6 5保留 4 3 2 1 0 通信通道设置 00H-0FH d对应410HZ~441HZ Lora模块就工作在此频率空间
option 7 定点发送使能位 为1时定点传输模式用户前三个字节作为高地址 低地址 通道、 为0时 透明传输
6 IO驱动方式 默认1
5 4 3 无线唤醒时间
2 FEC开关
1 0 发射功率
4、Lora使用方法
4.1 Lora的四种工作模式
Lora有四种工作模式,类似esp8266,模块的使用都会有配置模式和通讯模式等,Lora将模式分为四种
M0,M1两引脚通常与两个普通GPIO口链接,通过置位高低电平控制模块的工作模式,通常使用一般模式和休眠模式,其中休眠模式就是配置模式。
5、模块传输模式
模块传输模式有三种,模块的工作会时刻监听Lora工作频率433MHz下的任何数据
(1)透明传输:即透传数据,例如:A设备发5字节数据AABBCCDDEE到B设备,B设备就可以收到数据AABBCCDDEE。(透明传输,针对设备相同地址、相同的通信信道,用户数据可以是字符或16进制数据形式)
(2)定向传输:即定点传输,例如:A设备(地址为:0x0001,信道为0x02)需要向B设备(地址为:0x0003,信道为0x10)发送数据AABBCC,其通信格式为:0003 04 AABBCC,其中0003为模块B的地址,04为信道,则模块B可以收到AABBCC。同理,如果B设备需要向A设备发送数据AABBCC,其通信格式为:000102AABBCC,则A设备可以收到AABBCC。(定向传输,针对设备间地址和通信信道不同,数据格式为16进制,发送格式:高位地址+低位地址+信道+用户数据)
(3)广播与数据监听:将发送数据中的模块地址写为为0xFFFF(即65535),可以被相同信道上任意地址的模块收到,从而起到广播和监听的作用。
三者的区别:
简单的说,当只需要点对点通信(即两个LORA相互通信)时,可使用前两种方式。
其中,透明传输可以以字符或16进制数据形式发送,需要两个LORA模块的地址、信道相同,而定向传输只能以16进制的特定格式发送,无需二者地址或信道相同。(由于LORA模块的地址和信道有十分多的选择,一般不会出现冲突的可能,所以个人推荐使用透明传输更方便。)
6、c语言实现
lora.h
#ifndef _LOAR_H_
#define _LOAR_H_
#include "stm32f10x.h"
#define LORA_M0_CLK RCC_APB2Periph_GPIOB
#define LORA_M0_PORT GPIOB
#define LORA_M0_PIN GPIO_Pin_5
#define LORA_M1_CLK RCC_APB2Periph_GPIOB
#define LORA_M1_PORT GPIOB
#define LORA_M1_PIN GPIO_Pin_6
#define LORA_AUX_CLK RCC_APB2Periph_GPIOB
#define LORA_AUX_PORT GPIOB
#define LORA_AUX_PIN GPIO_Pin_7
#define M0(x) (x)?(GPIO_SetBits(LORA_M0_PORT,LORA_M0_PIN)):(GPIO_ResetBits(LORA_M0_PORT,LORA_M0_PIN))
#define M1(x) (x)?(GPIO_SetBits(LORA_M1_PORT,LORA_M1_PIN)):(GPIO_ResetBits(LORA_M1_PORT,LORA_M1_PIN))
#define AUX_Sta() (GPIO_ReadInputDataBit(LORA_AUX_PORT,LORA_AUX_PIN))
/*********************设置Lora工作参数***********/
//修改参数命令
#define CMD_STOREPRM 0xC0//所设置参数会保存
#define CMD_NOTSTOREPRM 0xC2//所设置参数不会保存
//UART协议中奇偶校验
#define PRM_UART_Parity_8N1 0x00//不奇偶校验
#define PRM_UART_Parity_8O1 0x01//偶校验
#define PRM_UART_Parity_8E1 0x10//奇校验
//UART协议中波特率
#define PRM_UART_BaudRate_1200 0x00
#define PRM_UART_BaudRate_2400 0x01
#define PRM_UART_BaudRate_4800 0x02
#define PRM_UART_BaudRate_9600 0x03
#define PRM_UART_BaudRate_19200 0x04
#define PRM_UART_BaudRate_38400 0x05
#define PRM_UART_BaudRate_57600 0x06
#define PRM_UART_BaudRate_115200 0x07
//设置空中数据传输速率
#define PRM_Sky_Speed_0_3 0x00//0.3kbps
#define PRM_Sky_Speed_1_2 0x01//1.2kbps
#define PRM_Sky_Speed_2_4 0x02//2.4kbps
#define PRM_Sky_Speed_4_8 0x03//4.8kbps
#define PRM_Sky_Speed_9_6 0x04//9.6kbps
#define PRM_Sky_Speed_19_2 0x05//19.2kbps
//设置传输模式
#define PRM_TRAN_MODE_TT 0x00//透传传输模式
#define PRM_TRAN_MODE_FP 0x01//定点传输模式
//AUX RX TX IO驱动方式
#define PRM_IO_Driver_PP 0x01//内部具有上拉
#define PRM_IO_Driver_OD 0x00//内部具有开路
//唤醒时间
#define PRM_WarkUp_Time_250 0x00//单位ms
#define PRM_WarkUp_Time_500 0x01
#define PRM_WarkUp_Time_750 0x02
#define PRM_WarkUp_Time_1000 0x03
#define PRM_WarkUp_Time_1250 0x04
#define PRM_WarkUp_Time_1500 0x05
#define PRM_WarkUp_Time_1750 0x06
#define PRM_WarkUp_Time_2000 0x07
//FEC纠错开关
#define PRM_FEC_OPEN 0x01//打开
#define PRM_FEC_CLOSE 0x00//关闭
//设置发射功率
#define PRM_EmissionPower_20 0x00//20dbm
#define PRM_EmissionPower_17 0x01
#define PRM_EmissionPower_14 0x02
#define PRM_EmissionPower_10 0x03
//设置默认的参数(也可以在外面设置参数)
#define CMD_DEFAULT CMD_STOREPRM
#define PRM_UART_Parity_DEFAULT PRM_UART_Parity_8N1
#define PRM_UART_BaudRate_DEFAULT PRM_UART_BaudRate_9600
#define PRM_Sky_Speed_DEFAULT PRM_Sky_Speed_2_4
#define PRM_CHANNEL_DEFAULT 0x17//00-73h变化 410~525MHz
#define PRM_TRAN_MODE_DEFAULT PRM_TRAN_MODE_TT
#define PRM_WarkUp_Time_DEFAULT PRM_WarkUp_Time_250
#define PRM_FEC_DEFAULT PRM_FEC_OPEN
#define PRM_EmissionPower_DEFAULT PRM_EmissionPower_20
#define LORA_MODE_PATTERN 0x00 //一般模式
#define LORA_MODE_WARKUP 0x01 //唤醒模式
#define LORA_MODE_POWERSAVE 0x10 //省电模式
#define LORA_MODE_SLEEP 0x11 //休眠模式
typedef struct{
u8 head;
u8 addh;
u8 addl;
u8 sped;
u8 chan;
u8 option;
}__Lora_WorkParameter;//工作参数
typedef union {
Lora_WorkParameter lora_workprm;
u8 buff[6];
}LORA_WORKDATA;//接收或则发送工作参数,使用共用体方便使用
#define WIRELESS_RX_MAX 1024
#define WIRELESS_TX_MAX 1024
typedef struct{
uint8_t rx_buff[WIRELESS_RX_MAX];//串口数据接收缓冲区
uint8_t tx_buff[WIRELESS_TX_MAX];//串口数据发送缓冲区
uint8_t rx_over; //接收完成标志0 -- 没有接收完成 1 -- 接收完成
uint32_t rx_count; //接收数据的个数
uint32_t tx_count; //发送数据的个数
}Lora_TypeDef;
void Lora_Init(void);
void UART4_Config(u32 boad);
void UART4_SendData(u8 data);
void Lora_SendCmd(u8* data, u8 size);
void Lora_SendData(u8 *data,u16 len);
void Lora_SetWorkParameters(void);
void Lora_DataAnalysis(void);
Lora.c
Lora_TypeDef loradata = {0};
LORA_WORKDATA lora_parameter = {0};
u16 lora_self_addr = 0x0001;//本身地址
u16 lora_target_addr = 0x0002;//目标地址
void Lora_Init(void)
{
//相关管脚初始化
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(LORA_M0_CLK|LORA_M1_CLK|LORA_AUX_CLK,ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = LORA_M0_PIN;
GPIO_Init(LORA_M0_PORT,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = LORA_M1_PIN;
GPIO_Init(LORA_M1_PORT,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = LORA_AUX_PIN;
GPIO_Init(LORA_AUX_PORT,&GPIO_InitStruct);
UART4_Config(9600);//串口3初始化+接收中断初始化
Lora_SetWorkParameters();
// Lora_CurrentPram();//读取Lora模块的参数
}
void UART4_Config(u32 boad)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
//3.给结构体赋值 TX管脚 输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //具体外设用哪个模式,从参考手册8.1.11中查询
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
//4.调用init函数,将参数写入到寄存器中
GPIO_Init(GPIOC,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //具体外设引脚用哪个模式,从参考手册8.1.11中查询
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStruct);
/*****************************************************************/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = boad; //波特率
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控制
USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; //发送和接收都使能
USART_InitStruct.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStruct.USART_StopBits = USART_StopBits_1; //1个停止位
USART_InitStruct.USART_WordLength = USART_WordLength_8b; //8个数据位
//8.调用init函数,将参数写入到寄存器中
USART_Init(UART4,&USART_InitStruct);
//配置为串口接收中断与空闲中断
USART_ITConfig(UART4,USART_IT_RXNE,ENABLE); //打开接收中断
USART_ITConfig(UART4,USART_IT_IDLE,ENABLE); //打开空闲中断
NVIC_SetPriority(UART4_IRQn,1);
NVIC_EnableIRQ(UART4_IRQn);
USART_Cmd(UART4,ENABLE);
}
void UART4_IRQHandler(void)
{
uint8_t data = 0;
data = data;
if(USART_GetITStatus(UART4, USART_IT_RXNE) == SET)
{
if(loradata.rx_count>WIRELESS_RX_MAX)
loradata.rx_count=0;
loradata.rx_buff[loradata.rx_count++] = UART4->DR;
USART_ClearITPendingBit(UART4, USART_IT_RXNE);
//USART_SendData(USART1,UART4->DR); //串口1显示
}
if(USART_GetITStatus(UART4, USART_IT_IDLE) == SET)
{
loradata.rx_over = 1;
USART_ReceiveData(UART4);
}
}
void UART4_SendData(u8 data)
{
while(USART_GetFlagStatus(UART4, USART_FLAG_TC) == RESET);
UART4->DR = data;
}
void Lora_SendCmd(u8* data, u8 size)
{
for(u8 i=0; i<size; i++)
UART4_SendData(data[i]);
}
//数组发送函数
//数组的首地址 数组的长度
void UART4_SendBuff(uint8_t *buff,uint16_t length)
{
uint16_t temp=0;
for(temp=0;temp<length;temp++)
{
UART4_SendData(buff[temp]);
}
}
void Lora_SendData(u8 *data, u16 len)
{
u8 addrh = (lora_target_addr>>8)&0xFF;
u8 addrl = lora_target_addr&0xFF;
uint8_t buff[256] = {addrh,addrl,PRM_CHANNEL_DEFAULT};
for(u8 i=0; i<len; i++)
buff[i+3] = data[i];
for(u8 i=0; i<len+3; i++)
UART4_SendData(buff[i]);
}
//设置Lora的模式
void Lora_SetMode(u8 mode)
{
if((mode != LORA_MODE_PATTERN) && (mode != LORA_MODE_WARKUP) && (mode != LORA_MODE_POWERSAVE) && (mode != LORA_MODE_SLEEP))
return ;
GPIO_WriteBit(LORA_M0_PORT,LORA_M0_PIN,(BitAction)(mode & 0x1));
GPIO_WriteBit(LORA_M1_PORT,LORA_M1_PIN,(BitAction)((mode>>4) & 0x1));
vTaskDelay(100);
}
//#define LORA_MODE_PATTERN 0x00 //一般模式
//#define LORA_MODE_WARKUP 0x01 //唤醒模式
//#define LORA_MODE_POWERSAVE 0x10 //省电模式
//#define LORA_MODE_SLEEP 0x11 //休眠模式
//Lora模块复位
void Lora_Reset(void)
{
u8 tx_buff[] = {0xC4,0xC4,0xC4};
Lora_SetMode(LORA_MODE_SLEEP);//进入休眠模式
Lora_SendCmd(tx_buff,sizeof(tx_buff));//发送重启命令
}
//设置lora工作参数
void Lora_SetWorkParameters(void)
{
//关闭串口4中断
USART_ITConfig(UART4,USART_IT_RXNE, DISABLE);
NVIC_DisableIRQ(UART4_IRQn);
Lora_SetMode(LORA_MODE_SLEEP);//进入休眠模式
lora_parameter.lora_workprm.head = CMD_STOREPRM;//掉电不丢失
lora_parameter.lora_workprm.addh = (lora_self_addr>>8) & 0xff;
lora_parameter.lora_workprm.addl = lora_self_addr & 0xff;
lora_parameter.lora_workprm.sped = (PRM_UART_Parity_8N1<<6)|(PRM_UART_BaudRate_9600<<3)|(PRM_Sky_Speed_2_4);
lora_parameter.lora_workprm.chan = PRM_CHANNEL_DEFAULT; // 0x17 00-73h变化 410~525MHz
lora_parameter.lora_workprm.option = ((PRM_TRAN_MODE_FP<<7)|(PRM_IO_Driver_PP<<6)|
(PRM_WarkUp_Time_250<<3)|(PRM_FEC_OPEN<<2)|(PRM_EmissionPower_20));
Lora_SendCmd(lora_parameter.buff,sizeof(lora_parameter.buff));
vTaskDelay(100);
Lora_SetMode(LORA_MODE_PATTERN);//进入一般模式
//开中断
USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);
NVIC_EnableIRQ(UART4_IRQn);
}