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

STM32:0.96寸OLED屏驱动全解析——SSD1306 I2C通信与显存配置指南

知识点1【0.96OLED显示屏介绍】

1、OLED的介绍

OLED被称作为 第三代显示技术。显示技术与传统的LED不同:无需背光灯具有柔性(采用柔性有机基板),有电流通过时,有机材料会发光。并且OLED屏幕可以做的更轻更薄可视角度更大,能够显著节省耗电量。

缺点是:屏幕价格较贵,无法做大屏幕显示。

2、OLED基本概念介绍

像素点:最小成像单元,每个像素点都是有大小的。

单色屏:1个像素点占1bit

彩色屏:RGB565(16bit);RGB666(18bit);RGB888(24bit)

R——红色,G——绿色,B——蓝色

如RGB(565)

R:5bit

G:6bit

B:5bit

总计16bit

像素:拍照过程中,依次曝光采集的像素点的个数

屏幕分辨率:一个固定尺寸的屏幕容纳的最大像素点个数

3、OLED显示原理

OLED的驱动芯片:SSD1306B

SSD1306是通过I2C与OLED显示屏进行通信的。

SSD1306B的作用:

1、接收单片机发送过来的数据——字符取模 坐标

2、确定当前显示字符的位置

4、SSD1306B介绍

SSD1306B是一款OLED / PLED驱动器。

特点

(1)支持最高128*64点阵单色

(2)单色

(3)内有GDDRAM(Graphic Display Data RAM),可存储整个屏幕的 像素点阵 数据

