IDF环境下ESP32使用硬件IIC驱动0.96寸OLED屏幕

ESP32的所有GPIO都可以配置为硬件I2C接口,这一点很方便。这里使用ESP32的I2C接口来驱动一个OLED,来验证I2C接口的用法。

一、新建工程

    参照前面ESP32点亮LED的方法,以“hello_world”工程为模板,创建一个新的工程。新工程命名为:i2c_oled01,如下图所示:

    二、添加OLED驱动文件

      我之前在STM32和ESP8266中驱动过OLED屏幕,把相关的源文件拷贝到main文件夹下面。如下图:

      返回到vs code中,可以看到该文件夹已经刷新到了main路径下:

      三、修改cmakelists.txt文件

        只是把源文件放进去还不行,还要让这个工程知道你添加了这个文件夹。双击main下面的cmakelists.txt文件,注意不是工程根目录下的cmakelists.txt文件。

        如图所示,右侧内容如下:

        idf_component_register(SRCS "hello_world_main.c" 
                            INCLUDE_DIRS "")

        需要添加文件路径和c文件名,修改后如下:

        上面添加了:oled/user_oled.c,即C源文件。

        第二行添加了:”oled”,即文件路径。

        修改后保存。我始终搞不懂,一个单片机级别的东西,搞这么复杂,肯定是哪里不正常!

        四、I2C接口初始化

          这部分内容较多,包括头文件、相关接口定义、I2C初始化等。依次如下:

          4.1 添加ESP32的I2C头文件

          双击打开“user_oled.c”文件,添加ESP32的I2C头文件:

          esp_system.h,包含一些基本参数;

          driver/i2c_master.h,包含I2C接口相关的函数。

          4.2 I2C接口初始化

          你想把哪些管脚定义为I2C,在这里操作,如下:

            #define SCL_IO_PIN 23 
            #define SDA_IO_PIN 22
            #define MASTER_FREQUENCY 100000
            #define PORT_NUMBER 0
            static i2c_master_bus_handle_t bus_handle;
            static i2c_master_dev_handle_t dev_handle;
          
            void esp32_i2c_init(void)
            {
                i2c_master_bus_config_t i2c_bus_config = {
                    .clk_source = I2C_CLK_SRC_DEFAULT,		//CLK时钟源
                    .i2c_port = PORT_NUMBER,
                    .scl_io_num = SCL_IO_PIN,
                    .sda_io_num = SDA_IO_PIN,
                    .glitch_ignore_cnt = 7,					//滤波参数,默认7即可
                    .flags.enable_internal_pullup = 0,			//I2C的上拉电阻。0,禁止;1,使能
                };
                ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
                i2c_device_config_t dev_cfg = {0};
          
                dev_cfg.dev_addr_length = I2C_ADDR_BIT_LEN_7;  // 7位地址
                dev_cfg.device_address = 0x3c;
                dev_cfg.scl_speed_hz = MASTER_FREQUENCY;  // 100kHz
          
                ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
          
          }

          如上,IO22定义为SDA,IO23定义为SCL。通信频率定义为100KHZ,端口号PORT_NUMBER一般0~1都行。

          static i2c_master_bus_handle_t bus_handle; 
          static i2c_master_dev_handle_t dev_handle;

          这里定义了两个句柄,一个是主机总线句柄,用来配置I2C总线相关参数;另一个是主机设备句柄,用来设置I2C主机下设备的相关参数。代码写的很清晰,直接看即可。

          五、I2C写操作函数编写

            编写一个函数,可以用来给OLED写入数据或命令。如下:

            void i2c_example_master_oled_write(uint8_t reg_address, uint8_t *data, size_t data_len) 
              {
                  uint8_t dat_buf[2] = {0};
                  dat_buf[0] = reg_address;
                  dat_buf[1] = *data;
                  ESP_ERROR_CHECK(i2c_master_transmit(dev_handle, dat_buf, 2, -1));
            }

            该函数有三个参数,第一个reg_address,即你要对OLED的哪个寄存器或哪个地址操作;第二个参数,你要写入的数据的地址;第三个参数,数据长度,但是没用到。

            这里可以看到,向I2C设备进行写操作时,是不需要写手动写入器件地址的。因为前面配置主机设备句柄时,已经写好了。

            六、编译、下载

              把I2C初始化和OLED配置的代码放到主函数里,如下:

              都改完了,编译、烧录即可。 如果编译时有报错,可以尝试删除之前的构建信息,然后重新编译。

              能看到OLED屏幕显示:

              最后,需要注意的一个地方就是,设置I2C设备的器件地址时,格式为7位地址格式。而我的OLED屏幕上,备注了器件地址为0x78,如下图:

              这个地址,看不出到底是7位的格式还是8位的格式,只能挨个试一下。像我这里,它其实是8位的格式,7位地址的话应该是0x3c。各位用的时候注意即可。

              我是单片机爱好者-MCU起航,打完收工!

              发表评论

              此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据