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(u8 ACK_Byte)
    {
        if(ACK_Byte == 1)
            SDA_HIGH;
        else
            SDA_LOW;
        SCL_HIGH;
        SCL_LOW;
    }

接受ACK方式参考

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

I2C读写1Byte数据

写数据的方式参考

    void IIC_WriteByte(u8 IIC_Byte)
    {
        u8 i;
        u8 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;
        }
    }

读数据的方式参考

    u8 IIC_ReadByte(void)
    {
        u8 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(u8 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中的初始数据输出 .

快速刷屏

    void OLED_ClearScreen(void)
    {
        OLED_DATA_128_64(0x00);
    }

    void OLED_FillScreen(void)
    {
        OLED_DATA_128_64(0xFF);
    }

    void OLED_DATA_128_64(u8 DATA_128_64)
    {
        u16 i;
        
        IIC_Start();
        
        IIC_WriteByte(0x78);//从机地址0111100和R/W#
        IIC_ReceiveAck();

        IIC_WriteByte(0x40);
        IIC_ReceiveAck();

        for(i=0;i<128*8;i++)
        {
            IIC_WriteByte(DATA_128_64);
            IIC_ReceiveAck();
        }
        
        IIC_Stop();
    }

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

        u8 r,c;

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

命令列表

基本命令

滚动命令

11/8