STM32实现软件IIC协议操作OLED显示屏(2)
时间记录:2024/1/27
一、OLED相关介绍
(1)显示分辨率128*64点阵
(2)IIC作为从机的地址0x78
(3)操作步骤:主机先发送IIC起始信号S,然后发送OLED的地址0x78,然后获取校验位ACK,接着发送控制字节,告诉OLED接下来发送的一个字节数据是指令字节还是数据字节,Co=0,接下来只包含数据,D/C=0时,接下来的是指令字节,D/C=1时,接下来的是数据字节,最后发送一个IIC结束信号
1.3.1 写指令代码
static void vOledWriteCmd(u8 cmd)
{vIICStart();vIICSendByte(0x78);vIICCheckAck();vIICSendByte(0x00);vIICCheckAck();vIICSendByte(cmd);vIICCheckAck();vIICStop();
}
1.3.2 写数据代码
static void vOledWriteData(u8 data)
{vIICStart();vIICSendByte(0x78);vIICCheckAck();vIICSendByte(0x40);vIICCheckAck();vIICSendByte(data);vIICCheckAck();vIICStop();
}
(4)显存GDDRAM大小为128*64
(5)每8COM组成一个Page,共有8Page,即64行
(6)每一个COM中有128个Segment,即128列
(7)在一个Segment中,发送的显示数据,数据高位在下,数据低位在上
二、OLED指令+数据结合使用,先发送命令指令然后发送数据指令
(1)设置对比度,即屏幕亮度
命令 | 数据 |
---|---|
0x81 | 对比度(0-255)0x00-0xFF,默认值0x7F(127) |
实际是设置OLED的驱动电流,对比度设置越大,驱动电流越大,显示亮度就越高。
(2)OLED显示跟随GDDRAM,即向GDDRAM写入显示数据后是否立马改变显示
命令 | 数据 |
---|---|
0xA4:OLED跟随,0xA5:OLED显示固定,不跟随,默认值0xA4 | 无 |
(3)设置反色,即GDDRAM中0还是1表示显示
命令 | 数据 |
---|---|
0xA6:正常显示,1表示显示,0表示不显示,0xA7:反转显示,1表示不显示,0表示显示,默认值0xA6 | 无 |
(4)开启/关闭显示
命令 | 数据 |
---|---|
0xAE:关闭显示,进入睡眠模式,0xAF:开启显示,默认值0xAE | 无 |
(5)设置显示列地址
命令 | 数据 |
---|---|
0x00-0x0F:设置列地址的低四位,默认值0x00,0x10-0x17:设置列地址的高四位,默认值0x10 | 无 |
此设置仅在页寻址模式下有效,两个设置共同决定了显示列的起始地址
(6)设置寻址模式
命令 | 数据 |
---|---|
0x20 | 0x00:行寻址模式,0x01:列寻址模式,0x02:页寻址模式,默认值0x02 |
2.6.1 页寻址模式,一行写入完毕向第1列覆盖显示
2.6.2 水平/行寻址模式,一行写入完毕向下一行的第一列覆盖显示
2.6.3 垂直/列寻址模式
(7)设置列地址
命令 | 数据 |
---|---|
0x21 | 0-127,默认为0,0-127,默认为127 |
此设置仅在行/列寻址模式下有效,两个数据用于设置列起始地址和结束地址
(8)设置页地址
命令 | 数据 |
---|---|
0x22 | 0-7,默认0,0-7,默认7 |
此设置仅在行/列寻址模式下有效,两个数据用于设置页的起始地址和结束地址
(9)设置显示页的起始地址
命令 | 数据 |
---|---|
0xB0-0xB7,默认值0xB0 | 无 |
此设置仅在页寻址模式下有效,用于设置显示页的起始页地址
(10)设置显示开始行
命令 | 数据 |
---|---|
0x40-0x7F:对应64-0行,默认0x40 | 无 |
(11)设置列对于Segment的映射
命令 | 数据 |
---|---|
0xA0:Column0映射到Seg0,0xA1:Column127映射到Seg0,默认值0xA0 | 无 |
(12)设置通道数(分辨率)
命令 | 数据 |
---|---|
0xA8 | 0x01-0x3F,对应1-63,默认63 |
(13)设置COM Driver的扫描方向
命令 | 数据 |
---|---|
0xC0:从COM0扫描到COMN,0xC8:从COMN扫描到COM0,默认值0xC0 | 无 |
(14)设置COM的偏移值,一般设置为0,保证屏幕的完整显示
命令 | 数据 |
---|---|
0xD3 | 0x00-0x3F,默认0 |
(15)设置时钟分频比和时钟频率
命令 | 数据 |
---|---|
0xDA | [3:0]:设置时钟分频比,[7:4]:设置时钟频率,0x12:128x64OLED,0x02:128x32OLED |
(16)操作充电泵
命令 | 数据 |
---|---|
0x8D | 0x10:关闭充电泵,0x14:打开充电泵 |
(17)设置预充电时间
命令 | 数据 |
---|---|
0xD9 | 0x00-0xFF |
(18)设置电压级别
命令 | 数据 |
---|---|
0xDB | 默认值0x20,0.77xVCC |
三、OLED函数实现
(1)初始化函数
void vOledInit(void)
{vIICInit();Delay_Ms(100);vOledWriteCmd(0xA8);//设置分辨率vOledWriteCmd(0x3F);//0x3f : 128*64 0x1f 128*32vOledWriteCmd(0xDA);//设置COM硬件引脚配置,适应分辨率vOledWriteCmd(0x12);//0x12 : 0.96->128*64 0x02 : 0.91->128*32vOledWriteCmd(0xD3);//设置显示偏移vOledWriteCmd(0x00);//默认无偏移vOledWriteCmd(0x40);//设置显示开始0-63vOledWriteCmd(0xA1);//段SEGMENT重映射对于IIC四角OLED要设置为0xA1vOledWriteCmd(0x81);//对比度设置vOledWriteCmd(0xFF);//亮度设置0x00-0xFF,数值越大亮度越大vOledWriteCmd(0xA4);//输出遵循RAM内容,0xA5输出忽略RAM内容vOledWriteCmd(0xA7);//显示方式正常显示,0xA7反向显示,逆码,0点亮还是1点亮vOledWriteCmd(0x8D);//充电泵设置vOledWriteCmd(0x14);//允许在显示开启的时候使用,0x10:不允许在开启前使用vOledWriteCmd(0x20);//设置内存地址模式 水平/垂直/页寻址(默认)vOledWriteCmd(0x02);//水平0x00 垂直0x01 页寻址0x02vOledWriteCmd(0xC8);//设置COM扫描方式0xC0上下反置左到右 0xC8正常右到左vOledWriteCmd(0xB0);//为页寻址模式设置开启地址0-7vOledWriteCmd(0x00);//设置低列地址vOledWriteCmd(0x10);//设置高列地址vOledWriteCmd(0xD9);//设置预充电时期vOledWriteCmd(0x22);//充电时间vOledWriteCmd(0xDB);//设置取消选择级别vOledWriteCmd(0x20);//默认0x20 0.77xvccvOledWriteCmd(0xAF);//显示开启
}
(2)清屏函数
void vOledClear(void)
{for(u8 i=0;i<8;i++){vOledWriteCmd(0xB0|i);vOledWriteCmd(0x00);vOledWriteCmd(0x10);for(u8 j=0;j<128;j++){vOledWriteData(0x00);}}
}
(3)开/关显示
void vOledOn(void)
{vOledWriteCmd(0x8D);//操作充电泵vOledWriteCmd(0x14);//打开vOledWriteCmd(0xAF);
}
void vOledOff(void)
{vOledWriteCmd(0x8D);vOledWriteCmd(0x10);//关闭vOledWriteCmd(0xAE);
}
(4)设置显示位置函数
static void vOledSetPos(int row,int col)//设置显示位置,8行*128列
{vOledWriteCmd(0xB0|row);vOledWriteCmd(col & 0x0F);//列低4位vOledWriteCmd(0x10+((col>>4)&0x0F));//列高4位
}
(5)显示一个英文字符函数
static void vOledShowChar(int row,int col,u8 charData)
{if(row>7 || col> 127) return;int index = charData-' ';//计算ASCII编码位置for(u8 i=0;i<2;i++){vOledSetPos(row+i,col);for(u8 j=0;j<8;j++){vOledWriteData(char8X16[index][i*8+j]);}}
}
取模格式
(6)格式化显示字符串函数
void vOledShowString(int row,int col,u8 *fmtStr,...)
{/******字符串格式化拼接********/int fmtPos = 0;char tempStr[STRMAX];memset(tempStr,0,sizeof(tempStr));int tempPos=0;va_list vaList;va_start(vaList,fmtStr);for(fmtPos=0;fmtPos<strlen((char*)fmtStr);fmtPos++){if(fmtStr[fmtPos] == '%' && fmtStr[fmtPos+1] == 'd'){//格式化输入整数sprintf(tempStr,"%s%d",tempStr,va_arg(vaList,int));tempPos = strlen(tempStr);fmtPos++;}else if(fmtStr[fmtPos] == '%' && fmtStr[fmtPos+1] == 's'){//格式化输入字符串sprintf(tempStr,"%s%s",tempStr,va_arg(vaList,char*));tempPos = strlen(tempStr);fmtPos++;}else if(fmtStr[fmtPos] == '%' && fmtStr[fmtPos+1] == 'f'){//格式化输入小数,小数点后全部保留sprintf(tempStr,"%s%lf",tempStr,va_arg(vaList,double));tempPos = strlen(tempStr);fmtPos++;}else if(fmtStr[fmtPos] == '%' && fmtStr[fmtPos+1] == '.' && fmtStr[fmtPos+3] == 'f'){//格式化输入小数,小数后进行保留指定位switch(fmtStr[fmtPos+2]){//默认6位,选择1-5位保留case '1':sprintf(tempStr,"%s%.1lf",tempStr,va_arg(vaList,double));tempPos = strlen(tempStr);fmtPos+=3;break;case '2':sprintf(tempStr,"%s%.2lf",tempStr,va_arg(vaList,double));tempPos = strlen(tempStr);fmtPos+=3;break;case '3':sprintf(tempStr,"%s%.3lf",tempStr,va_arg(vaList,double));tempPos = strlen(tempStr);fmtPos+=3;break;case '4':sprintf(tempStr,"%s%.4lf",tempStr,va_arg(vaList,double));tempPos = strlen(tempStr);fmtPos+=3;break;case '5':sprintf(tempStr,"%s%.5lf",tempStr,va_arg(vaList,double));tempPos = strlen(tempStr);fmtPos+=3;break;default:sprintf(tempStr,"%s%lf",tempStr,va_arg(vaList,double));tempPos = strlen(tempStr);fmtPos+=3;break;}}else{tempStr[tempPos] = fmtStr[fmtPos];tempPos++;}}va_end(vaList);/******输出显示字符串*******/for(u8 i=0;i<strlen(tempStr);i++){vOledShowChar(row,8*i+col,tempStr[i]);}
}
(7)输出一个汉字函数,文件编码格式需要转换为ANSI编码
static void vOledShowOneChinese(int row,int col,u8 font[2])
{if(row>7 || col> 127) return;int fontCount = sizeof(chinaFont)/sizeof(ChineseStruct);for(int index=0;index<fontCount;index++){if(chinaFont[index].hz[0] == font[0] && chinaFont[index].hz[1] == font[1]){for(int i=0;i<2;i++){vOledSetPos(row+i,col);for(int j=0;j<16;j++){vOledWriteData(chinaFont[index].hzHex[i*16+j]);}}break;}}
}
(8)显示汉字字符串函数
void vOledShowChinaese(int row,int col,u8 *cFont)
{int index=0;u8 tempChina[2];while(cFont[index]!='\0'){tempChina[0] = cFont[index];tempChina[1] = cFont[index+1];vOledShowOneChinese(row,index/2*16+col,tempChina);index+=2;}
}
相关文章:

STM32实现软件IIC协议操作OLED显示屏(2)
时间记录:2024/1/27 一、OLED相关介绍 (1)显示分辨率128*64点阵 (2)IIC作为从机的地址0x78 (3)操作步骤:主机先发送IIC起始信号S,然后发送OLED的地址0x78,然…...

【linux】远程桌面连接到Debian
远程桌面连接到Debian系统,可以使用以下几种工具: 1. VNC (Virtual Network Computing) VNC(Virtual Network Computing)是一种流行的远程桌面解决方案,它使用RFB(Remote Framebuffer Protocol࿰…...

python222网站实战(SpringBoot+SpringSecurity+MybatisPlus+thymeleaf+layui)-菜单管理实现
锋哥原创的SpringbootLayui python222网站实战: python222网站实战课程视频教程(SpringBootPython爬虫实战) ( 火爆连载更新中... )_哔哩哔哩_bilibilipython222网站实战课程视频教程(SpringBootPython爬虫实战) ( 火…...

JS之隐式转换与布尔判定
大家思考一下 [ ] [ ] ? 答案是空字符串 为什么呢? 当做加法运算的时候,发现左右两端存在非原始类型,也就是引用类型对象,就会对对象做隐式类型转换 如何执行的?或者说怎么查找的? 第一步&…...

ubuntu20根目录扩容
ubuntu根目录/ 或者 /home文件夹有时出现空间满了的情况,可以用gparted工具进行空间的重新分配。 首先,如果你是双系统,需要从windows系统下磁盘压缩分配一部分未使用的空间给ubuntu,注意压缩的空间要邻接ubuntu所在盘的位置。 …...

(四)DQL数据查询语言
基础语法 SELECT {*,列名,函数} FROM 表名 [WHERE 条件]; 说明: -SELECT检索关键字 *匹配所有列 , 匹配指定列 -FROM 所提供的数据源(表,视图,另一个查询机制反馈的结果) -WHERE 条件(控制查询的区…...

网络安全03---Nginx 解析漏洞复现
目录 一、准备环境 二、实验开始 2.1上传压缩包并解压 2.2进入目录,开始制作镜像 2.3可能会受之前环境影响,删除即可 编辑 2.4制作成功结果 2.5我们的环境一个nginx一个php 2.6访问漏洞 2.7漏洞触发结果 2.8上传代码不存在漏洞 2.9补充&#…...

第十四届蓝桥杯C组题目 三国游戏
4965. 三国游戏 - AcWing题库 小蓝正在玩一款游戏。 游戏中魏蜀吴三个国家各自拥有一定数量的士兵 X,Y,Z(一开始可以认为都为 00)。 游戏有 n 个可能会发生的事件,每个事件之间相互独立且最多只会发生一次,当第 i个事件发生时会分…...

【LeetCode-435】无重叠区间(贪心)
题目链接 题目简介 给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。 注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。 示例 1: 输入: [ [1,2], [2,3], [3,4…...

写读后感的时候,可以适当地引用书中的内容吗?
写读后感时,适当地引用书中的内容是可以的,这样可以更好地支持你的观点和感受,增强文章的可信度和说服力。 引用书中的内容可以帮助读者更好地理解你所讨论的主题和人物,同时也可以展示你对原著的深入理解和阅读能力。但是&#…...

RockChip DRM Display Driver
资料来源: 《Rockchip_DRM_Display_Driver_Development_Guide_V1.0.pdf》 《Rockchip_Developer_Guide_DRM_Display_Driver_CN.pdf》 一:DRM概述 DRM(Direct Rendering Manager)直接渲染管理,buffer分配,帧缓冲。对应userspace库位libdrm,libdrm库提供了一系列友好的…...

【数据库】GaussDB数据类型和简单DDL概述
GaussDB是一款华为公司开发的关系型数据库管理系统(RDBMS),提供了多种数据类型用于存储和处理不同类型的数据。以下是GaussDB常见的数据类型: 1、GaussDB常见的数据类型 1.1、数值型(Numeric Types)&…...

malloc/free和new/delete相关问题:
面试题: 1、两种方式的区别: (1)malloc需要强制类型转换,new不需要 (2)malloc需要计算空间大小,new不需要 例如:创建5个int类型的空间 int*p(int *)malloc(sizeof(i…...

设计一套扑克牌
约束和假设 这是一幅用于类似扑克和二十一点等游戏的通用扑克牌吗? 我们可以假设这副牌有52张(2-10,杰克,女王,国王,埃斯)和4种花色吗? 我们可以假设输入是有效的,还是需…...

ubuntu20.04 外接hdmi没有声音
pulseaudio -k 请尝试执行该命令...

Mybatis 拦截器注册方式
在MyBatis中注册拦截器可以通过以下三种方式: 1. XML配置文件方式 在Mybatis的核心配置文件(mybatis-config.xml)中的标签下定义拦截器,并指定实现类。 <configuration><!-- ...其他配置... --><plugins><…...

[嵌入式软件][启蒙篇][仿真平台] STM32F103实现SPI控制OLED屏幕
上一篇: [嵌入式软件][启蒙篇][仿真平台] STM32F103实现LED、按键 [嵌入式软件][启蒙篇][仿真平台] STM32F103实现串口输出输入、ADC采集 [嵌入式软件][启蒙篇][仿真平台]STM32F103实现定时器 [嵌入式软件][启蒙篇][仿真平台] STM32F103实现IIC控制OLED屏幕 文章目…...

个体诊所电子处方系统设计,社区门诊处方开单管理系统软件教程
个体诊所电子处方系统设计,社区门诊处方开单管理系统软件教程 一、前言 以下软件程序操作教程以 佳易王诊所电子处方管理系统软件V17.3为例说明 如图,在基本信息设置里,可以设置处方配方模板,这样在开电子处方的时候可以一键导入…...

数据结构(1)--> 顺序表
定义: 顺序表存储定义: 把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构,顺序表功能的实现借助于数组,通过对数组进行封装,从而实现增删查改的功能,严格意义上来说(数组无法实现…...

排序算法经典模型: 梯度提升决策树(GBDT)的应用实战
目录 一、Boosting训练与预测 二、梯度增强的思想核心 三、如何构造弱学习器和加权平均的权重 四、损失函数 五、梯度增强决策树 六、GBDT生成新特征 主要思想 构造流程 七、梯度增强决策树以及在搜索的应用 7.1 GDBT模型调参 7.1.1 框架层面参数 n_estimators su…...

【揭秘】ForkJoinTask全面解析
内容摘要 ForkJoinTask的显著优点在于其高效的并行处理能力,它能够将复杂任务拆分成多个子任务,并利用多核处理器同时执行,从而显著提升计算性能,此外,ForkJoinTask还提供了简洁的API和强大的任务管理机制,…...

如何利用数据压缩提高高性能存储的效率?
在当前信息爆炸的时代,大数据存储和管理成为了各大企业和组织面临的重要挑战之一。高性能存储系统的效率对于数据处理和应用的性能至关重要。而数据压缩技术的应用可以在一定程度上提高高性能存储的效率。 数据压缩技术的作用 数据压缩是通过对数据进行编码和压缩…...

前端工程化之:webpack1-2(安装与使用)
一、webpack简介 webpack中文网 webpack 是基于模块化的打包(构建)工具,它把一切视为模块它通过一个开发时态的入口模块为起点,分析出所有的依赖关系,然后经过一系列的过程(压缩、合并),最终生成运行时态的文件。 webpack的特点&a…...

MySQL索引类型及数据结构【笔记】
1 索引类型 返回面试宝典 主键索引(PRIMARY):数据列不允许重复,不允许为NULL,一个表只能有一个主键。 唯一索引(UNIQUE):数据列不允许重复,允许为NULL,一个表允许多个列创建唯一索引…...

成熟的内外网数据交换方案,如何实现跨网传输?
网络迅速发展,我们可以从网络上查找到各式各样的信息,但是同时网络安全问题也随之严重。近几年,各种有关网络安全的新闻不断被报道,数据泄露给很多企业带来了严重打击,不仅是经济损失,严重者还会对企业的声…...

python11-Python的字符串之repr
有时候,我们需要将字符串与数值进行拼接,而 Python 不允许直接拼接数值和字符串,程序必须先将数值转换成字符串。 为了将数值转换成字符串,可以使用str0或repr()函数,例如如下代码。 # !/usr/bin/env python# -*- co…...

python小项目:口令保管箱
代码: #! python3 # python 编程-----口令保管箱passwords{emails: F7minlBDDuvMJuxESSKHFhTxFtjVB6,blog:VmALvQyKAxiVH5G8v01if1MLZF3sdt,luggage:12345,} import sys,pyperclip if len(sys.argv)<2:print(usage:python python3文件[accout]-copy accout pass…...

微认证 openEuler社区开源贡献实践
文章目录 1. 开源与开源社区2. openEuler 社区概述3.参与openEuler社区贡献4.openEuler软件包开发Linux软件管理——源码编译 1. 开源与开源社区 Richard Matthew Stallman,1983年9月推出GNU项目,并发起自由软件运动(free software movement或free/open…...

紫光展锐M6780丨超分辨率技术——画质重构还原经典
上一期,我们揭秘了让画质更加炫彩的AI-PQ技术。面对分辨率较低的老电影,光有高饱和度的色彩是不够的,如何能够提高视频影像的分辨率,使画质更加清晰,实现老片新看? 本期带大家揭晓紫光展锐首颗AI8K超高清智…...

《Python 简易速速上手小册》第6章:Python 文件和数据持久化(基于最新版 Python3.12 编写)
注意:本《Python 简易速速上手小册》 核心目的在于让零基础新手「快速构建 Python 知识体系」 文章目录 <mark >注意:本《Python 简易速速上手小册》<mark >核心目的在于让零基础新手「快速构建 Python 知识体系」 6.1 文件读写操作6.1.1 打…...