STM32 软件IIC 控制OLED 显示屏

news/2025/1/30 17:14:25 标签: stm32, 单片机, 嵌入式硬件, OLED

1. 硬件IIC 实在是太难用了,各种卡死,各种发不出来数据,没那么多时间折腾了,还是用软件IIC 先吧,初始化

void OLED_Software_IIC_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_AHBPeriphClockCmd(OLED_SOFTWARE_IIC_PORT_B | OLED_SOFTWARE_IIC_AF_CLOCK, ENABLE);

    GPIO_InitStruct.GPIO_Pin = OLED_IIC_SDA_PIN_B11 | OLED_IIC_SCL_PIN_B10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_40MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct); // PB11 - SDA, PB10 - SCL

    GPIO_SetBits(GPIOB, OLED_IIC_SDA_PIN_B11 | OLED_IIC_SCL_PIN_B10);

    OLED_IIC_Stop();
}

2. 一些宏定义,带FreeRTOS 实时操作系统,系统节拍设置为1ms,系统主频设置为32Mhz

#define OLED_USE_SOFTWARE_IIC

#define OLED_SOFTWARE_IIC_PORT_B    RCC_AHBPeriph_GPIOB // SCL - PB10, SDA -PB11
#define OLED_SOFTWARE_IIC_AF_CLOCK    RCC_APB1Periph_I2C2

#define IIC_TIMEOUT_COUNTER    0x2000 // iic transmit timeout

#define OLED_IIC_SCL_PIN_B10    GPIO_Pin_10
#define OLED_IIC_SDA_PIN_B11    GPIO_Pin_11
#define OLED_SCL_H()    GPIO_SetBits(GPIOB, OLED_IIC_SCL_PIN_B10)
#define OLED_SCL_L()    GPIO_ResetBits(GPIOB, OLED_IIC_SCL_PIN_B10)

#define OLED_ADDRESS    0x78 // 0x78: device address + write, 0x79 - device address + read
#define IIC_CMD_LEN    2

#define OLED_SDA_H()    GPIO_SetBits(GPIOB, OLED_IIC_SDA_PIN_B11)
#define OLED_SDA_L()    GPIO_ResetBits(GPIOB, OLED_IIC_SDA_PIN_B11)

#define OLED_SDA_READ()    GPIO_ReadInputDataBit(GPIOB, OLED_IIC_SDA_PIN_B11)

3. 延时函数,CPU 阻塞,空转

static void IIC_Delay(void)
{
   uint8_t temp;

   for (temp = 0; temp < 10; temp++)
   {
       // do nothing
   }
}

4. 起始信号

static void OLED_IIC_Start(void)
{
    OLED_SDA_H();
    OLED_SCL_H();

    IIC_Delay();
    OLED_SDA_L();
    IIC_Delay();
    OLED_SCL_L();
    IIC_Delay();
}

5. 停止信号

static void OLED_IIC_Stop(void)
{
   OLED_SDA_L();
   OLED_SCL_H();
   IIC_Delay();
   OLED_SDA_H();
   IIC_Delay();
}

6. 发送一个字节的数据

static void OLED_IIC_SendByte(uint8_t data)
{
   uint8_t index;
   GPIO_InitTypeDef GPIO_InitStruct;

   for (index = 0; index < 8; index++) // send one byte data, first send MSB (bit[7]), send LSB at the last (bit[0])
   {
       if (data & 0x80)
       {
           OLED_SDA_H(); // send 1
       }
       else
       {
           OLED_SDA_L(); // send 0
       }
       IIC_Delay();
       OLED_SCL_H();
       IIC_Delay();
       OLED_SCL_L();
       data <<= 1; // send next bit (MSB -> LSB)
       IIC_Delay();
   }
//    OLED_SDA_H();
   GPIO_InitStruct.GPIO_Pin = OLED_IIC_SDA_PIN_B11;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;

   GPIO_Init(GPIOB, &GPIO_InitStruct);

   IIC_Delay();
}

7. 发送一个字节数据后等待从机回复一个ACK 信号

uint8_t OLED_IIC_WaitAck(void)
{
   uint8_t ret;

   OLED_SCL_H();
   if (OLED_SDA_READ())
   {
       ret = 1; // not received ACK signal, wait fail
   }
   else
   {
       ret = 0; // received ACK signal, wait success
   }
   IIC_Delay();
   OLED_SCL_L();
   IIC_Delay();

   return ret;
}