(4)工作电压 2.4-3.5V(典型值3.3V

(5)I2C接口

(6)指令集控制

知识点2【使用原理介绍】

1、GDDRAM(图形展示数据寄存器)

(1)特点总结

1、存储时,每8行像素为一页,屏幕有64行像素,因此被分为8页

2、每改动某行某列的像素,则 对应页对应列的8个像素将会一起被改动

3、每页每列的显示值都被一个字节定义,最低为对应最小行,最高位对应最高行。

(2)解释

如下图,

类似这样的页,还有7个(总计8个)

我们操作0行0列,即是操作红框的内容。

并且com0 - com7 依次对应的位是从低到高

2、指令集介绍

这里不介绍全部指令集,仅介绍一些常用的,或者说是本博客中会用到的指令集

81 + [0~256] :亮度(对比度)配置

A4:正常显示

A5:纯色显示

A6:1亮0灭 正常显示

A7:1灭0亮 反色显示

AE:关闭显示睡眠模式

AF:打开显示,正常刷新画面

0xD5 + [0-256]:设置显示时钟分割比例与振荡器频率

A[3:0]:设置分割比例;A[7:4]:设置振荡器频率

0x8A + A[5:0]:设置多路复用比例

A[5:0]配置 行扫描数(根据屏幕分辨率) 这个值加1为行数

0xD3 + A[5:0]:设置显示偏移量

0x00

设置起始行的位置 0x40 表示从第0行开始

0xDA + A[5:4] 配置引脚顺序和和复用方式

根据屏幕的型号配置:我们这里是

0xDA + 0x12

配置垂直方向扫描方向

选择反向扫描:即0xC8

配置水平方向扫描方向

选择反向扫描:即0xA1

下面是电池配置

3、OLED初始化流程图

上图即使初始化的流程图,这些需要结合指令来理解,内容很杂,但不难。

解释

大家结合上面的指令分析去理解即可。

我们需要发送的指令有:

0xAE,0xD5,0x80,0xA8,0x3F,0xD3, 0x00,0x40,0xDA,0x12,0xC8,0xA1,0x8D,0x10,0xD9,0x22,0xDB, 0x30,0x81,0x66,0xA4,0xA6,0xAF

共计23个,大家最好依次发送。

4、设备地址和寄存器地址

(1)前三段解读:设备地址

我们从 前3段 中可以得知

设备地址是 b0111 10[SA0][R/W]

SA:是从机地址选择,如3C

地址仅7位,大家记住,这时I2C中的地址标准,因此这里的地址可以是0x3C与0x3D

有两个地址的原因,是为了提高硬件的灵活性。当我们需要连接多个SSD1306(如双屏)的时候,可以通过此两个不同的地址来区别两个屏幕

R/W功能位:决定读,还是写

由于屏幕,常用来 读取数据

因此我们这里经常发送0x0C<<1 | 0 即0x78

(2)后四段解读:寄存器地址

由后四段可以知道:

寄存器地址

[Co][D/C]00 0000

寄存器的地址可以用来配置 单字节模式/连续模式(Co位来决定),后续字节是命令还是【显存数据(GDDRAM)(即我们上面说的GDDRAM中的特定行特定列的8个像素)(D/C位决定)】

  • 单字节模式:

    每次传输仅发送 一个字节的数据或命令,后续操作需重新发送控制字节。

  • 连续模式

    允许连续发送 多个字节的数据或命令,无需重复发送控制字节。

我们选择单字节模式

因此我们

发送数据,命令为0x40

发送指令,命令为0x00

知识点3【代码补充——I2C的发送函数】

由于今天我复习I2C 与 OLED屏幕

I2C还没有来得及整理。

大家先看看一下代码 了解I2C配置的步骤

我将在这周之内补充I2C的内容,希望大家能够理解!

代码演示

I2C.c

#include "i2c.h"int i2c_timeout;void I2C_Config(void)
{GPIO_InitTypeDef GPIO_InitTSources={0};I2C_InitTypeDef  I2C_InitSources;//打开时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);GPIO_InitTSources.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;GPIO_InitTSources.GPIO_Mode=GPIO_Mode_AF_OD;GPIO_InitTSources.GPIO_Speed=GPIO_Speed_10MHz;//PB6  PB7GPIO_Init(GPIOB,&GPIO_InitTSources);//i2c配置I2C_InitSources.I2C_ClockSpeed=100000;//100KHZI2C_InitSources.I2C_Mode=I2C_Mode_I2C;//IIC模式I2C_InitSources.I2C_OwnAddress1=0x00;I2C_InitSources.I2C_Ack=I2C_Ack_Enable;//使能应答I2C_InitSources.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;//7bit从机地址I2C_InitSources.I2C_DutyCycle=I2C_DutyCycle_16_9;I2C_Init(I2C1,&I2C_InitSources);I2C_Cmd(I2C1,ENABLE);
}u8 IIC_Write_Data(uint8_t sla_addr,uint8_t reg_addr,uint8_t data)
{//防止抢占冲突i2c_timeout = I2C_MAX_TIMEOUT_MS;while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY) && i2c_timeout--){//延时1msDelay_ms(1);if(i2c_timeout == 0){//关闭I2C1I2C_GenerateSTOP(I2C1,ENABLE);//返回超时信息return I2C_TRANS_TIMEOUT;}}//打开 加 防超时操作i2c_timeout = I2C_MAX_TIMEOUT_MS;I2C_GenerateSTART(I2C1,ENABLE);while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) && i2c_timeout--){Delay_ms(1);if(!i2c_timeout){I2C_GenerateSTOP(I2C1,ENABLE);return I2C_TRANS_TIMEOUT;}}//发送从设备地址 与 模式,判断是否被选中i2c_timeout = I2C_MAX_TIMEOUT_MS;I2C_Send7bitAddress(I2C1,sla_addr,I2C_Direction_Transmitter);while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && i2c_timeout--){Delay_ms(1);if(!i2c_timeout){I2C_GenerateSTOP(I2C1,ENABLE);return I2C_TRANS_TIMEOUT;}}//判断接收应答 是否正确if(I2C_GetFlagStatus(I2C1,I2C_FLAG_AF)){//清楚标志位I2C_ClearFlag(I2C1, I2C_FLAG_AF);//关闭I2CI2C_GenerateSTOP(I2C1,ENABLE);//返回值return I2C_TRANS_OTHERERR;}//发送从设备的寄存器地址i2c_timeout = I2C_MAX_TIMEOUT_MS;I2C_SendData(I2C1,reg_addr);while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) && i2c_timeout--){Delay_ms(1);if(!i2c_timeout){I2C_GenerateSTOP(I2C1,ENABLE);return I2C_TRANS_TIMEOUT;}}//发送数据i2c_timeout = I2C_MAX_TIMEOUT_MS;I2C_SendData(I2C1,data);while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) && i2c_timeout--){Delay_ms(1);if(!i2c_timeout){I2C_GenerateSTOP(I2C1,ENABLE);return I2C_TRANS_TIMEOUT;}}//停止I2C_GenerateSTOP(I2C1,ENABLE);return I2C_TRANS_SUCCESS;
}

I2C.h

#ifndef _I2C_H_
#define _I2C_H_#include "stm32f10x.h"
#include "delay.h"#define I2C_MAX_TIMEOUT_MS 1000
#define I2C_TRANS_OTHERERR 2
#define I2C_TRANS_TIMEOUT 1
#define I2C_TRANS_SUCCESS 0#endif

结束

代码重在练习!

代码重在练习!

代码重在练习!

今天的分享就到此结束了,希望对你有所帮助,如果你喜欢我的分享,请点赞收藏加关注,谢谢大家!!!

相关文章:

  • 二十、面向对象底层逻辑-ServiceRegistry接口设计集成注册中心
  • AI 多 Agent 图形化开发深度解析:iVX IDE 与主流产品技术架构对比研究
  • 在 Matter.js 物理引擎中,isSensor 布尔属性的使用
  • 【AI问答】Java类中,一些变量设置了@NotNull,怎么在调用内部方法时校验变量是否为空
  • Ubuntu20.04的安装(VMware)
  • LInux—shell编程
  • MySQL的可重复读事务隔离级别的实现原理
  • 人脸识别备案开启安全防护模式!紧跟《办法》!
  • 核实发票的真实性与合法性-发票查验接口-虚假发票防范
  • 前端图片裁剪上传全流程详解:从预览到上传的完整流程
  • python学习 day5
  • Excalidraw云端协作实战:如何用智能绘图打破地理限制?深度解析来了!
  • Java基础 Day18
  • VR光伏车棚虚拟仿真系统:开启绿色能源新视界​
  • VR溺水安全:为生命筑牢数字化防线
  • 模拟退火算法求解01背包问题:从理论到实践的完整攻略
  • 搜维尔科技VR+5G教室建设方案,推动实现教育数字化转型
  • Strands Agents:AWS开源Agent框架的技术与应用全景
  • 多模态大模型技术介绍
  • 作业过程管控——看安全生产信息化平台全方位解决方案
  • wordpress图片不显示/优化大师怎么样
  • 没有网站可以做哪些互联网广告推广/seo公司优化排名
  • 邢台做网站名列前茅/学it什么培训机构好
  • 广州最新疫情公布/今日头条搜索优化怎么做
  • 沈阳哪家网站做的好/苏州seo关键词优化外包
  • 预付网站建设费用会计分录/seo工作内容