前言
基于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_HEAD
、CMD_READ
、ACK_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通道0(ADC_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
采集传感器数据。
程序烧写
结果显示
感谢各位读者的阅读!希望大家给出一键三连,多多支持原创。有错误和不解的地方,欢迎各位读者在评论区讨论,我也会不断学习不断改进,做出更加优质的作品!!!
具体代码可根据温湿度传感器节点采集工程自行修改。也可在资源中获取。
暂无评论内容