8. GPIO 重新初始化

static void OLED_SoftwareIIC_SDA_Resume(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.GPIO_Pin = OLED_IIC_SDA_PIN_B11;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_40MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct); // PB11 - SDA
}

9. 模仿HAL库写的一个自己的函数,实现功能,发送设备地址+读写控制,再发送0x00,表示发的是命令,再发一个字节数据,具体的内容,数据,共发了三个字节的数据,加了超时退出机制

/*
 * imitate the stm32 HAL library, achieve myself's software i2c send function
 * deviceAddr: 0x78 - device address and write operation, 0x79 - device address and read operation
 */
static void HAL_I2C_Master_Transmit(I2C_TypeDef *I2Cx, uint8_t deviceAddr, uint8_t buff[], uint16_t buffLen, uint32_t timeout)
{
    uint32_t temp;
    uint16_t index;

    temp = timeout;

    OLED_IIC_Start();

    IIC_Delay();
    OLED_IIC_SendByte(deviceAddr); // device address and write bit

    while (OLED_IIC_WaitAck())
    {
        temp--;
        if (0 == temp)
        {
            return;
        }
        IIC_Delay();
    }

    OLED_SoftwareIIC_SDA_Resume();
    for (index = 0; index < buffLen; index++)
    {
        OLED_IIC_SendByte(buff[index]);
        IIC_Delay();
        while (OLED_IIC_WaitAck())
        {
            temp--;
            if (0 == temp)
            {
                return;
            }
            IIC_Delay();
        }
        OLED_SoftwareIIC_SDA_Resume();
        IIC_Delay();
    }

    OLED_IIC_Stop();
}

OLED__206">10. 向OLED 发送指令函数

static void OLED_SendCmd(uint8_t cmd)
{
    uint8_t sendBuff[2];

    sendBuff[0] = 0x00;
    sendBuff[1] = cmd;

    HAL_I2C_Master_Transmit(I2C2, OLED_ADDRESS, sendBuff, IIC_CMD_LEN, IIC_TIMEOUT_COUNTER);
}

OLED_OLED_IC_CH1116GSH1106_218">11. OLED 初始化函数,OLED 用的龙科显示公式的产品,控制IC 用的是CH1116G,他们给我发是资料却是SH1106的

void OLED_Init(void)
{
    delay_xms(200); // oled startup slowly than stm32l151c8t6
    INFO_LOG("[OLED_Init] init start\r\n");

    OLED_SendCmd(0xAE); // display off

    OLED_SendCmd(0x02); // set colum start address, low 4-bits
    OLED_SendCmd(0x10); // set colum end address, high 4-bits

    OLED_SendCmd(0x40); // set start line (first row)
    OLED_SendCmd(0xB0); // set page address

    delay_xms(5);
    OLED_SendCmd(0x81); // set contrast ratio (对比度)
    delay_xms(5);
    OLED_SendCmd(0xCF); // 128
    delay_xms(5);

    OLED_SendCmd(0xA1); // set segment remapping, from right to left

    OLED_SendCmd(0xA6); // forward display, normal or reverse

    OLED_SendCmd(0xA8); // multiple reuse rate, multiple ratio (多路复用率)
    OLED_SendCmd(0x3F); // duty = 1 / 64

    OLED_SendCmd(0xAD); // set charge pump enable
    OLED_SendCmd(0x8B); // enable DC-DC

    OLED_SendCmd(0x33); // set VPP = 10V

    OLED_SendCmd(0xC8); // set output scan direction, COM[N - 1] to COM[0], COM scan direction

    OLED_SendCmd(0xD3); // set display offset
    OLED_SendCmd(0x00); // 0x00

    OLED_SendCmd(0xD5); // set internal clock frequence, set osc frequency
    OLED_SendCmd(0xC0);

    OLED_SendCmd(0xD9); // set pre-charge period
    OLED_SendCmd(0x1F); // 0x22

    OLED_SendCmd(0xDA); // set COM pins, pin layout
    OLED_SendCmd(0x12);

    OLED_SendCmd(0xDB); // set electrical level, set VCOMH
    OLED_SendCmd(0x40);

    OLED_SendCmd(0xAF); // enable display, display on

    INFO_LOG("[OLED_Init][alfred01] init complete\r\n");
    INFO_LOG("[OLED_Init] init complete\r\n");
}

OLED__274">12. OLED 测试函数

