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…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
