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

news2024/12/28 3:55:08

关联: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-7
    WriteCmd(0xc8); //设置COM输出扫描方向
    WriteCmd(0x00); //-设置低列地址
    WriteCmd(0x10); //-设置高列地址
    WriteCmd(0x40); //-设置起始行地址
    WriteCmd(0x81); //设置对比度控制寄存器
    WriteCmd(0xff); //亮度调节 0x00~0xff
    WriteCmd(0xa1); //设置段重新映射0到127
    WriteCmd(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 frequency
    WriteCmd(0xf0); //--set divide ratio
    WriteCmd(0xd9); //--set pre-charge period
    WriteCmd(0x22); //
    WriteCmd(0xda); //--set com pins hardware configuration
    WriteCmd(0x12);
    WriteCmd(0xdb); //--set vcomh
    WriteCmd(0x20); //0x20,0.77xVcc
    WriteCmd(0x8d); //设置DC-DC使能
    WriteCmd(0x14); //
    WriteCmd(0xaf); //--turn on oled panel
    OLED_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, "气压");
}

效果如下图所示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2200456.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows环境安装CentOS7

【注意】安装CentOS需要先安装Vmware虚拟机 【下载前准备】 一、下载CentOS 7镜像文件阿里云镜像开源&#xff0c;点击跳转 二、安装VMware&#xff08;17&#xff09;&#xff1a; a. 官网&#xff0c;点击跳转 b. 许可证&#xff1a;JU090-6039P-08409-8J0QH-2YR7F 安装V…

Aegisub字幕自动化及函数篇(图文教程附有gif动图展示)(二)

目录 template行 template pre-line template line template syl template syl noblank template char template notext template pre-line notext template syl noblank notext template keeptags ​编辑 template loop number 内联变量 ​编辑 remeber函数 re…

提示工程、微调和 RAG

自众多大型语言模型&#xff08;LLM&#xff09;和高级对话模型发布以来&#xff0c;人们已经运用了各种技术来从这些 AI 系统中提取所需的输出。其中一些方法会改变模型的行为来更好地贴近我们的期望&#xff0c;而另一些方法则侧重于增强我们查询 LLM 的方式&#xff0c;以提…

【华为OD机试真题】95、最少面试官数

package mainimport ("fmt""sort" )type s struct {start intend intworkCount int }type duration struct {start intend int }// 查询时间段内是否有可用的面试官 func getFreeS(sList []*s, d *duration, workCountLimit int) (sIndex int)…

CanOpen转Profinet网关与钢成型机等机械集成时发挥的作用

在现代工业自动化领域&#xff0c;不同设备和系统之间的通信至关重要。CanOpen和Profinet是两种广泛应用于工业控制系统的通讯协议。CanOpen通常用于设备级别的通信&#xff0c;而Profinet则更常见于工业以太网&#xff0c;适用于更大范围的系统级控制。当型钢成型机等复杂机械…

@Service代替@Controller注解来标注到控制层的场景?

在SpringBoot开发中&#xff0c;Controller和Service基本上是日常开发中使用的最频繁的两个注解。但你有没考虑过Service代替Controller注解来标注到控制层的场景&#xff1f;换言之&#xff0c;经过Service标注的控制层能否实现将用户请求分发到服务层的功能&#xff1f; 前言…

视频智能分析/AI智能分析网关V4客流统计算法介绍及其在多领域多场景中的应用

随着人工智能技术的快速发展&#xff0c;AI智能分析网关V4作为一种集高性能、低功耗于一体的软硬一体AI边缘计算硬件设备&#xff0c;在工地、工厂、园区、消防、社区、校园等领域展现出强大的应用潜力。本文将详细介绍AI智能分析网关V4的客流统计算法原理及其在多个场景中的应…

[Python] 函数入参中的 *args和**kwargs 是什么意思

Python函数中*args和**kwargs的用法&#xff0c;它们允许接收任意数量的位置参数和关键字参数。*args用于非关键字的可变参数&#xff0c;而**kwargs则用于接受键值对的可变参数。在调用函数时&#xff0c;字典参数需置于单实例参数之后。示例代码展示了如何定义和使用这些可变…

上海马拉松2024年:城市律动,跑者狂欢

随着2024年的脚步日益临近&#xff0c;上海这座国际化大都市即将迎来一场体育盛事——上海马拉松。作为城市律动与跑者狂欢的完美结合&#xff0c;上海马拉松不仅吸引了来自世界各地的跑者&#xff0c;更成为了展现上海城市魅力和体育精神的重要窗口。 本次上海马拉松将于2024年…

每日OJ题_牛客_AB13【模板】拓扑排序_C++_Java