void OLED_Test(void)
{
    OLED_SendCmd(0xB0); // page 0
    OLED_SendCmd(0x02); // colume 0, low 4-bits
    OLED_SendCmd(0x10); // colume 0, high 4-bits

    uint8_t sendBuff[] = {0x40, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
    HAL_I2C_Master_Transmit(I2C2, OLED_ADDRESS, sendBuff, sizeof(sendBuff), IIC_TIMEOUT_COUNTER);
}

OLED_OK_287">13. OLED 初步显示效果,表示控制驱动是OK的了,其它的就是慢慢细调了

在这里插入图片描述

OLED_CH1116G_289">14. OLED 规格书,控制芯片用的CH1116G,这是硬件发给我,和厂家给的不一致,厂家说是兼容的,那我就直接上手调了

在这里插入图片描述

15. 看这三个引脚接的是高电平还是低电平,怎么组合的,就知道用的什么接口,需要看原理图了

在这里插入图片描述
需要看原理图了
在这里插入图片描述
在这里插入图片描述

OLED__296">16. 逻分仪抓的OLED 初始化时序图

在这里插入图片描述


http://www.niftyadmin.cn/n/5005646.html

相关文章

整车电子电器架构和自动驾驶架构的区别

整车电子电器架构和自动驾驶架构的区别&#xff1a; 范围不同&#xff1a; 整车电子电器架构是面向整车电子电器部件的通信、网络和诊断&#xff0c;包含车身、动力、底盘、娱乐和电器等系统&#xff1b;自动驾驶架构是面向智能网联的驾驶辅助功能或高度自动驾驶功能系统的功…

stable diffusion webui中的sampler

Stable Diffusion-采样器篇 - 知乎采样器&#xff1a;Stable Diffusion的webUI中&#xff0c;提供了大量的采样器供我们选择&#xff0c;例如Eular a&#xff0c; Heum&#xff0c;DDIM等&#xff0c;不同的采样器之间究竟有什么区别&#xff0c;在操作时又该如何进行选择&…

【web开发】1、flask入门和html开发

文章目录 一、前端三剑客是什么&#xff1f;二、快速开发网站1.安装flask2.根目录下创建templates目录及web.py文件 三、HTML3.1常用标签3.2列表标签3.3表格标签3.4INPUT系列&#xff08;7个&#xff09;3.5下拉框3.6多行文本3.7案例&#xff1a;用户注册页面 一、前端三剑客是…

【学习笔记】元学习如何解决计算机视觉少样本学习的问题?

目录 1 计算机视觉少样本学习 2 元学习 3 寻找最优初始参数值方法&#xff1a;MAML 3.1 算法步骤 3.2 代码&#xff1a;使用MAML 和 FO-MAML、任务增强完成Few-shot Classification 4 距离度量方法&#xff1a;Siamese Network,ProtoNet,RN 4.1 孪生网络&#xff08;Sia…

肖sir__设计测试用例方法之_(白盒测试)

白盒测试技术 一、定义&#xff1a; 白盒测试也叫透明盒测试&#xff0c;检查程序内部结构及路径一是否符合规格说明&#xff0c;二是否符合其代码规范。 因此&#xff0c;也叫结构测试或者逻辑驱动测试。 二、白盒测试常见方法&#xff1a; a、语句覆盖&#xff1b; b、判断覆…

项目(智慧教室)第四部分,页面交互功能

一。页面构思 1.标题栏 大标题&#xff1a;智慧教室管理系统 小标题&#xff1a;灯光&#xff0c;报警&#xff0c;风扇&#xff0c;温度&#xff0c;湿度&#xff0c;光照 2.样式设计 背景设置。字体设置&#xff08;字体大小&#xff0c;格式&#xff0c;颜色&#xff09; 3.…

使用Flask编写一个最简单的后端接口

文章目录 一、Flask简介二、Flask与Django的对比三、一个最简单的例子 一、Flask简介 Flask是一个轻量级的Python Web框架&#xff0c;它使用Python语言编写&#xff0c;并且使用MVC模式进行开发。Flask被称为微框架&#xff0c;但这并不意味着它只能处理小型应用程序&#xf…

获取微信小程序二维码的bug

项目场景&#xff1a; 获取微信小程序二维码的bug,原来测试一直是没问题的&#xff0c;上线后也没啥问题&#xff0c;这次突然爆错 问题描述 access_token已失效或已过期 {"errcode":40001,"errmsg":"invalid credential, access_token is invalid…