IIC及OLED实验

发布时间:2023年12月21日
I2C (Inter-Integrated Circuit): I2C 是一种用于在芯片之间进行短距离数字通信的串行通信协议。它允许多个设备通过两根导线(一根数据线 SDA 和一根时钟线 SCL)进行通信。I2C 常常用于嵌入式系统中连接传感器、存储器、显示屏和其他外设。

数据线和时钟线是用于串行通信的两种基本信号线。它们通常用于协调和传输数据,确保发送和接收设备之间的同步和正确的通信。以下是它们的作用:

  1. 数据线(SDA - Serial Data Line): 数据线用于传输实际的数据位。在串行通信中,每个数据位按照顺序一个接一个地传输。SDA 承载着要发送或接收的二进制数据,每个数据位都在 SDA 上进行传输。

  2. 时钟线(SCL - Serial Clock Line): 时钟线是一个用于同步的信号线。它定义了数据位何时开始传输和何时结束,以及每个位的持续时间。SCL 的频率决定了通信速率,即每秒传输的位数。

在串行通信中,数据和时钟信号的组合允许设备在相同的时序下进行通信。发送设备通过时钟线告诉接收设备何时读取数据线上的位。这种同步机制确保了数据的正确性和可靠性。

例如,对于 I2C(Inter-Integrated Circuit)协议,SDA 是数据线,而 SCL 是时钟线。在每个时钟周期内,一个数据位被传输或接收,并且通过时钟信号进行同步。这种机制使得可以在两根线上进行双向通信,同时在同一总线上连接多个设备。

总的来说,数据线和时钟线是串行通信中的基本元素,它们协同工作以实现可靠和同步的数据传输。

用到的库函数:
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c,
                                    uint16_t DevAddress,
                                    uint16_t MemAddress,
                                    uint16_t MemAddSize,
                                    uint8_t *pData,
                                    uint16_t Size,
                                    uint32_t Timeout)

函数的参数如下:

  • hi2c: I2C外设的句柄,包含了I2C外设的配置和状态信息。
  • DevAddress: 目标设备的I2C地址。
  • MemAddress: 目标设备的内存地址,即要写入数据的位置。
  • MemAddSize: 内存地址的大小,以字节为单位,通常是1或2个字节。
  • pData: 要写入的数据的指针。
  • Size: 要写入的数据的字节数。
  • Timeout: 操作的超时时间,以毫秒为单位。

这个函数的作用是在指定的I2C总线上,向目标设备的指定内存地址写入一定数量的数据。函数返回一个 HAL_StatusTypeDef 类型的状态,表示操作的成功或失败。

OLED写命令的封装:

void Oled_Write_Cmd(uint8_t dataCmd)
{
    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT,
                        &dataCmd, 1, 0xff);
}

?OLED写数据的封装:

void Oled_Write_Data(uint8_t dataData)
{
    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT,
                        &dataData, 1, 0xff);
}

OLED实验?

接线:
SCL -- PB6
SDA -- PB7
void Oled_Write_Cmd(uint8_t dataCmd)
{
    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT,
                        &dataCmd, 1, 0xff);
}
void Oled_Write_Data(uint8_t dataData)
{
    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT,
                        &dataData, 1, 0xff);
}
void Oled_Init(void){
    Oled_Write_Cmd(0xAE);//--display off
    Oled_Write_Cmd(0x00);//---set low column address
    Oled_Write_Cmd(0x10);//---set high column address
    Oled_Write_Cmd(0x40);//--set start line address
    Oled_Write_Cmd(0xB0);//--set page address
    Oled_Write_Cmd(0x81); // contract control
    Oled_Write_Cmd(0xFF);//--128
    Oled_Write_Cmd(0xA1);//set segment remap
    Oled_Write_Cmd(0xA6);//--normal / reverse
    Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
    Oled_Write_Cmd(0x3F);//--1/32 duty
    Oled_Write_Cmd(0xC8);//Com scan direction
    Oled_Write_Cmd(0xD3);//-set display offset
    Oled_Write_Cmd(0x00);//
    Oled_Write_Cmd(0xD5);//set osc division
    Oled_Write_Cmd(0x80);//
    Oled_Write_Cmd(0xD8);//set area color mode off
    Oled_Write_Cmd(0x05);//
    Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
    Oled_Write_Cmd(0xF1);//
    Oled_Write_Cmd(0xDA);//set com pin configuartion
    Oled_Write_Cmd(0x12);//
    Oled_Write_Cmd(0xDB);//set Vcomh
    Oled_Write_Cmd(0x30);//
    Oled_Write_Cmd(0x8D);//set charge pump enable
    Oled_Write_Cmd(0x14);//
    Oled_Write_Cmd(0xAF);//--turn on oled panel
}

