【STM32CubeMX】教程二_IIC驱动0.96oled屏幕(SSD1306)
前言
本篇博客涉及以下内容
- IIC通讯原理讲解、代码编写
- SSD1306驱动芯片datasheet讲解、驱动代码编写、0.96oled模块原理图说明
- STM32CubeMX配置IIC
使用硬件:STM32F103C8T6
使用软件:STM32CubeMX、keil5(MDK)、VSCode(搭载keil assistant插件)
提示:以下是本篇文章正文内容
一、IIC通讯
在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和片上外设。STM32HAL 库则是在寄存器与用户代码之间的软件层。
对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和协议层。物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。
1.IIC物理层
IIC(Inter-Integrated Circuit)总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接微控制器以及其外围设备。它是由数据线 SDA 和时钟线 SCL 构成的串行总线,可发送和接收数据,在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送。
SDA(Serial data)是数据线,D代表Data也就是数据,Send Data 也就是用来传输数据的
SCL(Serial clock line)是时钟线,C代表Clock 也就是时钟 也就是控制数据发送的时序的
IIC作为一种低数半双工总线,通信速率比SPI低,常见的半双工还有485,SPI和USART都是全双工。
全双工:同一时间可以双向通信,即可以同时接收,发送数据。
半双工:同一时间只能单向通信,即同一时间只能接收或者发送数据。
常见的IIC通讯接线方式如下图:
IIC设备分为主设备和从设备,基本上谁控制时钟线(即控制SCL的电平高低变换)谁就是主设备
。
它的物理层有如下特点:
(1) 它是一个支持设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线中,可连接多个 IIC 通讯设备,支持多个通讯主机及多个通讯从机。
主机从机概念:
主机就是负责整个系统的任务协调与分配.发布主要命令的称为主机。
从机一般是通过接收主机的指令从而完成某些特定的任务,主机和从机之间通过总线连接,进行数据通讯。
(2) 一个 IIC 总线只使用两条总线线路,一条双向串行数据线 (SDA) ,一条串行时钟线 (SCL)
。数据线即用来表示数据,时钟线用于数据收发同步。
(3) 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。
(4) 总线通过上拉电阻接到电源。当 IIC 设备空闲时,会输出高阻态
,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。
(5) 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
(6) 具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式下可达 3.4Mbit/s,但目前大多 IIC 设备尚不支持高速模式。
(7) 连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制。
2.IIC协议层
学习IIC协议之前,我们先看一下它的总线时序图
IIC 的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。
-
① 起始信号
当 SCL 为高电平期间,SDA 由高到低的跳变。
起始信号是一种电平跳变时序信号,而不是一个电平信号。该信号由主机发出,在起始信号产生后,总线就处于被占用状态,准备数据传输。
代码如下:
void iic_start(void)
{
IIC_SDA(1); /* SDA置高 */
IIC_SCL(1); /* SCL置高 */
iic_delay();
IIC_SDA(0); /* START信号: 当SCL为高时, SDA从高变成低, 表示起始信号 */
iic_delay();
IIC_SCL(0); /* 钳住I2C总线,准备发送或接收数据 */
iic_delay();
}
-
② 停止信号
当 SCL 为高电平期间,SDA 由低到高的跳变。
停止信号也是一种电平跳变时序信号,而不是一个电平信号。该信号由主机发出,在停止信号发出后,总线就处于空闲状态。
代码如下:
void iic_stop(void)
{
IIC_SDA(0); /* STOP信号: 当SCL为高时, SDA从低变成高, 表示停止信号 */
iic_delay();
IIC_SCL(1);
iic_delay();
IIC_SDA(1); /* 发送I2C总线结束信号 */
iic_delay();
}
-
③ 数据传输
在 I2C 总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在 SCL 串行时钟的配合下,在 SDA 上逐位地串行传送每一位数据。数据位的传输是边沿触发。 -
④ 数据有效性
IIC 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。IIC 总线进行数据传送时,SCL 为高电平的时候 SDA 表示的数据有效,即此时的 SDA 为高电平时表示数据“1”,为低电平时表示数据“0”。当 SCL 为低电平时,SDA 的数据无效,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化.
数据在 SCL 的上升沿到来之前就需准备好。并在下降沿到来之前必须稳定。
每次数据传输都以字节为单位,每次传输的字节数不受限制。 -
⑤ 应答信号
发送方每发送一个字节(一个字节8位),由接收方反馈一个应答信号(在第9个时钟信号期间),包括“应答 (ACK)”和“非应答 (NACK)”两种信号。应答信号为低电平时,规定为有效应答位(ACK 简称应答位),表示接收方已经成功地接收了该字节,发送方会继续发送下一个数据;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功
,发送方接收到该信号后会产生一个停止信号,结束信号传输。
传输时主机产生时钟,在第 9 个时钟时,数据发送端会释放 SDA 的控制权,由数据接收端控制SDA,若 SDA 为高电平,表示非应答信号 (NACK),低电平表示应答信号 (ACK)。
代码如下:
void iic_ack(void)
{
IIC_SDA(0); /* SCL 0 -> 1 时 SDA = 0,表示应答 */
iic_delay();
IIC_SCL(1); /* 产生一个时钟 */
iic_delay();
IIC_SCL(0);
iic_delay();
IIC_SDA(1); /* 释放SDA线 */
iic_delay();
}
-
⑥ 空闲状态
IIC 总线的 SDA 和 SCL 两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。 -
⑦ 读写通讯过程
I2C 总线上的每个设备都有自己的独立地址,主机发起通讯时,通过 SDA 信号线发送设备地址(SLAVE_ADDRESS) 来查找从机。I2C 协议规定设备地址可以是 7 位或 10 位,实际中 7 位的地址应用比较广泛。紧跟设备地址的一个数据位用来表示数据传输方向,它是数据方向位 (R/w),第 8位或第 11 位。数据方向位为“1”时表示主机由从机读数据,该位为“0”时表示主机向从机写数据。
IIC 的基本的读写通讯过程,包括主机写数据到从机即写操作,主机到从机读取数据即读操作。下面先看一下写操作通讯过程图
主机首先在 IIC 总线上发送起始信号,那么这时总线上的从机都会等待接收由主机发出的
数据。主机接着发送从机地址+0(写操作)组成的 8/11bit 数据,所有从机接收到该 8/11bit 数据后,自行检验是否是自己的设备的地址,假如是自己的设备地址,那么从机就会发出应答信号。主机在总线上接收到有应答信号后,才能继续向从机发送数据。
注意:IIC 总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。
写数据
若配置的方向传输位为“写数据”方向。如下图:广播完地址,接收到应答信号后,主机开始正式向从机传输数据 (DATA),数据包的大小为 8 位,主机每发送完一个字节数据,都要等待从机的应答信号 (ACK),重复这个过程,可以向从机传输 N 个数据,这个 N 没有大小限制。当数据传输结束时,主机向从机发送一个停止传输信号 §,表示不再传输数据。
代码如下:
uint8_t iic_read_byte(uint8_t ack)
{
uint8_t i, receive = 0;
for (i = 0; i < 8; i++ ) /* 接收1个字节数据 */
{
receive <<= 1; /* 高位先输出,所以先收到的数据位要左移 */
IIC_SCL(1);
iic_delay();
if (IIC_READ_SDA)/* 接收到高电平‘1’ */
{
receive++;
}
IIC_SCL(0);
iic_delay();
}
if (!ack)
{
iic_noack(); /* 发送nACK */
}
else
{
iic_ack(); /* 发送ACK */
}
return receive;
}
读数据
若配置的方向传输位为“读数据”方向。如下图:广播完地址,接收到应答信号后,从机开始向主机返回数据 (DATA),数据包大小也为 8 位,从机每发送完一个数据,都会等待主机的应答信号 (ACK),重复这个过程,可以返回 N 个数据,这个 N 也没有大小限制。当主机希望停止接收数据时,就向从机返回一个非应答信号 (NACK),则从机自动停止数据传输。
void iic_send_byte(uint8_t data)
{
uint8_t t;
for (t = 0; t < 8; t++)/* 一个字节8位,发送一个字节需要八个时钟周期 */
{
IIC_SDA((data & 0x80) >> 7); /* 高位先发送 */
iic_delay();
IIC_SCL(1);
iic_delay();
IIC_SCL(0);
data <<= 1; /* 左移1位,用于下一次发送 */
}
IIC_SDA(1); /* 发送完成, 主机释放SDA线,检测接收端应答信号 */
}
读写数据
除了基本的读写,I2C 通讯更常用的是复合格式。如下图该传输过程有两次起始信号 (S)。一般在第一次传输中,主机通过 SLAVE_ADDRESS 寻找到从设备后,发送一段“数据”,这段数据通常用于表示从设备内部的寄存器或存储器地址 (注意区分它与 SLAVE_ADDRESS 的区别);在第二次的传输中,对该地址的内容进行读或写。也就是说,第一次通讯是告诉从机读写地址,第二次则是读写的实际内容。以上通讯流程中包含的各个信号分解如下:
3.STM32的 II 特性及架构
3.1 软件IIC
如果我们直接控制 STM32 的两个 GPIO 引脚,分别用作 SCL 及 SDA,按照上述信号的时序要求,直接像控制 LED 灯那样控制引脚的输出 (若是接收数据时则读取 SDA 电平),就可以实现 I2C 通讯。由于直接控制 GPIO 引脚电平产生通讯时序时,需要由 CPU 控制每个时刻的引脚状态,所以称之为“软件模拟协议”
方式。优点就是不管是 ST 生产的控制器还是 ATMEL 生产的存储器,都能按通讯标准交互。
3.2 硬件IIC
STM32 的 I2C 片上外设专门负责实现 I2C 通讯协议,只要配置好该外设,它就会自动根据协议要求产生通讯信号,收发数据并缓存起来,CPU 只要检测该外设的状态和访问数据寄存器,就能完成数据收发,称之为“硬件协议”
方式。优点就是由硬件外设处理 I2C 协议的方式减轻了CPU 的工作,且使软件设计更加简单。
4.软件IIC代码
本代码适用于HAL库与标准库,两者切换仅需更改iic_init()与头文件。
软件IIC代码的编写应当具有高度可移植性,方便用于不同款的MCU,上出已近列写部分代码,此处仅列出STM2初始化GPIO代码和.h文件代码。完整代码链接在文章末。
4.1 IIC.c
void iic_init(void)
{
/******************************************************************************************/
/*HAL库版本*/
GPIO_InitTypeDef gpio_init_struct;
IIC_SCL_GPIO_CLK_ENABLE(); /* SCL引脚时钟使能 */
IIC_SDA_GPIO_CLK_ENABLE(); /* SDA引脚时钟使能 */
gpio_init_struct.Pin = IIC_SCL_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* 快速 */
HAL_GPIO_Init(IIC_SCL_GPIO_PORT, &gpio_init_struct);/* SCL */
gpio_init_struct.Pin = IIC_SDA_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD; /* 开漏输出 */
HAL_GPIO_Init(IIC_SDA_GPIO_PORT, &gpio_init_struct);/* SDA */
/* SDA引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1), 也可以读取外部信号的高低电平 */
/******************************************************************************************/
/*标准库版本*/
/*
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//ʹÄÜGPIOBʱÖÓ
//GPIOB7,B8初始化
GPIO_InitStructure.GPIO_Pin = IIC_SCL_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(IIC_SCL_GPIO_PORT, &GPIO_InitStructure); //SCL
GPIO_InitStructure.GPIO_Pin = IIC_SDA_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(IIC_SDA_GPIO_PORT, &GPIO_InitStructure); //SDA
*/
/******************************************************************************************/
IIC_SCL(1); /* 总线空闲状态 */
IIC_SDA(1);
}
4.2 IIC.h
/*
****************************************************************************************************
* @file IIC.h
* @author 橙子太
* @version V1.0
* @date 2023-1-8
* @brief 软件IIC 驱动代码
****************************************************************************************************
* @attention
*
* 实验平台:STM32F103C8T6
*
* 修改说明
* V1.0 2023-1-8
* 第一次编写
*
* 本代码仅用于个人学习使用
*
****************************************************************************************************
*@引脚接线
* PB6---->SCL
* PB7---->SDL
*
****************************************************************************************************
*/
#ifndef __IIC_H
#define __IIC_H
#include "stm32f1xx_hal.h"
//#include "stm32f1xx.h"
/******************************************************************************************/
#ifndef uint32_t
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
#endif
/******************************************************************************************/
/* 引脚 定义 */
#define IIC_SCL_GPIO_PORT GPIOB
#define IIC_SCL_GPIO_PIN GPIO_PIN_6
#define IIC_SCL_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */
#define IIC_SDA_GPIO_PORT GPIOB
#define IIC_SDA_GPIO_PIN GPIO_PIN_7
#define IIC_SDA_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */
/******************************************************************************************/
/* IO操作 */
#define IIC_SCL(x) do{ x ? \
HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_RESET); \
}while(0) /* SCL */
#define IIC_SDA(x) do{ x ? \
HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_RESET); \
}while(0) /* SDA */
#define IIC_READ_SDA HAL_GPIO_ReadPin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) /* 读取SDA */
/*
IIC_SCL(1); SCL置高
IIC_SCL(0); SCL置低
IIC_SDA(1); SDA置高
IIC_SDA(0); SDA置低
*/
#endif
二、SSD1306
在此我们简单学习一下SSD1306这款芯片,通过查看datasheet,了解SSD1306的指令、引脚定义、寻址方式、0.96Oled的原理图,学习如何驱动SSD1306。
2.1 通讯协议选择
由图可知SSD1306适用于多种通讯协议,IIC,6800,8080,SPI(三线,四线)都可,由BS0;BS1;BS2三位引脚决定。本篇我们只讨论IIC驱动SSD1306。
2.2 引脚定义
SSD1306的引脚非常多,这里我们仅介绍重要引脚,电气特征引脚不做介绍,详细引脚请看数据手册。
-
RES#
&emsp;此引脚是复位信号输入。当引脚被拉时,执行芯片的初始化。在正常操作期间保持此引脚较高
(即连接到VDD)。 -
CS#
&emsp;这个引脚是芯片的选择输入.保持低电平即可
-
D/C#
&emsp;这是数据/命令控制引脚。当它被拉动HIGH(即连接到VDD)时,D[7:0]处的数据被视为数据。当它被LOW时,D[7:0]的数据将被传输到命令寄存器
。在II C模式下,该引脚作为从属地址选择的SA0。当选择三线串行接口时,该引脚必须连接到VSS。
DC=0,IIC下地址为0x78;DC=1;IIC下地址为0x7A,下面会介绍
-
R/W#(WR#)
这是连接到MCU接口的读/写控制输入引脚。1为读,0为写。 -
D[7:0]
8位双向数据总线。当选择串行接口模式时,D0为串行时钟输入:SCLK;D1为串行数据输入:SDA,SDIN和D2应保持NC。当选择IIC模式时,D2、D1应该绑定在一起,作为SDA。
2.3 0.96oled屏幕模块
0.96寸oled显示模块电路图如下,此处使用的模块为IIC通信
2.4 SSD1306下的IIC
2.4.1 从机地址
IIC设备在数据传输之前都必须识别从机地址。SSD1306的从机地址有 0111100b 和 0111101b 两种,通过将SA0(D/C#)脚上拉到高电平可以设置从机地址第七位为 1,将SA0(D/C#)脚下拉到低电平可以设置从机地址第七位为 0。通过SA0(D/C#)脚的上拉和下拉来设置从机地址,从而令总线上可以存在最多2个SSD1306驱动器。由于显示模块只用来写数据,R/W为0,所以从机地址只有01111000 和 01111010 两种
2.4.2数据读/写
2.4.3 写入顺序及格式
在传输完从属地址后,控制字节或数据字节都可以通过SDA发送。一个控制字节主要由Co和D/C#位组成,后面有六个 “0”。
如果Co位被设置为逻辑 “0”,则以下信息的传输将只包含数据字节。D/C#位决定了下一个数据字节是作为命令还是数据。
如果D/C#位被设置为逻辑"0",它定义下一个数据字节为命令。
如果D/C#位被设置为逻辑"1",则定义下一个数据字节为数据,将被存储在GDDRAM中。
2.5 GDDRAM
GDDRAM是一个保持要显示的位模式的位映射静态RAM。RAM的大小为128 x 64位,RAM分为8页,从PAGE0到PAGE7,用于单色128 x 64点矩阵显示,就是我们常说的像素点为128x64(横坐标有 128 个像素格,纵坐标有 64 个像素格)。
当一个数据字节被写入GDDRAM时,当前列同一页的所有行图像数据都被填充(即列地址指针指向的整个列(8位)被填充)。数据位D0写入上行,数据位D7写入下行。
当一个数据字节被写入GDDRAM时,当前列同一页的所有行图像数据都被填充(即列地址指针指向的整个列(8位)被填充)。数据位D0写入上行,数据位D7写入下行。
简而言之,该显示模块一共64行,可以分为8页(Page0 ~ Page7),每页8行(COM0 ~ COM7,COM8 ~ COM15,…),一共128列(SEG0~SEG127),每次显示时一次性至少显示8位,即一页中的一列,上面的为低位(LSB),下面的为高位(MSB),且低4位为列低地址,高4位为列高地址。一般一个中文字体占 16×16 个像素格,字母以及符号占 8×16或者6x8 个像素格。
2.6 寻址方式
通过设置指令,OLED模块可以配置为三种显示模式:页地址模式、水平地址模式、垂直地址模式,其实差别在于显示完本位置后,下一位要在哪显示的问题。
页面寻址模式(A[1:0]=10xb)
在页面寻址模式下,读写显示RAM后,列地址指针自动增加1。如果列地址指针到达列结束地址,则列地址指针将被重置为列起始地址,而页面地址指针将不被更改。用户必须设置新的页面和列地址,才能访问下一页的RAM内容。页面寻址模式设置下低列开始地址(00h~0Fh),页面寻址模式设置高列开始地址(10h~1Fh)
水平地址模式(A[1:0]=00b)
在水平寻址模式下,读写显示RAM后,列地址指针自动增加1。如果列地址指针到达列结束地址,则将列地址指针重置为列起始地址,页地址指针增加1。当列和页面地址指针都到达结束地址时,指针将重置为列起始地址和页面起始地址。
垂直地址模式(A[1:0]=01b)
在垂直寻址模式下,读写显示RAM后,页面地址指针自动增加1。如果页面地址指针到达页面结束地址,则页面地址指针重置为页面起始地址,列地址指针增加1。当列和页面地址指针都到达结束地址时,指针将重置为列起始地址和页面起始地址。
需要注意的是,OLED上电复位时的默认状态为页地址模式,而且这种也是最为常用的显示模式,因此可以看到很多OLED的代码中初始化时都没有配置这一项。
2.7 基础指令
SSD1306的指令非常多,这里我们只介绍几个基础指令,详细说明请看DataSheet。
2.8 驱动代码编写
2.8.1写数据/指令
由上文的IIC数据格式可知,当控制字节发送为0x00,代表下一个字节为命令,当控制字节发送为0x40,代表下一个字节为数据,此处我们采用软件IIC方式写入字节,如需使用硬件IIC仅需要在 _Oled_write_Byte()函数中调用STM32硬件IIC函数即可。此处我们从机地址为0x78,这里使用宏定义来设定从机地址,便于阅读和后续修改。
/**
* @brief 向OLED写入命令
* @param iic_command:写入命令
* @retval 无
*/
void _Oled_Write_Cmd(uint8_t iic_command)
{
_Oled_Write_Byte(0x00,iic_command);// 0000 0000 ,代表传输的是指令
}
/**
* @brief 向OLED写入数据
* @param iic_data: 写入数据
* @retval 无
*/
void _Oled_Write_Data(uint8_t iic_data)
{
_Oled_Write_Byte(0x40,iic_data);// 0100 0000,代表传输的是数据
}
/**
* @brief 向OLED写入一字节
* @param addr:控制字节
* data:写入的数据
* @retval 无
*/
void _Oled_Write_Byte(uint8_t addr,uint8_t data)
{
_IIc_Start(); //起始信号
_IIc_Send_Byte(ADDRESS); //发送从机地址
_IIc_Wait_Ack(); //等待应答信号
_IIc_Send_Byte(addr); //发送控制字节
_IIc_Wait_Ack(); //等待应答信号
_IIc_Send_Byte(data); //发送一个字节
_IIc_Wait_Ack(); //等待应答
_IIc_Stop(); //停止信号
}
2.8.2 Oled初始化
SSD1306指令过多,可以参照下面图发送初始化指令,也可以根据DataSheet自行修改。
附上我的初始化代码
uint8_t command[]={
0xAE, 0x20, 0x10, 0xb0, 0xc8, 0x00, 0x10, 0x40, 0x81, 0xff, 0xA1,
0xA6, 0xA8, 0x3F, 0xA4, 0xD3, 0x00, 0xD0, 0xF0, 0xD9, 0x22, 0xDA,
0x12, 0xDB, 0x20, 0x8D, 0x14, 0xAF};
/**
* @brief 写入初始化指令
* @param 无
* @retval 无
*/
void _Oled_Init()
{
uint8_t i=0;
HAL_Delay(200);//延时200MS,很重要必须得有
for(i=0;i<28;i++)
_Oled_Write_Cmd(command[i]);
_Oled_Clear();
}
2.8.3功能函数
成功对Oled屏幕写入字节之后,就可以通过写入指令和数据实现一些简单的功能,比如显示字符,字符串,汉字,图片,绘制点,线、也可以通过发送指令实现滚动显示,屏幕旋转,正反显示等。复杂一点的还可以写OLED菜单;具体实现不过多复述,附上本人的打包文件,代码,文件,教程,数据手册已经打包好了。
- 字符通常占据6x8、8x16个像素点。
- 一个汉字大小通常占据16x16个像素点。
- 显示图片的大小不能超过128x64。
可以通过pctolcd2002对汉字和图片取模,对于像素过大的图片可以使用imageled缩小。
具体教程请搜索网络,点击查看imageled教程
2.8.4 演示效果
文章来源:https://www.toymoban.com/news/detail-420601.html
3 cubeMX配置硬件IIC
写累了,抽空再写
文章来源地址https://www.toymoban.com/news/detail-420601.html
到了这里,关于【STM32CubeMX】教程二_IIC驱动0.96oled屏幕(SSD1306)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!