HAL_Project/Project -APP-V1.0/Hardware/LORA/lora.c

478 lines
22 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "lora.h"
LoRaParameter LoRaSetData = { //模块工作参数
0x00, //模块地址高字节
0x00, //模块地址低字节
0x01, //模块网络地址
LoRa_9600, //模块串口 波特率 9600
LoRa_8N1, //串口工作模式 8数据位 无校验 1停止位
LoRa_38_4, //模块空中速率 38.4K
LoRa_Data240, //数据分包大小 240字节
LoRa_RssiDIS, //关闭RSSI功能
LoRa_FEC_22DBM, //发射功率22dbm
LoRa_CH23, //模块信道
LoRa_RssiByteDIS, //禁用RSSI字节功能
LoRa_ModePOINT, //定点模式
LoRa_RelayDIS, //禁用中继模式
LoRa_LBTEN, //使能LBT
LoRa_WorTX, //Wor模式发送 只在模式1才有效
LoRa_Wor2000ms, //Wor周期2000毫秒 只在模式1才有效
0x22, //模块加密秘钥高字节
0x33, //模块加密秘钥低字节
};
//LoRA模块引脚初始化
void loraGpioInit(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIOA_RCC_ENABLE;
GPIOB_RCC_ENABLE;
GPIOC_RCC_ENABLE;
GPIO_InitStruct.Pin = LORA_AUX_Pin; //忙检测引脚
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(LORA_AUX_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LORA_POW_Pin ; //电源控制引脚
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LORA_POW_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LORA_M0_Pin ; //M0引脚
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LORA_M0_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LORA_M1_Pin ; //M1引脚
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LORA_M1_Port, &GPIO_InitStruct);
LoRa_MODE2; //模块模式2
HAL_Delay(200); //适当延时
}
/*-------------------------------------------------*/
/*函数名LoRa上电复位 */
/*参 数timeout超时时间 */
/*返回值0正确 其他:错误 */
/*-------------------------------------------------*/
uint8_t loraReset(int16_t timeout) {
LoRa_PowerOFF; //先关闭电源
HAL_Delay(200); //延时
LoRa_PowerON; //再打开电源
while(timeout--) { //等待复位成功
HAL_Delay(100); //延时100ms
if(LoRa_AUX==1) //需要等到高电平1才能跳出while表示复位完毕
break; //主动跳出while循环
u1_printf("%d ",timeout); //串口输出现在的超时时间
}
u1_printf("\r\n"); //串口输出信息
if(timeout<=0)return 1; //如果timeout<=0说明超时时间到了也没能等到LoRa_AUX高电平返回1
return 0; //正确返回0
}
/*-------------------------------------------------*/
/*函数名:初始化模块 */
/*参 数:无 */
/*返回值:无 */
/*-------------------------------------------------*/
void loraInit(void) {
loraGpioInit(); //Lora模块引脚初始化
u1_printf("准备复位Lora模块\r\n"); //串口输出信息
if(loraReset(100)) { //复位Lora模块返回值如果非零表示错误
u1_printf("复位Lora模块失败重启\r\n"); //串口输出信息
NVIC_SystemReset(); //重启
} else u1_printf("Lora模块复位成功\r\n"); //串口输出信息
u1_printf("准备设置Lora模块\r\n"); //串口输出信息
loraSet(); //设置Lora模块
HAL_Delay(200); //延时
}
/*-------------------------------------------------*/
/*函数名LoRa设置工作参数 */
/*参 数:无 */
/*返回值:无 */
/*-------------------------------------------------*/
void loraSet(void) {
uint8_t cmd[12]; //保存设置参数的数组缓冲区命令共计12字节
cmd[0] = 0xC0; //设置参数指令的起始字节固定值0xC0
cmd[1] = 0x00; //设置参数的起始寄存器地址从寄存器0开始设置一共9个
cmd[2] = 0x09; //一共设置9个寄存器
cmd[3] = LoRaSetData.LoRa_AddrH; //设置模块地址高字节
cmd[4] = LoRaSetData.LoRa_AddrL; //设置模块地址低字节
cmd[5] = LoRaSetData.LoRa_NetID; //设置模块网络地址
cmd[6] = LoRaSetData.LoRa_Baudrate | LoRaSetData.LoRa_UartMode | LoRaSetData.LoRa_airvelocity; //设置模块 波特率 串口模式 空中速率
cmd[7] = LoRaSetData.LoRa_DataLen | LoRaSetData.LoRa_Rssi | LoRaSetData.LoRa_TxPower; //设置模块 数据分包长度 RSSI噪声是否使能 发射功率
cmd[8] = LoRaSetData.LoRa_CH; //设置模块信道
cmd[9] = LoRaSetData.LoRa_RssiByte | LoRaSetData.LoRa_DateMode | LoRaSetData.LoRa_Relay | LoRaSetData.LoRa_LBT | LoRaSetData.LoRa_WORmode | LoRaSetData.LoRa_WORcycle; //设置模块 是否使用RSSI字节功能 传输方式 是否中继 是否使用LBT WOR模式收发控制 WOR周期
cmd[10] = LoRaSetData.LoRa_KeyH; //设置模块加密秘钥高字节
cmd[11] = LoRaSetData.LoRa_KeyL; //设置模块加密秘钥低字节
u3_TxDataBuf(cmd,12); //发送缓冲区加入数据
}
/*-------------------------------------------------*/
/*函数名LoRa查询工作参数 */
/*参 数data工作参数数据 */
/*返回值:无 */
/*-------------------------------------------------*/
void loraGet(uint8_t *data) {
uint8_t ch; //保存信道的变量
u1_printf("模块地址:0x%02X%02X\r\n",data[3],data[4]); //串口输出信息
u1_printf("模块网络ID:0x%02X\r\n",data[5]); //串口输出信息
switch(data[6]&0xE0) { //判断串口波特率
case LoRa_1200 :
u1_printf("波特率 1200\r\n"); //串口输出信息
break; //跳出
case LoRa_2400 :
u1_printf("波特率 2400\r\n"); //串口输出信息
break; //跳出
case LoRa_4800 :
u1_printf("波特率 4800\r\n"); //串口输出信息
break; //跳出
case LoRa_9600 :
u1_printf("波特率 9600\r\n"); //串口输出信息
break; //跳出
case LoRa_19200 :
u1_printf("波特率 19200\r\n"); //串口输出信息
break; //跳出
case LoRa_38400 :
u1_printf("波特率 38400\r\n"); //串口输出信息
break; //跳出
case LoRa_57600 :
u1_printf("波特率 57600\r\n"); //串口输出信息
break; //跳出
case LoRa_115200:
u1_printf("波特率 115200\r\n"); //串口输出信息
break; //跳出
}
switch(data[6]&0x18) { //判断串口参数
case LoRa_8N1 :
u1_printf("8数据位 无校验 1停止位\r\n"); //串口输出信息
break; //跳出
case LoRa_8O1 :
u1_printf("8数据位 奇校验 1停止位\r\n"); //串口输出信息
break; //跳出
case LoRa_8E1 :
u1_printf("8数据位 偶校验 1停止位\r\n"); //串口输出信息
break; //跳出
}
switch(data[6]&0x07) { //判断空中速率
case LoRa_0_3 :
u1_printf("空中速率 0.3K\r\n"); //串口输出信息
break; //跳出
case LoRa_1_2 :
u1_printf("空中速率 1.2K\r\n"); //串口输出信息
break; //跳出
case LoRa_2_4 :
u1_printf("空中速率 2.4K\r\n"); //串口输出信息
break; //跳出
case LoRa_4_8 :
u1_printf("空中速率 4.8K\r\n"); //串口输出信息
break; //跳出
case LoRa_9_6 :
u1_printf("空中速率 9.6K\r\n"); //串口输出信息
break; //跳出
case LoRa_19_2 :
u1_printf("空中速率 19.2K\r\n"); //串口输出信息
break; //跳出
case LoRa_38_4 :
u1_printf("空中速率 38.4K\r\n"); //串口输出信息
break; //跳出
case LoRa_62_5 :
u1_printf("空中速率 62.5K\r\n"); //串口输出信息
break; //跳出
}
switch(data[7]&0xC0) { //判断数据分包大小
case LoRa_Data240 :
u1_printf("数据分包大小240字节\r\n"); //串口输出信息
break; //跳出
case LoRa_Data128 :
u1_printf("数据分包大小128字节\r\n"); //串口输出信息
break; //跳出
case LoRa_Data64 :
u1_printf("数据分包大小64字节\r\n"); //串口输出信息
break; //跳出
case LoRa_Data32 :
u1_printf("数据分包大小32字节\r\n"); //串口输出信息
break; //跳出
}
switch(data[7]&0x20) { //判断是否启用RSSI功能
case LoRa_RssiEN :
u1_printf("启用RSSI功能\r\n"); //串口输出信息
break; //跳出
case LoRa_RssiDIS :
u1_printf("禁用RSSI功能\r\n"); //串口输出信息
break; //跳出
}
switch(data[7]&0x03) { //判断发射功率
case LoRa_FEC_22DBM :
u1_printf("发射功率 22dbm\r\n"); //串口输出信息
break; //跳出
case LoRa_FEC_17DBM :
u1_printf("发射功率 17dbm\r\n"); //串口输出信息
break; //跳出
case LoRa_FEC_13DBM :
u1_printf("发射功率 13dbm\r\n"); //串口输出信息
break; //跳出
case LoRa_FEC_10DBM :
u1_printf("发射功率 10dbm\r\n"); //串口输出信息
break; //跳出
}
ch = data[8] & 0x7F; //保存信道
u1_printf("信道:0x%02X 对应频率%dMHz\r\n",ch,410+ch); //串口输出信息
switch(data[9]&0x80) { //判断RSSI字节功能
case LoRa_RssiByteEN :
u1_printf("启用RSSI字节功能\r\n"); //串口输出信息
break; //跳出
case LoRa_RssiByteDIS :
u1_printf("禁用RSSI字节功能\r\n"); //串口输出信息
break; //跳出
}
switch(data[9]&0x40) { //判断传输模式
case LoRa_ModeTRANS :
u1_printf("透明传输\r\n"); //串口输出信息
break; //跳出
case LoRa_ModePOINT :
u1_printf("定点传输\r\n"); //串口输出信息
break; //跳出
}
switch(data[9]&0x20) { //判断中继功能
case LoRa_RelayEN :
u1_printf("启用中继\r\n"); //串口输出信息
break; //跳出
case LoRa_RelayDIS :
u1_printf("禁用中继\r\n"); //串口输出信息
break; //跳出
}
switch(data[9]&0x10) { //判断LBT功能
case LoRa_LBTEN :
u1_printf("启用LBT\r\n"); //串口输出信息
break; //跳出
case LoRa_LBTDIS :
u1_printf("禁用LBT\r\n"); //串口输出信息
break; //跳出
}
// switch(data[9]&0x08){ //判断WOR模式
// case LoRa_WorTX : u1_printf("Wor模式发送\r\n"); //串口输出信息
// break; //跳出
// case LoRa_WorRX : u1_printf("Wor模式接收\r\n"); //串口输出信息
// break; //跳出
// }
// switch(data[9]&0x07){ //判断WOR周期
// case LoRa_Wor500ms : u1_printf("WOR周期时间 500毫秒\r\n"); //串口输出信息
// break; //跳出
// case LoRa_Wor1000ms : u1_printf("WOR周期时间 1000毫秒\r\n"); //串口输出信息
// break; //跳出
// case LoRa_Wor1500ms : u1_printf("WOR周期时间 1500毫秒\r\n"); //串口输出信息
// break; //跳出
// case LoRa_Wor2000ms : u1_printf("WOR周期时间 2000毫秒\r\n"); //串口输出信息
// break; //跳出
// case LoRa_Wor2500ms : u1_printf("WOR周期时间 2500毫秒\r\n"); //串口输出信息
// break; //跳出
// case LoRa_Wor3000ms : u1_printf("WOR周期时间 3000毫秒\r\n"); //串口输出信息
// break; //跳出
// case LoRa_Wor3500ms : u1_printf("WOR周期时间 3500毫秒\r\n"); //串口输出信息
// break; //跳出
// case LoRa_Wor4000ms : u1_printf("WOR周期时间 4000毫秒\r\n"); //串口输出信息
// break; //跳出
// }
}
/*-------------------------------------------------*/
/*函数名串口3被动事件 */
/*参 数data :数据 */
/*参 数datalen :数据长度 */
/*返回值:无 */
/*-------------------------------------------------*/
uint8_t tempdata[512];
void u3PassiveEvent(uint8_t *data, uint16_t datalen) {
/*----------------------------------------------*/
/* 接收设置LoRa模块返回数据 */
/*----------------------------------------------*/
if((data[0]==0xC1)&&(datalen==12)) {
u1_printf("接收设置LoRa模块返回数据\r\n"); //串口输出信息
loraGet(data); //分析设置的参数
LoRa_MODE0; //切换到模式0
HAL_Delay(200); //延时
catReset(); //4G模块重启
}
/*----------------------------------------------*/
/* 接收到子设备x上发的证书信息 */
/*----------------------------------------------*/
if(datalen==(SUBMQTTINFO_STRUCT_LEN+1)) { //收到符合长度的数据
switch (data[0]) {
case CERT1_DATA:
subDeviceReportingCertificate(0,data);
break;
case CERT2_DATA:
subDeviceReportingCertificate(1,data);
break;
case CERT3_DATA:
subDeviceReportingCertificate(2,data);
break;
case CERT4_DATA:
subDeviceReportingCertificate(3,data);
break;
case CERT5_DATA:
subDeviceReportingCertificate(4,data);
break;
case CERT6_DATA:
subDeviceReportingCertificate(5,data);
break;
case CERT7_DATA:
subDeviceReportingCertificate(6,data);
break;
case CERT8_DATA:
subDeviceReportingCertificate(7,data);
break;
case CERT9_DATA:
subDeviceReportingCertificate(8,data);
break;
case CERT10_DATA:
subDeviceReportingCertificate(9,data);
break;
default :
break;
}
u1_printf("***收到子设备数据,线程结束...\r\n");
taskRunning = 0; //则退出
}
/*----------------------------------------------*/
/* 接收到子设备x上发的数据 */
/*----------------------------------------------*/
if(datalen==(ATTRIBUTE_STRUCT_LEN+1)) { //收到符合长度的数据
switch (data[0]) {
case SUB1_DATA:
subDeviceReportingSwitchStatus(0,data);
break;
case SUB2_DATA:
subDeviceReportingSwitchStatus(1,data);
break;
case SUB3_DATA:
subDeviceReportingSwitchStatus(2,data);
break;
case SUB4_DATA:
subDeviceReportingSwitchStatus(3,data);
break;
case SUB5_DATA:
subDeviceReportingSwitchStatus(4,data);
break;
default :
break;
}
u1_printf("***收到子设备数据,线程结束...\r\n");
taskRunning = 0; //则退出
}
}
//子设备上报证书信息至云平台 推送 参数说明: sub_num 子设备序号 0表示设备1...
void subDeviceReportingCertificate(uint8_t sub_num,uint8_t *data) {
u1_printf("接收到子设备%d证书信息。\r\n",sub_num + 1);
memcpy(&SubMqttInfo_Struct[sub_num],&data[1],SUBMQTTINFO_STRUCT_LEN); //临时缓冲区全部清零
CAT1_printf("AT+MPUB=\"/iot/sub/live/post/%s\",0,0,\"{\\22header\\22:\\22iot.sub.live.post\\22,\\22version\\22:\\221.0\\22,\\22body\\22:{\\22online\\22:[{\\22uid\\22:\\22%s\\22,\\22secret\\22:\\22%s\\22}]}}\"\r\n",
GwMqttInfo_Struct.ClientID,
SubMqttInfo_Struct[sub_num].ClientID,
SubMqttInfo_Struct[sub_num].Passward);
u1_printf("子设备%d的uid%s,secret%s\r\n",
sub_num + 1,
SubMqttInfo_Struct[sub_num].ClientID,
SubMqttInfo_Struct[sub_num].Passward);
SUB_DEVICE_ON[sub_num] = 1;//子设备上线标志位置一
}
//子设备上报开关状态至云平台 推送 参数说明: sub_num 子设备序号 0表示设备1...
void subDeviceReportingSwitchStatus(uint8_t sub_num,uint8_t *data) {
u1_printf("接收到子设备%d的数据。\r\n",sub_num + 1);
memcpy(&SubAttribute_Struct[sub_num],&data[1],ATTRIBUTE_STRUCT_LEN); //拷贝数据
u1_printf("* * * * *准备上传设备电量,温度,大气压强,环境温湿度* * * * *\r\n");
/*
BAT_VAL 电池电量
DEV_TP 设备温度
DEV_RES 设备重启次数
BS_RH 大气湿度
BS_T 大气温度
BS_DO 大气压强
SOIL_RH 土壤湿度
SOIL_TP 土壤温度
YSMD_RH 叶面湿度
YSMD_TP 叶面温度
BY_HV 百叶箱光照
BY_CO2 百叶箱二氧化碳
SOIL_NV 土壤氮
SOIL_PV 土壤磷
SOIL_KV 土壤钾
SOIL_PH 土壤PH
SOIL_RV 土壤电导率
SIGNAL 信号强度
*/
CAT1_printf("AT+MPUB=\"/iot/sub/prop/post/%s\",0,0,\"{\\22header\\22:\\22iot.sub.prop.post\\22,\\22version\\22:\\221.0\\22,\\22body\\22:{\\22subs\\22:[{\\22uid\\22:\\22%s\\22,\\22props\\22:{\\22BAT_VAL\\22:%d,\\22DEV_TP\\22:%.1f,\\22DEV_RES\\22:%d,\\22BS_RH\\22:%.1f,\\22BS_T\\22:%.1f,\\22BS_DO\\22:%.1f}}]}}\"\r\n",
GwMqttInfo_Struct.ClientID,
SubMqttInfo_Struct[sub_num].ClientID,
SubAttribute_Struct[sub_num].Sub_BAT,
SubAttribute_Struct[sub_num].Device_Temp,
SubAttribute_Struct[sub_num].Res_Count,
SubAttribute_Struct[sub_num].Envir_PressHumi,
SubAttribute_Struct[sub_num].Envir_PressTemp,
SubAttribute_Struct[sub_num].Envir_Press);//回复数据
HAL_Delay(1000);
u1_printf("* * * * *准备上传叶面温湿度,土壤温湿度,环境光照强度,二氧化碳含量 * * * * *\r\n");
CAT1_printf("AT+MPUB=\"/iot/sub/prop/post/%s\",0,0,\"{\\22header\\22:\\22iot.sub.prop.post\\22,\\22version\\22:\\221.0\\22,\\22body\\22:{\\22subs\\22:[{\\22uid\\22:\\22%s\\22,\\22props\\22:{\\22SOIL_RH\\22:%.1f,\\22SOIL_TP\\22:%.1f,\\22YSMD_RH\\22:%.1f,\\22YSMD_TP\\22:%.1f,\\22BY_HV\\22:%d,\\22BY_CO2\\22:%d}}]}}\"\r\n",
GwMqttInfo_Struct.ClientID,
SubMqttInfo_Struct[sub_num].ClientID,
SubAttribute_Struct[sub_num].Soil_Humi,
SubAttribute_Struct[sub_num].Soil_Temp,
SubAttribute_Struct[sub_num].Leaf_Humi,
SubAttribute_Struct[sub_num].Leaf_Temp,
SubAttribute_Struct[sub_num].Envir_Light,
SubAttribute_Struct[sub_num].Envir_Co2);//回复数据
HAL_Delay(1000);
u1_printf("* * * * *准备上传土壤氮磷钾含量土壤PH土壤电导率子设备信号强度* * * * *\r\n");
CAT1_printf("AT+MPUB=\"/iot/sub/prop/post/%s\",0,0,\"{\\22header\\22:\\22iot.sub.prop.post\\22,\\22version\\22:\\221.0\\22,\\22body\\22:{\\22subs\\22:[{\\22uid\\22:\\22%s\\22,\\22props\\22:{\\22SOIL_NV\\22:%d,\\22SOIL_PV\\22:%d,\\22SOIL_KV\\22:%d,\\22SOIL_PH\\22:%.1f,\\22SOIL_RV\\22:%d,\\22SIGNAL\\22:%d}}]}}\"\r\n",
GwMqttInfo_Struct.ClientID,
SubMqttInfo_Struct[sub_num].ClientID,
SubAttribute_Struct[sub_num].Soil_NV,
SubAttribute_Struct[sub_num].Soil_PV,
SubAttribute_Struct[sub_num].Soil_KV,
SubAttribute_Struct[sub_num].Soil_PH,
SubAttribute_Struct[sub_num].Soil_EC,
SubAttribute_Struct[sub_num].SIGNAL_STRENGTH);//回复数据
u1_printf("子设备重启次数:%d\r\n",SubAttribute_Struct[sub_num].Res_Count);
u1_printf("设备温度: %.1f'C\r\n",SubAttribute_Struct[sub_num].Device_Temp);
u1_printf("电池电量为:%d %%\r\n",SubAttribute_Struct[sub_num].Sub_BAT); //串口输出
u1_printf("环境湿度:%.2f%%RH温度%.2f'C,大气压强:%.2fKpa\r\n",SubAttribute_Struct[sub_num].Envir_PressHumi,SubAttribute_Struct[sub_num].Envir_PressTemp,SubAttribute_Struct[sub_num].Envir_Press);
u1_printf("叶面湿度:%.2f%%RH温度%.2f'C\r\n",SubAttribute_Struct[sub_num].Leaf_Humi,SubAttribute_Struct[sub_num].Leaf_Temp);
u1_printf("土壤湿度:%.2f%%RH温度%.2f'C\r\n",SubAttribute_Struct[sub_num].Soil_Humi,SubAttribute_Struct[sub_num].Soil_Temp);
u1_printf("土壤氮含量:%dmg/kg磷含量%dmg/kg钾含量%dmg/kg\r\n",SubAttribute_Struct[sub_num].Soil_NV,SubAttribute_Struct[sub_num].Soil_PV,SubAttribute_Struct[sub_num].Soil_KV);
u1_printf("土壤酸碱度:%.2f\r\n",SubAttribute_Struct[sub_num].Soil_PH);
u1_printf("土壤电导率:%duS/cm\r\n",SubAttribute_Struct[sub_num].Soil_EC);
}