当前位置: 首页 > news >正文

基于LORA的一主多从监测系统_0.96OLED

关联:0.96OLED         hal硬件I2C         LORA

在本项目中每个节点都使用oled来显示采集到的数据以及节点状态,OLED使用I2C接口与STM32连接,这个屏幕内部驱动IC为SSD1306,SSD1306作为从机地址为0x78

发送数据:起始信号-从机地址-应答-写数据模式(0x40)-应答-数据(8bit)-结束信号

发送命令:起始信号-从机地址-应答-写命令模式(0x00)-应答-命令(8bit)-结束型号

我这里使用硬件I2C,使用HAL的I2C操作函数HAL_I2C_Mem_Write,这个函数是在阻塞模式下将大量数据写入特定的内存地址,函数原型为:HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

参数:1、I2C指针,即用I2C1 还是 I2C2… 2、器件地址uint16_t DevAddress 3、要写入的内存地址 uint16_t MemAddress 4、内存地址类型,是一个地址存8bit ,还是16bit数据 , uint16_t MemAddSize 5、要写入的数组指针uint8_t *pData 6、数据 大小 7、超时时间。下面是用这个函数封装的两个命令发送函数:

/**
* @brief  向OLED寄存器地址写一个byte的数据
* @param  addr:寄存器地址
* @param  data:要写入的数据
* @retval 无
*/
void I2C_WriteByte(uint8_t addr, uint8_t data)
{extern I2C_HandleTypeDef hi2c1;HAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS, addr, I2C_MEMADD_SIZE_8BIT, &data, 1, 10);
}/*** ************************************************************************* @brief 写命令函数* @param[in] cmd  写入的命令* *************************************************************************/
void WriteCmd(unsigned char cmd)
{I2C_WriteByte(0x00, cmd);
}/*** ************************************************************************* @brief 写数据函数* @param[in] dat  写入的数据* *************************************************************************/
void WriteDat(unsigned char dat)
{I2C_WriteByte(0x40, dat);
}

下面是初始化对一些参数的配置:

void OLED_Init(void)
{WriteCmd(0xAE); //显示关闭WriteCmd(0x20); //设置内存寻址模式WriteCmd(0x10); //00,水平寻址模式;01,垂直寻址模式;10,页寻址模式(复位);11,无效WriteCmd(0xb0); //设置页寻址模式的页起始地址,0-7WriteCmd(0xc8); //设置COM输出扫描方向WriteCmd(0x00); //-设置低列地址WriteCmd(0x10); //-设置高列地址WriteCmd(0x40); //-设置起始行地址WriteCmd(0x81); //设置对比度控制寄存器WriteCmd(0xff); //亮度调节 0x00~0xffWriteCmd(0xa1); //设置段重新映射0到127WriteCmd(0xa6); //设置正常显示WriteCmd(0xa8); //设置复用比例(1到64)WriteCmd(0x3F); //WriteCmd(0xa4); //0xa4,输出遵循RAM内容;0xa5,输出忽略RAM内容WriteCmd(0xd3); //设置显示偏移WriteCmd(0x00); //不偏移WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequencyWriteCmd(0xf0); //--set divide ratioWriteCmd(0xd9); //--set pre-charge periodWriteCmd(0x22); //WriteCmd(0xda); //--set com pins hardware configurationWriteCmd(0x12);WriteCmd(0xdb); //--set vcomhWriteCmd(0x20); //0x20,0.77xVccWriteCmd(0x8d); //设置DC-DC使能WriteCmd(0x14); //WriteCmd(0xaf); //--turn on oled panelOLED_CLS();
}

我们不需要去研究这个具体每项配置的作用,我们只需要关注如何显示我们所需要的,我这里提供三个接口函数,分别用来显示汉字、字符、数字,具体方法如下:

