LoRa通信应用开发【保姆级】+LoRa光照传感器节点应用程序开发 !!!

前言

基于LoRa无线通信和传感器数据采集的嵌入式程序,主要功能是通过LoRa模块发送和接收数据,并在OLED屏幕上显示光照信息


硬件选择

新大陆——LoRa开发板

新大陆——光照传感器 


代码讲解

跳过文件创建过程,直接对代码进行讲解。

1. 头文件和宏定义模块

#include <string.h>
#include <stdio.h>
#include "board.h"
#include "radio.h"
#include "NS_Radio.h"
#include "hal_temHum.h"

#define START_HEAD 0x55
#define CMD_READ 0x01
#define ACK_OK 0x00
#define ACK_NONE 0x01
#define ACK_ERR 0x02

#define MY_NET_ID 0x0138
#define MY_ADDR 0x02

功能:这部分引入了程序所需的头文件,并定义了一些常量。

START_HEADCMD_READACK_OK 等宏定义用于协议帧的格式化和解析。

MY_NET_ID 和 MY_ADDR 分别定义了网络ID和设备地址,用于LoRa通信中的身份标识。

2. 全局变量模块

uint16_t LightLux = 0; // 光照变量

功能:定义了全局变量 LightLux,用于存储光照的值。初始值为0。

3. 传感器数据采集模块

void LoRa_GetSensorDataProcess(void){
	const uint16_t time = 1000;
	if(User0Timer_MS > time){
		User0Timer_MS = 0;
		uint16_t AdcNum , voltage;
		//AdcNum
		AdcNum = AdcReadChannel(&Adc , ADC_CHANNEL_0);
		voltage = AdcNum*3300/(4096 - 1.0);
		LightLux = (5 / 2.0)*(voltage / 10.0);
		char StrBuf[64] = {0};
		memset(StrBuf , '' ,64);
		
		sprintf(StrBuf , "%d lux" , LightLux);
		printf("%d lux" , LightLux);
		OLED_ShowString(0,4,(uint8_t *)StrBuf);
	}
}

功能概述

定时触发

每 1000毫秒(1秒) 执行一次数据采集(通过 User0Timer_MS 计时器控制)。

每次触发后重置计时器(User0Timer_MS = 0)。

传感器数据读取

通过 ADC通道0ADC_CHANNEL_0)读取模拟信号值(AdcNum),假设ADC分辨率为12位(取值范围 0-4095)。

电压值转换

将ADC原始值转换为电压(单位:毫伏)

光照强度计算

将电压转换为光照强度(单位:勒克斯,Lux):

LightLux=2.5×(voltage10)LightLux=2.5×(10voltage​)

公式假设传感器输出电压与光照强度成线性关系,但需根据具体传感器校准。

数据输出与显示

通过 串口打印 光照值(printf("%d lux", LightLux))。

在 OLED屏幕 的坐标 (0, 4) 处显示光照值(如 "123 lux")。

4. 校验和计算模块

uint8_t CheckSum(uint8_t *buf , uint8_t len){
    uint8_t temp = 0;
    while(len--){
        temp += *buf;
        buf++;
    }
    return (uint8_t)temp;
}

功能:计算数据帧的校验和,用于数据完整性验证。

遍历数据缓冲区 buf,累加所有字节的值,返回校验和结果。

5. 数据帧提取模块

uint8_t *ExtractCmdframe(uint8_t *buf , uint8_t len , uint8_t CmdStart){
    uint8_t *point = NULL;
    uint8_t i;
    for(i=0 ; i<len ; i++){
        if(CmdStart == *buf){
            point = buf;
            return point;
        }
        buf++;
    }
    return NULL;
}

功能:从接收的数据中提取特定起始字节(CmdStart)开始的数据帧。

遍历数据缓冲区 buf,查找起始字节 CmdStart,返回该字节的指针

6. 数据转十六进制字符串模块

uint16_t GetHexStr(uint8_t *input , uint16_t len , uint8_t *output){
    for(uint16_t i=0; i<len ; i++){
        sprintf((char*)(output+i*3),"%02X",*input);
        input++;
    }
    return strlen((const char*)output);
}

功能:将二进制数据转换为十六进制字符串。

遍历输入数据 input,使用 sprintf 将每个字节转换为两位十六进制字符串。

7. LoRa数据解析模块

