【蓝桥杯——物联网设计与开发】Part2:OLED

目录

一、OLED

(1)资源介绍

        🔅原理图 

        🔅驱动原理

(2)STM32CubeMX 软件配置

(3)代码编写

(4)实验现象

二、OLED接口函数封装

🟡️OLED_Write 函数代码实现

🟡️OLED_Init 函数代码补全

三、踩坑日记

(1)OLED 显示问题

(2)显示对齐问题


一、OLED

(1)资源介绍

        🔅原理图 

        在新版蓝桥杯物联网竞赛实训平台中,有一块 0.91 寸的 OLED;

         🟢️OLED 原理图如图1所示:

图1        OLED电路原理图

        通过电路图连接可知,引脚资源配置情况为:

表1 引脚资源配置情况
OLED MCU
SCL PB6
SDA PB7

        🔅驱动原理

        在原理图中,模块已板载 SCL SDA 线的上拉电阻MCU的引脚只需配置为开漏输出模式,即可接入模块。当有其他 I2C 从机接入同一 I2C 总线时,由于这里已经带有上拉电阻,所以无需另行外接 I2C 总线的上拉电阻,(在下一章的AT24C02中会提到)简化了系统的硬件连接复杂度。

        模块作为 I2C 从机,其地址编码为:0111 10 [SA0] [RW]。其中,SA0 属于硬件地址选择位,其电平状态直接决定地址编码中的 SA0 取值。当 SA0 引脚外接高电平时,地址中的 SA0 即为 1;反之,若 SA0 引脚外接低电平时,地址中的 SA0 则为 0。模块出厂时,默认 SA0 引脚接低电平,用户如有需求,可自行通过调整模块背面的电阻连接,将 SA0 置为高电平。如此一来,基于地址编码的唯一性限制,同一 I2C 总线最多能够同时挂接 2 个该型号的 OLED 模块,用户在进行系统扩展时需留意这一特性。

        因此,使用 I2C 驱动 OLED 时:

  • 写地址:0x78;
  • 读地址:0x79;
  •       ⚠️在赛点资源包中,官方提供了 OLED 的底层驱动代码,这里不再赘述;但函数

    void OLED_Write(uint8_t ucType, uint8_t ucData)需要自行补充编写;

    驱动原理部分内容参考博客:

    0.96寸与0.91寸OLED显示屏详解与驱动编程指南-CSDN博客

    (2)STM32CubeMX 软件配置

    🔅“工程建立、时钟树配置、Debug 串行线配置、代码生成配置” 在下文中有讲解,这里不再赘述❗️

    【蓝桥杯——物联网设计与开发】Part1:GPIO-CSDN博客https://blog.csdn.net/m0_63116406/article/details/144894900?sharetype=blogdetail&sharerId=144894900&sharerefer=PC&sharesource=m0_63116406&spm=1011.2480.3001.8118

    1️⃣点击左侧 "Connectivity" → 选择 "I2C1"  → 模式选择 "I2C" ( I2C 总线模式);

            ⚠️此处模式参数默认,请根据题意或项目需求进行修改;

    图2        I2C配置

    2️⃣生成代码;

    3️⃣将赛点资源数据包中的参考代码:"font.h""oled.h""oled.c""i2c.h" 添加到工程;

    (3)代码编写

    🟢️main 函数

    /* USER CODE BEGIN Includes */
    #include <stdio.h>
    #include "oled.h"
    /* USER CODE END Includes */
    /* USER CODE BEGIN PV */
    uint8_t puc_oled[17];	// OLED 显示存储区
    /* USER CODE END PV */
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
    
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_I2C1_Init();
      /* USER CODE BEGIN 2 */
    	OLED_Init();	// OLED 初始化
    	OLED_Clear();	// OLED 清屏,去除初始噪点
    	sprintf((char*)puc_oled, "123456789ABCDEFG");	// 将需要显示的字符串格式化到显示存储区
    	OLED_ShowString(0, 0, puc_oled, 16);					// 第0行显示
    	sprintf((char*)puc_oled, "  Hello World!  ");
    	OLED_ShowString(0, 2, puc_oled, 16);					// 第2行显示
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }

    (4)实验现象

            OLED 一共显示两行,第一行显示字符串 "123456789ABCDEFG",第二行显示 "Hello World!"


    二、OLED接口函数封装

    🟡️OLED_Write 函数代码实现

    void OLED_Write(uint8_t ucType, uint8_t ucData)
    {
    	uint8_t pData[2];		// 定义数组存储传输的数据
    	pData[0] = ucType;	// 数据类型:数据 或者 命令
    	pData[1] = ucData;	// 数据本身
    	HAL_I2C_Master_Transmit(&hi2c1, 0x78, pData, 2, 10);	// 调用库函数使用硬件 I2C 进行传输		
    }

    🟡️OLED_Init 函数代码补全

            ⚠️该函数需要添加一句代码,以稳定 OLED 

    HAL_Delay(100);

            如图3,在 OLED 的芯片手册上也有提到,在上电流程最后,推荐延迟100ms

    void OLED_Init(void)
    {
    //OLED_Write(TYPE_COMMAND, 0xA0);       /* 段重映射, b0:0,0->0(复位值); */
      OLED_Write(TYPE_COMMAND, 0xA1);       /* 段重映射, b0:1,0->127 */
    
      OLED_Write(TYPE_COMMAND, 0xA8);       /* 复用比 */
      OLED_Write(TYPE_COMMAND, 0x1F);       /* 0F~3F,16MUX~64MUX(复位值) */
    
    //OLED_Write(TYPE_COMMAND, 0xC0);       /* COM扫描方向, b3:0,正常模式(复位值) */
      OLED_Write(TYPE_COMMAND, 0xC8);       /* COM扫描方向, b3:1,反转模式 */
    
      OLED_Write(TYPE_COMMAND, 0xDA);       /* COM引脚配置 */
      OLED_Write(TYPE_COMMAND, 0x00);       /* D4:0,顺序;1,交替(复位值) */
    
      OLED_Write(TYPE_COMMAND, 0x8D);       /* 充电泵 */
      OLED_Write(TYPE_COMMAND, 0x14);       /* D2:0,禁止(复位值);1,允许 */
    
      OLED_Clear();                         /* 清除屏幕 */
      OLED_Write(TYPE_COMMAND, 0xAF);       /* 开启显示 */
    	
    	HAL_Delay(100);	// 延迟100ms
    }
    图3        芯片手册

    三、踩坑日记

    (1)OLED 显示问题

    ⚠️该 OLED 像素点为128 × 32:

  • Y轴:显示大小为 16 时,最多显示 排;显示大小为 8 时,最多显示 排;
  • X轴:最多显示 16 个字符,由于sprintf会在字符串后面添加  ’\0’  ,所以 OLED 显示数组 pucBuf 大小应该为 17
  • (2)显示对齐问题

            在蓝桥杯赛题上,会对 OLED 显示的字符有相对位置要求,如下图所示:

    图4        赛题

            根据上文对 OLED 的显示分析,一行最多有 16 个字符。那么根据这一特性,我们可以先写入一排大小为 8 的字符串 "123456789ABCDEFH",可以根据此字符串进行居中显示等;

            显示偶数个字符时,左右的空位刚好相等,能够满足完全居中;

            显示奇数个字符时,左边空位数 = 右边空位数 – 1,满足相对居中;

    作者:逝灮

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【蓝桥杯——物联网设计与开发】Part2:OLED

    发表回复