LOADING

加载过慢请开启缓存 浏览器默认开启

SSD1306

2023/10/20 MCU

了解 I2C

飞利浦(NXP)于 1980 提出I2C串行总线,使用多主从架构,为同步半双工通信方式 .
常见速率:100kbps、300kbps、3.4Mbps .

端口设置

采用外部上拉(强上拉)时,端口配置为开漏输出,配合上拉电阻(1K 左右)以输出高电平 .

I2C 的数据有效性

在传输期间,SCL为高电平时数据有效,数据的切换只能在SCL为低电平时进行 .

I2C 的 START 和 STOP 信号

    void IIC_Start(void)
    {
        SDA_HIGH;
        SCL_HIGH;
        SDA_LOW;
        SCL_LOW;
    }

    void IIC_Stop(void)
    {
        SDA_LOW;
        SCL_HIGH;
        SDA_HIGH;
    }

I2C 的 ACK 应答信号

START之后,在接下来的 8 个 CLK 中,SDA进行一次 8bit 的数据传输,若接收到数据,则在第 9 个 CLK 对SDA拉低,将其视作一次ACK应答信号 .

发送 ACK 的方式参考

    void IIC_SendAck(uint8_t ACK_Byte)
    {
        if(ACK_Byte == 1)
            SDA_HIGH;
        else
            SDA_LOW;
        SCL_HIGH;
        SCL_LOW;
    }

接受 ACK 方式参考

    uint8_t IIC_ReceiveAck(void)
    {
        uint8_t ACK_Byte;
        SDA_HIGH;//主机释放,从机接管
        SCL_HIGH;
        ACK_Byte = READ_SDA;
        SCL_LOW;
        return ACK_Byte;
    }

I2C 读写 1Byte 数据

写数据的方式参考

    void IIC_WriteByte(uint8_t IIC_Byte)
    {
        uint8_t i;
        uint8_t data = IIC_Byte;
        SCL_LOW;
        for(i=0;i<8;i++)
        {
            if((data&0x80) == 0x80)
                SDA_HIGH;
            else
                SDA_LOW;
            data = data<<1;
            SCL_HIGH;
            SCL_LOW;
        }
    }

读数据的方式参考

    uint8_t IIC_ReadByte(void)
    {
        uint8_t i,IIC_Byte = 0x00;
        SDA_HIGH;//主机释放,从机接管  --这里的SDA,SCL都是推挽输出
        for(i=0;i<8;i++)
        {
            SCL_HIGH;
            if(READ_SDA == 1)
                IIC_Byte |= (0x80>>i);
            SCL_LOW;
        }
        return IIC_Byte;
    }

了解 SSD1306

SSD1306 使用 I2C 的数据格式

首字节

由从机地址0x3CR/W#组成 .

        IIC_WriteByte(0x78);//W
        IIC_WriteByte(0x79);//R

控制字节

CoD/C#000000组成,Co低电平意指后续的 Byte 都是数据,可用于连续输出 CMD 和 DATA .

        IIC_WriteByte(0x00);//后面的字节是命令
        IIC_WriteByte(0x40);//后面的字节是数据,并存入GDDRAM
        IIC_WriteByte(0x80);//后一位字节是命令
        IIC_WriteByte(0xC0);//后一位字节是数据,并存入GDDRAM

写一次命令

    void OLED_CMD(uint8_t CMD)
    {
        IIC_Start();

        IIC_WriteByte(0x78);
        IIC_ReceiveAck();

        IIC_WriteByte(0x80);
        IIC_ReceiveAck();

        IIC_WriteByte(CMD);
        IIC_ReceiveAck();

        IIC_Stop();
    }

验证

尝试发送 0xAF 开启屏幕的显示

    OLED_CMD(0xAF);

接上逻辑分析仪查看时序

观察屏幕,情况如下:

屏幕被成功点亮,并将 GDDRAM 中的初始数据输出 .

SSD1306 的 GDDRAM

GDDRAM 结构

从上至下,将 GDDRAM 分为 8 个 PAGE,8 * 128 Byte
从左至右,将 PAGE 分为 128 个 SEG,128 * 1 Byte


写入 GDDRAM 的 Byte,最低位 D0 在顶行,最高位 D7 在底行 .

GDDRAM 的寻址模式

20h+A[1:0] 设置内存寻址模式

  1. A[1:0]=10b 页面寻址 用于局部刷新
    仅在 PAGE 中寻址 .向 GDDRAM 写入 1Byte 后,列指针自增 1,直至寻址结束,页指针不变 .

  2. A[1:0]=00b 水平寻址

  3. A[1:0]=01b 竖直寻址

  4. A[1:0]=11b 无效寻址

填充全屏

    OLED_FILL()
    {
        OLED_CMD(0x20);		// 设置寻址模式
        OLED_CMD(0x00);		// 水平寻址模式
        OLED_CMD(0X21);		// 设置列起始和结束地址
        OLED_CMD(0X00);		// 列起始地址 0
        OLED_CMD(0X7F);		// 列终止地址 127
        OLED_CMD(0X22);		// 设置页起始和结束地址
        OLED_CMD(0X00);		// 页起始地址 0
        OLED_CMD(0X07);		// 页终止地址 7

        uint8_t r,c;

        for(r=0;r<8;r++)
            for(c=0;c<128;c++)
                OLED_DATA(0xFF);
    }

命令列表

基本命令

滚动命令

11/8