void LoRa_DataParse(uint8_t *LoRaRxBuf, uint16_t len){
	uint8_t *DestData = NULL;
	#define HEAD_DATA *DestData
	#define CMD_DATA *(DestData+1)
	#define NETH_DATA *(DestData+2)
	#define NETL_DATA *(DestData+3)
	#define ADDR_DATA *(DestData+4)
	
	#define ACK_DATA  *(DestData+5)
	#define LEN_DATA  *(DestData+6)
	#define DATASTAR_DATA  *(DestData+7)
	
	DestData = ExtractCmdframe((uint8_t *)LoRaRxBuf , len , START_HEAD);
	if(DestData != NULL){
		if((DestData - LoRaRxBuf) > (len - 6)) return;
		if(CMD_DATA != CMD_READ)return;
		if(CheckSum((uint8_t *)DestData ,5) != (*(DestData+5))) return;
		if(((((uint16_t)NETH_DATA)<<8)+NETL_DATA) != MY_NET_ID) return;
		if(ADDR_DATA != MY_ADDR) return;
		
		uint8_t RspBuf[BUFFER_SIZE]={0};
		memset(RspBuf, '',BUFFER_SIZE);
		RspBuf[0]=START_HEAD;
		RspBuf[1]=CMD_READ;
		RspBuf[2]=(uint8_t)(MY_NET_ID>>8);
		RspBuf[3]=(uint8_t)MY_NET_ID;
		RspBuf[4]=MY_ADDR;
		RspBuf[5]=ACK_OK,
		//
		sprintf((char *)(RspBuf+7),"LightLux(lux):%d",LightLux);
		
		RspBuf[6]=strlen((const char *)(RspBuf+7))+1;
		RspBuf[6+RspBuf[6]]=CheckSum((uint8_t*)RspBuf, 6+RspBuf[6]);
		Radio.Send(RspBuf , 7+RspBuf[6]);
		GpioToggle(&Led1);
	}
}

功能:解析接收到的LoRa数据帧,并根据协议格式进行处理。

检查数据帧的合法性(如校验和、命令类型、网络ID和地址)。

如果数据帧合法,构造响应帧,包含光照信息,并通过LoRa发送。

8. LoRa发送模块

void LoRa_Send( uint8_t *TxBuffer, uint8_t len )
{
    Radio.Send( TxBuffer, len);
}

功能:封装了LoRa模块的发送功能,调用底层的 Radio.Send 函数发送数据。

9. LoRa接收处理模块

void MyRadioRxDoneProcess( void )
{
    uint16_t BufferSize = 0;
    uint8_t RxBuffer[BUFFER_SIZE];
 
    BufferSize = ReadRadioRxBuffer( (uint8_t *)RxBuffer );
    if(BufferSize>0)
    {
        GpioToggle(&Led2);
        LoRa_DataParse((uint8_t*)RxBuffer,BufferSize);
    }
}

功能:处理LoRa模块接收到的数据。

调用 ReadRadioRxBuffer 读取接收缓冲区中的数据。

如果接收到数据,则调用 LoRa_DataParse 进行解析。

10. OLED初始化模块

void OLED_InitView(void)
{
    OLED_Clear();
    OLED_ShowString(0,0, (uint8_t *)"230102030138");
		OLED_ShowString(0,2,(uint8_t *)"LoRa Light");
}

功能:初始化OLED屏幕,并显示初始信息。

11. 平台初始化模块

void PlatformInit(void)
{
    // 开发板平台初始化
    BoardInitMcu();
    BoardInitPeriph();

    // 开发板设备初始化
    OLED_Init();//液晶初始化
    USART1_Init(115200);//串口1初始化
    OLED_Clear();
    OLED_InitView();//OLED屏幕显示初始信息
    
    printf("张思奇 
");
		

    //Lora模块初始化
    NS_RadioInit( (uint32_t) RF_PING_PONG_FREQUENCY, (int8_t) TX_OUTPUT_POWER, (uint32_t) TX_TIMEOUT_VALUE, (uint32_t) RX_TIMEOUT_VALUE );
    
    //请在下方添加用户初始化代码
    printf("LoRa Light
");
	
		AdcInit(&Adc , ADC_0);
		Tim3McuInit(1);
    //IWDG_PrmInit(2048);//独立看门狗初始化,超时设置为2048ms
}

功能:初始化硬件平台和外设。

初始化MCU和外设(如OLED、串口、LoRa模块)。

初始化光照传感器。

12.主函数模块

int main( void )
{
    PlatformInit();
 
    while( 1 )
    {
        MyRadioRxDoneProcess();
        LoRa_GetSensorDataProcess();
    }
}

功能:程序的入口点。

调用 PlatformInit 初始化平台。

在主循环中,不断调用 MyRadioRxDoneProcess 处理LoRa接收数据,调用 LoRa_GetSensorDataProcess 采集传感器数据。


程序烧写


结果显示

感谢各位读者的阅读!希望大家给出一键三连,多多支持原创。有错误和不解的地方,欢迎各位读者在评论区讨论,我也会不断学习不断改进,做出更加优质的作品!!! 

具体代码可根据温湿度传感器节点采集工程自行修改。也可在资源中获取。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容