【STM32CubeMX】教程二_IIC驱动0.96oled屏幕(SSD1306)

文章目录

  • 【STM32CubeMX】教程二_IIC驱动0.96oled屏幕(SSD1306)
  • 前言
  • 一、IIC通讯
    • 1.IIC物理层
    • 2.IIC协议层
    • 3.STM32的 II 特性及架构
      • 3.1 软件IIC
      • 3.2 硬件IIC
    • 4.软件IIC代码
      • 4.1 IIC.c
      • 4.2 IIC.h
  • 二、SSD1306
    • 2.1 通讯协议选择
    • 2.2 引脚定义
    • 2.3 0.96oled屏幕模块
    • 2.4 SSD1306下的IIC
      • 2.4.1 从机地址
      • 2.4.2数据读/写
      • 2.4.3 写入顺序及格式
    • 2.5 GDDRAM
    • 2.6 寻址方式
      • 2.7 基础指令
    • 2.8 驱动代码编写
      • 2.8.1写数据/指令
      • 2.8.2 Oled初始化
      • 2.8.3功能函数
      • 2.8.4 演示效果
  • 3 cubeMX配置硬件IIC

前言

本篇博客涉及以下内容

  • 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;  //100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉GPIO_Init(IIC_SCL_GPIO_PORT, &GPIO_InitStructure);  //SCLGPIO_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;  //100MHzGPIO_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 演示效果

3 cubeMX配置硬件IIC

写累了,抽空再写

【STM32CubeMX】教程二_IIC驱动0.96oled屏幕(SSD1306)相关推荐

  1. OpenHarmony学习笔记——I2C驱动0.96OLED屏幕

    文章目录 前言 I2C简介 硬件连接 编程实现 创建代码框架 初始化并复用GPIO 初始化I2C0 初始化OLED 从机地址 OLED初始化配置 功能代码 总结 目录 前言 前面介绍了一些关于在Hi3 ...

  2. MSP430F149程序移植——0.96OLED(ssd1306驱动)

    链接:https://pan.baidu.com/s/1ov-lE3sD2nMpV33Q9E7omw 提取码:2333 一.引脚说明 1.1 接口定义 引脚 功能说明 GND 电源地 VCC 电源正 ...

  3. NRF52840学习历程(九)SPI协议0.96OLED屏幕

    时间在2021年2月4日,寒假放假在家好好学一学nRF52840 今天还在感冒,休息一波 开发板:初雪的100出头那块 NRF52840 EVAL KIT 下载工具:JINLK V11(最好是JLIN ...

  4. NRF52840学习历程(八)IIC协议0.96OLED屏幕

    时间在2021年2月3日,寒假放假在家好好学一学nRF52840 昨天喉咙就不舒服,今天就感冒了,休息一波 开发板:初雪的100出头那块 NRF52840 EVAL KIT 下载工具:JINLK V1 ...

  5. stm32的IIC驱动0.96OLED

    IIC原理介绍: IIC是一个总线的结构但不支持总线协议 OLED介绍: 一.0.96寸OLED屏幕介绍 本文采用的是4针的0.96寸OLED显示进行讲解,采用的是SPI协议,速度会比采用I2C协议的 ...

  6. GD32F310G8 -【6】硬件I2C软件I2C驱动0.96OLED

    GD32F310-硬件I2C&软件I2C驱动OLED I2C 简介及特点 并行总线至 I2C 总线协议的转换及接口: 同一接口既可实现主机功能又可实现从机功能: 主从机之间的双向数据传输: 支 ...

  7. 【STM32】STM32CubeMX教程二--基本使用(新建工程点亮LED灯)

    前言 在配置好CubeMX之后,就是新建工程的开始了,那么首先我们需要一些准备,本片博客我们会很详细的介绍STM32CubeMx的基本使用和如何创建一个新的工程并且点亮LED灯  面向初学者   如果 ...

  8. STM32(基于HAL库)驱动0.96寸OLED屏幕(六脚)

    STM32驱动0.96寸OLED屏幕(六脚) 1 序言 2 如何利用STM32单片机驱动12864液晶屏 2.1*基本配置* 2.2 *0.96寸OLED端口含义* 2.3 *0.96寸OLED液晶屏 ...

  9. STM32(基于HAL库)驱动0.96寸OLED屏幕(四脚且中英文皆可显示)

    STM32驱动0.96寸OLED屏幕(四脚) 1 注意事项 2 如何利用STM32单片机驱动12864液晶屏 2.1*基本配置* 2.2 *0.96寸OLED端口含义* 2.3 *0.96寸OLED液 ...

最新文章

  1. 重拾CCNA,学习笔记持续更新ing......(4)
  2. Pthread多线程编程之查看Pthread版本的方法
  3. split函数python 未定义_Python字符串方法split()中的一道坑
  4. activiti实现跳转节点的方法
  5. leetcode 687. Longest Univalue Path | 687. 最长同值路径(树形dp)
  6. mysql面向对象例子_PHP 面向对象实例:获取数据库用户数据
  7. python读取文件夹下所有文件的名称_python2.7 学习之读取文件夹下所有文件名称及内容...
  8. 翻译: 4.3. 多层感知器的简明实现MLP pytorch
  9. 苹果cmsv10仿爱客影视搜索自适应模板
  10. 惠群计算机科技,电脑报专访:探索新视角,再造多元化的宏碁
  11. 手刃豆瓣top250排行榜
  12. 网络通 浏览器 无法上网
  13. 如何在word文档里复选框里打勾?
  14. Apple Lossless Audio Codec 苹果无损音频解码器
  15. Keras深度学习实战(39)——音乐音频分类
  16. Unity如何调用摄像头并显示在窗口内
  17. mysql 去除逗号_mysql注入之过滤逗号
  18. 阿里云服务器永久修改主机名
  19. 嵌入式软件工程师能做什么!需要哪些专业技能!这些你了解吗?
  20. 华为 HCIE 2.0(云服务)-- 云上可扩展性设计实验

热门文章

  1. java基础巩固-宇宙第一AiYWM:为了维持生计,MySQL基础Part2(MVCC、存储过程、触发器、编码方式及字符集、多表连接,内外连接,子查询、自联结、视图、设计DB、三范式)~整起
  2. Python入门必备知识
  3. oracle exfsys 下 rlm$evtcleanup,记一次数据库无法增删改趋于HANG住状态的故障诊断和处理 -电脑资料...
  4. linux上p图工具,万能P图神器下载-万能P图神器手机版v1.1-Linux公社
  5. WRF-Chem模拟(MEIC清单)
  6. 《计算机固件安全技术》学习笔记
  7. jvm性能调优 - 09白话新生代垃圾回收算法
  8. 运算放大器分类 、作用及运放的选型
  9. UE4通过SteamAudio实现3D立体声(HRTF)
  10. ImageMagick高级教程整理