void Oled_Screen_Clear(void){
    int i,n;
    Oled_Write_Cmd (0x20); //set memory addressing mode
    Oled_Write_Cmd (0x02); //page addressing mode
    
    for(i=0;i<8;i++){
        Oled_Write_Cmd(0xb0+i); 
        Oled_Write_Cmd(0x00); 
        Oled_Write_Cmd(0x10); 
        for(n=0;n<128;n++)
            Oled_Write_Data(0x00);
    }
}
unsigned char bmpImager[] = {
/*-- 调入了一幅图像:D:\无标题.bmp --*/
/*-- 宽度x高度=128x64 --128x8x8*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xF0,0x08,0x0C,0x04,0x06,0x06,0x0C,0x04,0x0C,0xFC,0x1C,0x74,0xFC,0xF8,
0xF0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x07,0x04,0x88,0xF8,0x08,0x08,0x0C,0x06,0x01,0x00,0x00,0x01,0x1F,
0x7F,0xFF,0xDC,0xF8,0xE0,0xC0,0x40,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x10,0x18,0x08,0x0C,
0x04,0x04,0x06,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x60,0xC0,0x80,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
0x03,0x06,0x1C,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0xFC,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x88,0xE8,0x38,0x0E,0x09,0x08,
0x08,0x88,0xE8,0x18,0x08,0x08,0x08,0x00,0x00,0xFF,0x89,0x89,0x89,0xFF,0x00,0xFF,
0x89,0x89,0x89,0x89,0xFF,0x00,0x00,0x04,0x04,0x84,0x74,0x6F,0xA4,0x24,0x24,0x24,
0x24,0xA4,0x64,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x80,0xF0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x7F,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x08,0x09,0x09,0x06,0x06,
0x06,0x05,0x08,0x08,0x10,0x10,0x00,0x00,0x0C,0x03,0x10,0x10,0x10,0x1F,0x18,0x07,
0x00,0x00,0x10,0x10,0x1F,0x00,0x10,0x08,0x06,0x11,0x10,0x08,0x09,0x0A,0x06,0x06,
0x0B,0x08,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,
0x1E,0x03,0x00,0x00,0xC0,0x60,0x30,0x0C,0x04,0x06,0x02,0x01,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
0x1E,0x60,0x78,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

void Oled_Show_Image(unsigned char *image)
{
    unsigned char i;
    unsigned int j;
    for(i=0;i<8;i++){
        Oled_Write_Cmd(0xB0 + i);//page0--page7
        //每个page从0列
        Oled_Write_Cmd(0x00);
        Oled_Write_Cmd(0x10);
        //0到127列,依次写入0,每写入数据,列地址自动偏移
        for(j = 128 * i; j<(128 * (i+1));j++){
            Oled_Write_Data(image[j]);
         }
     }
}

int main(void)
{
    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();
    MX_I2C1_Init();

    //1. OLED初始化
    Oled_Init();
    //2. 选择一个位置
    //2.1 确认页寻址模式
    Oled_Write_Cmd(0x20);
    Oled_Write_Cmd(0x02);
    Oled_Screen_Clear();
    Oled_Show_Image(bmpImager);

    while (1)
    {

    }

}

这段代码是一个用于控制OLED显示屏的STM32程序,通过I2C总线进行通信。以下是代码的主要部分的解释:

  1. Oled_Write_Cmd 函数:

    • 用于向OLED发送命令。
    • 使用了 HAL_I2C_Mem_Write 函数,该函数用于通过I2C总线向设备的指定内存地址写入数据。
    • 在这里,使用 HAL_I2C_Mem_Write 函数向OLED发送命令,包括设备地址、内存地址(命令地址)、数据长度等参数。
  2. Oled_Write_Data 函数:

    • 用于向OLED发送数据。
    • 同样使用了 HAL_I2C_Mem_Write 函数,但这次写入的是数据而不是命令。
  3. Oled_Init 函数:

    • 用于OLED的初始化,设置了一系列的初始化命令,例如关闭显示、设置列地址、设置起始行地址等。
  4. Oled_Screen_Clear 函数:

    • 用于清除OLED屏幕内容。
    • 设置OLED为页寻址模式,然后对每一页的每一列写入0,实现清屏效果。
  5. Oled_Show_Image 函数:

    • 用于在OLED上显示图像。
    • 接收一个指向图像数据的指针,然后将数据逐页逐列写入OLED。
  6. main 函数:

    • main 函数中,首先进行了系统初始化、GPIO初始化和I2C初始化。
    • 调用了 Oled_Init 进行OLED的初始化。
    • 调用了 Oled_Screen_Clear 进行OLED的清屏。
    • 最后调用了 Oled_Show_Image 显示了一个预定义的图像。

总的来说,这个程序通过I2C总线控制OLED屏幕,进行初始化、清屏并显示图像。其中使用了HAL库提供的函数来简化硬件控制的实现。

图像显示函数

void Oled_Show_Image(unsigned char *image)
{
    unsigned char i;
    unsigned int j;
    for(i=0; i<8; i++){
        Oled_Write_Cmd(0xB0 + i);  // 设置页地址(Page Address),范围是0xB0到0xB7
        Oled_Write_Cmd(0x00);      // 设置列地址的低四位
        Oled_Write_Cmd(0x10);      // 设置列地址的高四位
        // 每个page从0列开始写入数据,列地址自动偏移
        for(j = 128 * i; j < (128 * (i+1)); j++){
            Oled_Write_Data(image[j]);  // 写入图像数据
        }
    }
}

?

  1. Oled_Write_Cmd(0xB0 + i);: 设置OLED的页地址,因为OLED是分页显示的,每页有8行。0xB0是页地址的基准值,通过 i 的变化,可以在0xB0到0xB7之间循环选择页。

  2. Oled_Write_Cmd(0x00);: 设置列地址的低四位,因为一共有128列,这里设置低四位为0,表示从第0列开始写入数据。

  3. Oled_Write_Cmd(0x10);: 设置列地址的高四位,因为列地址是8位的,这里设置高四位为0x1,表示从第16列开始写入数据。这是因为OLED内部的存储结构是每个列占8个像素,所以16列的高四位为1。

  4. for(j = 128 * i; j < (128 * (i+1)); j++) { Oled_Write_Data(image[j]); }: 通过循环,逐列写入图像数据。j 的取值范围是从0到127,实际上,每页的图像数据在 image 数组中是连续存放的,因此通过这个循环可以将一整页的图像数据逐列写入OLED。

OLED的宽度为128像素,高度为64像素。这是一种常见的OLED屏幕分辨率。在这种情况下,每个页面(Page)有8行,共有64/8 = 8个页面。

具体到代码中的 Oled_Show_Image 函数,它通过循环遍历8个页面,每个页面逐列写入图像数据。每个页面有128列,因为OLED的宽度是128像素。

在这个例子中,假设 image 数组中的数据是按照每个页面从左到右、从上到下的顺序存储的,每个像素用一个字节表示。因此,通过循环逐页逐列写入数据,可以正确地将整个图像显示在OLED上。

?

文章来源:https://blog.csdn.net/qq_61391875/article/details/135135797
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。