/*** ************************************************************************* @brief 中文汉字显示函数** @param[in] x     起始点横坐标(0~127)* @param[in] y     起始点纵坐标(0~63)* @param[in] ch    汉字字模库索引** @example OLED_ShowCN(0,0,"字");* *************************************************************************/
void OLED_ShowChinese(signed short int x, signed short int y, unsigned char* ch)
{if (x >= 0 && x < SCREEN_COLUMN && y >= 0 && y < SCREEN_ROW) {int32_t  len = 0,offset = sizeof(F16x16_CN[0].index);while(ch[len] != '\0'){if(x >= 127 || (127-x < 16))//8个汉字显示||剩余列小于16不能显示完整字符,换行显示{x = 0;y += 16;if(63 - y < 16) // 不足以显示一行时不显示break;}//需要处理输入数据大于显示数据的问题for(unsigned char i = 0; i < sizeof(F16x16_CN)/sizeof(GB2312_CN); i++){if(((F16x16_CN[i].index[0] == ch[len]) && (F16x16_CN[i].index[1] == ch[len+1]))){for(unsigned char m = 0; m < 2; m++)    //页{for(unsigned char n = 0; n < 16; n++) // 列{for(unsigned char j = 0; j < 8; j++)    // 行{OLED_SetPixel(x+n, y+j+m*8, (F16x16_CN[i].encoder[n+m*16] >> j) & 0x01);}}}x += 16;len += offset;break;}else if(F16x16_CN[i].index[0] == ch[len] && ch[len] == 0x20){for(unsigned char m = 0; m < 2; m++){for(unsigned char n = 0; n < 16; n++){for(unsigned char j = 0; j < 8; j++){OLED_SetPixel(x+n, y+j+m*8, (F16x16_CN[i].encoder[n+m*16] >> j) & 0x01);}}}x += 16;len++;break;}}}}OLED_RefreshRAM();
}/*** ************************************************************************* @brief BMP图片显示函数** @param[in] x0    起始点横坐标(0~127)* @param[in] y0    起始点纵坐标(0~63)* @param[in] L     BMP图片宽度* @param[in] H     BMP图片高度* @param[in] BMP   图片取模地址** @example OLED_ShowBMP(0,0,52,48,(unsigned char *)astronaut_0);* *************************************************************************/
void OLED_ShowBMP(signed short int x0,signed short int y0,signed short int L,signed short int H,const unsigned char BMP[])
{if (x0 >= 0 && x0 < SCREEN_COLUMN && x0+L <= SCREEN_ROW &&\y0 >= 0 && y0 < SCREEN_COLUMN && y0+H <= SCREEN_ROW) {unsigned char *p = (unsigned char *)BMP;for(signed short int y = y0; y < y0+H; y+=8){for(signed short int x = x0; x < x0+L; x++){for(signed short int i = 0; i < 8; i++){OLED_SetPixel(x, y+i, ((*p) >> i) & 0x01);}p++;}}}OLED_RefreshRAM();
}/*** ************************************************************************* @brief 数字显示函数** @param[in] x          起始点横坐标(0~127)* @param[in] y          起始点纵坐标(0~63)* @param[in] number     要显示的数字(可以是整数或浮点数)* @param[in] TextSize   字符大小(1:6*8;2:8*16)* @param[in] decimalPlaces   小数位数(例如:2 表示显示两位小数)** *************************************************************************/
void OLED_ShowNumber(signed short int x, signed short int y, float number, unsigned char TextSize, unsigned char decimalPlaces)
{char buffer[20]; // 预留空间以存放数字转换为字符串后的结果,包括符号和终止符// 构造格式字符串,%.*f 表示动态设置小数位数sprintf(buffer, "%.*f", decimalPlaces, number); // 将浮点数转换为字符串OLED_ShowStr(x, y, (unsigned char *)buffer, TextSize); // 调用显示字符串的函数
}

通过以上接口函数,我们可以控制在屏幕上显示我们想要显示的东西

void oledUIShow(void){OLED_ShowStr(0, 0, "DEVICE.1", 1);OLED_ShowStr(62, 0, "ADDR:0x0A", 1);OLED_ShowChinese(0, 16, "温度");OLED_ShowChinese(68, 16, "湿度");OLED_ShowStr(118, 16, "%", 2);OLED_ShowChinese(0, 40, "光照");OLED_ShowChinese(54, 40, "气压");
}

效果如下图所示:

相关文章:

基于LORA的一主多从监测系统_0.96OLED

关联&#xff1a;0.96OLED hal硬件I2C LORA 在本项目中每个节点都使用oled来显示采集到的数据以及节点状态&#xff0c;OLED使用I2C接口与STM32连接&#xff0c;这个屏幕内部驱动IC为SSD1306&#xff0c;SSD1306作为从机地址为0x78 发送数据&#xff1a;起始…...

C#系统学习路线

分享一个C#程序员的成长学习路线规划&#xff0c;希望能够帮助到想从事C#开发的你。 我一直在想&#xff0c;初学者刚开始学习编程时应该学些什么&#xff1f;学习到什么程度才能找到工作&#xff1f;才能在项目中发现和解决Bug&#xff1f; 我不知道每位初学者在学习编程时是…...

UI开发:从实践到探索

UI开发&#xff1a;从实践到探索 参考博客文章&#xff1a;https://blog.jim-nielsen.com/2024/sanding-ui/ 在现代web开发中&#xff0c;用户界面&#xff08;UI&#xff09;的重要性不言而喻。一个优秀的UI不仅能提升用户体验&#xff0c;还能直接影响产品的成功。 UI开发…...

操作系统 | 学习笔记 | 王道 | 3.1 内存管理概念

3 内存管理 3.1 内存管理概念 3.1.1 内存管理的基本原理和要求 内存可以存放数据&#xff0c;程序执行前需要先放到内存中才能被CPU处理—缓和cpu和磁盘之间的速度矛盾 内存管理的概念 虽然计算机技术飞速发展&#xff0c;内存容量也在不断扩大&#xff0c;但仍然不可能将所有…...

Unity射线之拾取物体

实现效果&#xff1a; 可以移动场景内物品放置到某个位置。通过射线检测&#xff0c;点击鼠标左键&#xff0c;移动物体&#xff0c;再点击左键放下物体。 效果&#xff1a; 移动物体 实现思路&#xff1a; 通过射线检测&#xff0c;将检测到的物体吸附到摄像机前的一个空物…...

Python的numpy库矩阵计算(数据分析)

一、创建矩阵 import numpy as np#创建矩阵anp.arange(15).reshape(3,5) bnp.arange(15,30).reshape(3,5) 使用arrange和reshape创建的二维数组就可以看成矩阵。 此时a和b存储的是&#xff1a; [[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14]] [[15 16 17 18 19]…...

R语言的基本语句及基本规则

0x01 赋值语句 使用 “<-” 或 “” 进行赋值。例如&#xff1a; x <- 5 # 将数值 5 赋值给变量 x y 10 # 另一种赋值方式0x02 输出语句 使用 print() 函数输出内容。例如&#xff1a; print("Hello, R!") print(x)0x03 注释语句 任何在 #之后的内容在…...

网络受限情况下安装openpyxl模块提示缺少Jdcal,et_xmlfile

1.工作需要处理关于Excel文件内容的东西 2.用公司提供的openpyxl模块总是提示缺少jdcal文件,因为网络管控,又没办法直接使用命令下载&#xff0c;所以网上找了资源&#xff0c;下载好后上传到个人资源里了 资源路径 openpyxl jdcal et_xmlfile 以上模块来源于&#xff1a;Py…...

【算法】- 查找 - 散列表查询(哈希表)

文章目录 前言一、哈希表的思想二、哈希表总结 前言 散列技术&#xff1a;在记录的存储位置和它的关键字之间建立一个确定的对应关系f&#xff0c;使得每个关键字key对应一个存储位置f(key) 哈希表&#xff1a;采用散列技术将记录存储在一块连续的存储空间中&#xff0c;这块连…...

货币政策工具

本文为个人学习笔记&#xff0c;内容源于教材&#xff1b;整理记录的同时也作为一种分享。 1. 简介 货币政策工具作为央行实现货币政策目标的经济手段&#xff0c;以期达到最终目标&#xff0c;即物价稳定&#xff0c;充分就业&#xff0c;经济增长&#xff0c;国际收支平衡。…...

std::async概念和使用方法

std::async是 C 标准库中的一个函数模板&#xff0c;用于启动一个异步任务&#xff0c;并返回一个std::future对象&#xff0c;该对象可用于获取异步任务的结果。 1、概念 std::async允许你以异步的方式执行一个函数或者可调用对象&#xff0c;它会在后台启动一个新的线程或者…...

Chatgpt 原理解构

一、背景知识 1. 自然语言处理的发展历程 自然语言处理在不同时期呈现出不同的特点和发展态势。萌芽期&#xff0c;艾伦・图灵在 1936 年提出 “图灵机” 概念&#xff0c;为计算机诞生奠定基础&#xff0c;1950 年他提出著名的 “图灵测试”&#xff0c;预见了计算机处理自然…...

【每日刷题】Day135

【每日刷题】Day135 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. LCR 011. 连续数组 - 力扣&#xff08;LeetCode&#xff09; 2. 【模板】二维前缀和_牛客题霸_牛客…...

Linux运维01:VMware创建虚拟机

视频链接&#xff1a;05.新建VM虚拟机_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1nW411L7xm/?p14&spm_id_from333.880.my_history.page.click&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 1.点击“创建虚拟机” 2.选择“自定义&#xff08;高级&#xff0…...

服务器平均响应时间和数据包大小关系大吗?

服务器的平均响应时间与数据包大小有一定的关系&#xff0c;但这只是影响响应时间的众多因素之一。具体来说&#xff0c;数据包大小对服务器响应时间的影响可以从以下几个方面来理解&#xff1a; 1. 数据传输时间 影响: 较大的数据包需要更多的时间在网络上传输&#xff0c;因此…...

Vue入门-指令学习-v-show和v-if

v-show&#xff1a; 作用&#xff1a;控制元素的显示隐藏 语法&#xff1a;v-show"表达式" 表达式值true显示&#xff0c;false隐藏 v-if 作用&#xff1a;控制元素的显示隐藏&#xff08;条件渲染&#xff09; 语法&#xff1a; vif"表达式" 表达式tr…...

nacos多数据源插件介绍以及使用

概述 在微服务架构中&#xff0c;服务配置的集中管理和动态调整是至关重要的。Nacos 提供了配置管理和服务发现的功能&#xff0c;其中配置管理支持动态数据源的切换&#xff0c;增强了其在复杂环境中的适用性。默认情况下&#xff0c;Nacos 支持 MySQL 和Derby&#xff0c;但…...

国庆档不太热,影视股“凉”了?

今年国庆档票房止步21亿元&#xff0c;属实有点差强人意。 根据国家电影局统计&#xff0c;2024年国庆档&#xff08;2024年10月1日至7日&#xff09;全国电影票房为21.04亿元&#xff0c;观影人次为5209万&#xff0c;总票房成绩、观影总人次同比均有所下滑。 作为传统观影高…...

QtDesign预览的效果与程序运行的结果不一致的解决方法

存在的问题 使用Qt designer软件设计出来的界面&#xff0c;与转换成python程序运行出来的结果不一致&#xff0c;具体看下图 Qt designer预览结果 程序运行出来的结果 原因分析 我自己的电脑是2560*1600分辨率的屏幕&#xff0c;采用的是200%的缩放比例&#xff0c;出现这种…...

模运算和快速幂

文章目录 模运算快速幂 模运算 模运算是大数运算中的常用操作。如果一个数太大&#xff0c;无法直接输出&#xff0c;或者不需要直接输出&#xff0c;则可以对它取模&#xff0c;缩小数值再输出。取模可以防止溢出&#xff0c;这是常见的操作。 取模运算一般要求a和m的符号一…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...