目录 牛客_AB13【模板】拓扑排序 题目解析 C代码 Java代码 牛客_AB13【模板】拓扑排序 【模板】拓扑排序_牛客题霸_牛客网 (nowcoder.com) 描述&#xff1a; 给定一个包含nn个点mm条边的有向无环图&#xff0c;求出该图的拓扑序。若图的拓扑序不唯一&#xff0c;输出任意合法…

The Sandbox 全新游戏赛季 Alpha 第 4 季完整攻略

欢迎来到 Alpha 第 4 季攻略&#xff01; 准备好投入 The Sandbox 有史以来最令人兴奋的游戏赛季吧&#xff01;我们诚邀你于 10 月 9 日晚上 10 点&#xff08;北京时间&#xff09;&#xff0c;加入我们为期 10 周的精彩平台活动&#xff0c;其中包含超过 100 个独特游戏体验…

杭州悦数参与制定的图技术国家标准项目进入公示期!

9 月 27 日&#xff0c;由全国智能计算标准化工作组归口&#xff0c;杭州悦数科技有限公司等多家知名企业及科研机构共同参与的 《智能计算 图计算性能测试方法》 国家标准项目正式进入公示期。作为第一个图技术相关的国家标准&#xff0c;这一里程碑式的进展&#xff0c;不仅标…

【韩顺平Java笔记】第8章:面向对象编程(中级部分)【297-313】

文章目录 297. super基本语法297.1 基本介绍297.2 基本语法 298. super使用细节1299. super使用细节2300. super使用细节3301. 方法重写介绍302. 方法重写细节303. 重写课堂练习1304. 重写课堂练习2输出结果&#xff1a; 姓名&#xff1a;田所浩二 年龄:24305. 养宠物引出多态3…

直面商标管理难题,开启商标管理系统的解决方案

商标管理对于企业的品牌建设和市场竞争至关重要。然而&#xff0c;商标管理并非一帆风顺&#xff0c;其中存在着诸多难题。 1. 商标监测与侵权防范&#xff1a;随着市场竞争的加剧&#xff0c;及时发现潜在的侵权行为变得越来越困难。监测范围广泛&#xff0c;包括线上线下各种…

华为免费杀毒软件 | HiSec Endpoint 智能终端安全系统

HiSec Endpoint智能终端安全系统是由华为开发的一款全面的终端安全防护产品。该系统的核心目的是保护终端资产的安全&#xff0c;防止各种网络威胁。能够实时感知终端异常行为&#xff0c;多维检测识别潜在安全威胁&#xff0c;自动处置威胁事件&#xff0c;智能溯源入侵路径&a…

直击工博会 | 万物集与四大供应商强强联手,开启战略合作新纪元!

9月24日&#xff0c;第24届中国国际工业博览会在国家会展中心&#xff08;上海&#xff09;开幕。本届工博会设置数控机床与金属加工展、工业自动化展、节能与工业配套展、新一代信息技术与应用展等9大专业主题展&#xff0c;吸引28个国家和地区2600家企业参展。万物集作为参展…

SeaboxSQL

目录 一、基本架构 0、数据模型 1、主从集群 2、分库分表 二、部署安装 1、配置要求 2、前置依赖 3、安装步骤 三、基本操作 1、实例启停 2、命令执行 3、基本查询 4、表空间管理 4、用户管理 6、数据库操作 7、SCHEMA操作 8、表操作 9、日志操作 &…

立即升级!Windows11 24H2 正式版 V26100.2033!

今日&#xff0c;系统之家小编给您带来2024年10最新推出了Windows11 24H2正式版系统下载&#xff0c;该版本系统以微软官方Windows11 24H2 26100.2033 专业版为基础&#xff0c;展开离线制作与优化&#xff0c;安全无毒&#xff0c;且修复了之前版本存在的蓝屏、绿屏等问题&…

多模态大语言模型(MLLM)-InstructBlip深度解读

前言 InstructBlip可以理解为Blip2的升级版&#xff0c;重点加强了图文对话的能力。 模型结构和Blip2没差别&#xff0c;主要在数据集收集、数据集配比、指令微调等方面下文章。 创新点 数据集收集&#xff1a; 将26个公开数据集转换为指令微调格式&#xff0c;并将它们归类…

五、Python基础语法(程序的输入和输出)

一、输入 输入&#xff1a;输入就是获取键盘输入的数据&#xff0c;使用input()函数。代码会从上往下执行&#xff0c;当遇到input()函数&#xff0c;就会暂停执行&#xff0c;输入内容后&#xff0c;敲回车键&#xff0c;表示本次的输入结束。input函数得到的数据类型都是字符…