ESP32S3学习——i2c,点亮0.96寸oled

芯片:esp32s3

开发环境:espidfv4.4

一、官网相关资料(哎嘿嘿,中文的I2C 驱动程序 - ESP32-S3 - — ESP-IDF 编程指南 v4.4.2 文档)

1)概述

ESP32-S3 有两个 I2C 控制器(也称为端口),负责处理在 I2C 两根总线上的通信。每个控制器都可以设置为主机或从机。例如,可以同时让一个控制器用作主机,另一个用作从机。

2)功能

I2C 驱动程序管理在 I2C 总线上设备的通信,该驱动程序具备以下功能:

  • 在主机模式下读写字节

  • 支持从机模式

  • 读取并写入寄存器,然后由主机读取/写入

3)如何使用

  1. 配置驱动程序 - 设置初始化参数(如主机模式或从机模式,SDA 和 SCL 使用的 GPIO 管脚,时钟速度等)

  2. 安装驱动程序- 激活一个 I2C 控制器的驱动,该控制器可为主机也可为从机

  3. 根据是为主机还是从机配置驱动程序,选择合适的项目

    1. 主机模式下通信 - 发起通信(主机模式)

    2. 从机模式下通信 - 响应主机消息(从机模式)

  4. 中断处理 - 配置 I2C 中断服务

  5. 用户自定义配置 - 调整默认的 I2C 通信参数(如时序、位序等)

  6. 错误处理 - 如何识别和处理驱动程序配置和通信错误

  7. 删除驱动程序- 在通信结束时释放 I2C 驱动程序所使用的资源

4)配置流程

设置 i2c_config_t 结构中的几个参数
  • 设置 I2C 工作模式 - 从 i2c_mode_t 中选择主机模式或从机模式

  • 设置 通信管脚

    • 指定 SDA 和 SCL 信号使用的 GPIO 管脚

    • 是否启用 ESP32-S3 的内部上拉电阻

  • (仅限主机模式)设置 I2C 时钟速度

  • (仅限从机模式)设置以下内容:

    • 是否应启用 10 位寻址模式

    • 定义 从机地址

然后,初始化给定 I2C 端口的配置,请使用端口号和 i2c_config_t 作为函数调用参数来调用 i2c_param_config() 函数。在此阶段,i2c_param_config() 还将其他 I2C 配置参数设置为 I2C 总线协议规范中定义的默认值。有关默认值及修改默认值的详细信息

5) 时钟选择

增加了 时钟源分配器,用于支持不同的时钟源。时钟分配器将选择一个满足所有频率和能力要求的时钟源(如 i2c_config_t::clk_flags 中的要求)。

i2c_config_t::clk_flags0 时,时钟分配器将仅根据所需频率进行选择。如果不需要诸如 APB 之类的特殊功能,则可以将时钟分配器配置为仅根据所需频率选择源时钟。为此,请将 i2c_config_t::clk_flags 设置为 0。有关时钟特性,请参见下表

时钟名称时钟频率SCL 的最大频率时钟功能
XTAL 时钟40 MHz2 MHz/
RTC 时钟20 MHz1 MHzI2C_SCLK_SRC_FLAG_AWARE_DFS, I2C_SCLK_SRC_FLAG_LIGHT_SLEEP

时钟功能是嘛

i2c_config_t::clk_flags 的解释如下:

  1. I2C_SCLK_SRC_FLAG_AWARE_DFS:当 APB 时钟改变时,时钟的波特率不会改变。

  2. I2C_SCLK_SRC_FLAG_LIGHT_SLEEP:支持轻度睡眠模式,APB 时钟则不支持。

  3. ESP32-S3 可能不支持某些标志,请在使用前阅读技术参考手册

sugar,暂时用不到这些功能

6)安装驱动程序

配置好 I2C 驱动程序后,使用以下参数调用函数 i2c_driver_install() 安装驱动程序:

  • 端口号,从 i2c_port_t 中二选一

  • 主机或从机模式,从 i2c_mode_t 中选择

  • (仅限从机模式)分配用于在从机模式下发送和接收数据的缓存区大小。I2C 是一个以主机为中心的总线,数据只能根据主机的请求从从机传输到主机。因此,从机通常有一个发送缓存区,供从应用程序写入数据使用。数据保留在发送缓存区中,由主机自行读取。

  • 用于分配中断的标志(请参考 esp_hw_support/include/esp_intr_alloc.h 中 ESP_INTR_FLAG_* 值)

7)主机模式通讯

为优化通信流程,驱动程序提供一个名为 “命令链接” 的容器,该容器应填充一系列命令,然后传递给 I2C 控制器执行。

8)向从机发送数据

使用命令链接的流程

  1. 使用 i2c_cmd_link_create() 创建一个命令链接。

    然后,将一系列待发送给从机的数据填充命令链接:

    1. 启动位 - i2c_master_start()

    2. 从机地址 - i2c_master_write_byte()。提供单字节地址作为调用此函数的实参。

    3. 数据 - 一个或多个字节的数据作为 i2c_master_write() 的实参。

    4. 停止位 - i2c_master_stop()

    函数 i2c_master_write_byte()i2c_master_write() 都有额外的实参,规定主机是否应确认其有无接受到 ACK 位。

  2. 通过调用 i2c_master_cmd_begin() 来触发 I2C 控制器执行命令链接。一旦开始执行,就不能再修改命令链接。

  3. 命令发送后,通过调用 i2c_cmd_link_delete() 释放命令链接使用的资源

9)主机读取数据

write改为i2c_master_read_byte() 和/或 i2c_master_read() 填充命令链接,在步骤 5 中配置最后一次的读取,以便主机不提供 ACK 位。

10)指示写入或读取数据

主机实际执行的操作信息存储在从机地址的最低有效位中。

因此,为了将数据写入从机,主机发送的命令链接应包含地址 (ESP_SLAVE_ADDR << 1) | I2C_MASTER_WRITE

11)从机模式,还从来没用过

API 为从机提供以下功能:

  • i2c_slave_read_buffer()

    当主机将数据写入从机时,从机将自动将其存储在接收缓存区中。从机应用程序可自行调用函数 i2c_slave_read_buffer()。如果接收缓存区中没有数据,此函数还具有一个参数用于指定阻塞时间。这将允许从机应用程序在指定的超时设定内等待数据到达缓存区。

  • i2c_slave_write_buffer()

    发送缓存区是用于存储从机要以 FIFO 顺序发送给主机的所有数据。在主机请求接收前,这些数据一直存储在发送缓存区。函数 i2c_slave_write_buffer() 有一个参数,用于指定发送缓存区已满时的块时间。这将允许从机应用程序在指定的超时设定内等待发送缓存区中足够的可用空间。

peripherals/i2c 中可找到介绍如何使用这些功能的代码示例。

12)中断处理

安装驱动程序时,默认情况下会安装中断处理程序。但是,您可以通过调用函数 i2c_isr_register() 来注册自己的而不是默认的中断处理程序。在运行自己的中断处理程序时,可以参考 ESP32-S3 技术参考手册 > I2C 控制器 (I2C) > 中断 [PDF],以获取有关 I2C 控制器触发的中断描述。

调用函数 i2c_isr_free() 删除中断处理程序

13)用户自定义配置

如本节末尾所述 配置驱动程序,函数 i2c_param_config() 在初始化 I2C 端口的驱动程序配置时,也会将几个 I2C 通信参数设置为 I2C 总线协议规范 规定的默认值。 其他一些相关参数已在 I2C 控制器的寄存器中预先配置。

通过调用下表中提供的专用函数,可以将所有这些参数更改为用户自定义值。请注意,时序值是在 APB 时钟周期中定义。APB 的频率在 I2C_APB_CLK_FREQ 中指定

要更改的参数函数
SCL 脉冲周期的高电平和低电平i2c_set_period()
在产生 启动 信号期间使用的 SCL 和 SDA 信号时序i2c_set_start_timing()
在产生 停止 信号期间使用的 SCL 和 SDA 信号时序i2c_set_stop_timing()
从机采样以及主机切换时,SCL 和 SDA 信号之间的时序关系i2c_set_data_timing()
I2C 超时i2c_set_timeout()
优先发送/接收最高有效位 (LSB) 或最低有效位 (MSB),可在 i2c_trans_mode_t 定义的模式中选择i2c_set_data_mode()

上述每个函数都有一个 get 对应项来检查当前设置的值。例如,调用 i2c_get_timeout() 来检查 I2C 超时值。

要检查在驱动程序配置过程中设置的参数默认值,请参考文件 driver/i2c.c 并查找带有后缀 _DEFAULT 的定义。

通过函数 i2c_set_pin() 可以为 SDA 和 SCL 信号选择不同的管脚并改变上拉配置。如果要修改已经输入的值,请使用函数 i2c_param_config()

ESP32-S3 的内部上拉电阻范围为几万欧姆,因此在大多数情况下,它们本身不足以用作 I2C 上拉电阻。建议用户使用阻值在 I2C 总线协议规范 规定范围内的上拉电阻。

14)错误处理

大多数 I2C 驱动程序的函数在成功完成时会返回 ESP_OK ,或在失败时会返回特定的错误代码。实时检查返回的值并进行错误处理是一种好习惯。驱动程序也会打印日志消息,其中包含错误说明,例如检查输入配置的正确性。有关详细信息,请参考文件 driver/i2c.c 并用后缀 _ERR_STR 查找定义。

使用专用中断来捕获通信故障。例如,如果从机将数据发送回主机耗费太长时间,会触发 I2C_TIME_OUT_INT 中断。详细信息请参考 中断处理

如果出现通信失败,可以分别为发送和接收缓存区调用 i2c_reset_tx_fifo()i2c_reset_rx_fifo() 来重置内部硬件缓存区。

15)删除驱动程序

当使用 i2c_driver_install() 建立 I2C 通信,一段时间后不再需要 I2C 通信时,可以通过调用 i2c_driver_delete() 来移除驱动程序以释放分配的资源。

由于函数 i2c_driver_delete() 无法保证线程安全性,请在调用该函数移除驱动程序前务必确保所有的线程都已停止使用驱动程序。

16)应用示例

I2C 主机和从机示例:peripherals/i2c。已经没有啦

我将修改示例程序来驱动oled,会添加详尽的注释

二、配置流程

1)配置i2c_config_t,调用i2c_param_config,再安装驱动程序i2c_driver_install

2)读寄存器:i2c_master_write_read_device

3)写寄存器:i2c_master_write_to_device

4)删去驱动:i2c_driver_delete

就这些,不考虑一些默认参数,还是很简单呐

三、oled屏驱动简要知识

SSD1306 的每页包含了 128 个字节(1288个点,每页8行128列,一列8bit,自自上到下刷新),总共 8 页,这样刚好是 12864 的点阵大小

1)初始化:写一堆寄存器,看厂家给的就ok,就能用

2)页地址:0xb0-0xb7[2:0],低三位

3)列地址(低四位):00-0f 低四位

4)列地址(高四位):10-1f

5)对比度:0x81写8位数据,值越大越亮

6)关闭:0xae,开启oxaf

8)电荷泵:0x8d写8位数据:a2=0/1

1、清屏

for(i=0;i<8;i++)

{

OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)

//起始列地址0x00,写128个数据,写满一页

OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址

OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址

for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);

} //更新显示

 

需要注意一点,设备地址!!!!!

我使用的商家的代码

 

将写函数直接替换后屏幕并不能点亮,是设备地址的问题,图片中将地址右移动才是正确的地址,原因是:写函数再一次将地址左移,类似这样 addr<<1|WRITE

 

明白了吧

三、代码加注释

main

/* i2c - Simple example

   Simple I2C example that shows how to initialize I2C
   as well as reading and writing from and to registers for a sensor connected over I2C.

   The sensor used in this example is a MPU9250 inertial measurement unit.

   For other examples please check:
   https://github.com/espressif/esp-idf/tree/master/examples

   See README.md file to get detailed usage of this example.

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "oled.h"
#include "bmp.h"
static const char *TAG = "i2c-simple-example";

#define I2C_MASTER_SCL_IO           GPIO_NUM_22      /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO           GPIO_NUM_21      /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM              0                          /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ          400000                     /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS       1000



//     return i2c_master_write_read_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);

//     uint8_t write_buf[2] = {reg_addr, data};

//     ret = i2c_master_write_to_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);



/**
 * @brief i2c master initialization
 */
static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c_param_config(i2c_master_port, &conf);

    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}


void app_main(void)
{
    uint8_t data[2];
    ESP_ERROR_CHECK(i2c_master_init());
    ESP_LOGI(TAG, "I2C initialized successfully");

    /* Read the MPU9250 WHO_AM_I register, on power up the register should have the value 0x71 */

    OLED_Init();			//初始化OLED  
	OLED_Clear()  	; 
	OLED_DrawBMP(0,0,128,8,BMP1);  //图片显示(图片显示慎用,生成的字表较大,会占用较多空间,FLASH空间8K以下慎用)

    //ESP_ERROR_CHECK(i2c_driver_delete(I2C_MASTER_NUM));
    ESP_LOGI(TAG, "I2C unitialized successfully");
}

oled.c

//
// 本程序只供学习使用,未经作者许可,不得用于其它任何用途
// 中景园电子
// 店铺地址:http://shop73023976.taobao.com/?spm=2013.1.0.0.M4PqC2
//
//   文 件 名   : main.c
//   版 本 号   : v2.0
//   作    者   : HuangKai
//   生成日期   : 2014-0101
//   最近修改   :
//   功能描述   : OLED 4接口演示例程(51系列)
//               说明:
//               ----------------------------------------------------------------
//               GND    电源地
//               VCC  接5V或3.3v电源
//               D0   P1^0(SCL)
//               D1   P1^1(SDA)
//               RES  接P12
//               DC   接P13
//               CS   接P14
//               ----------------------------------------------------------------
//  修改历史   :
//  日    期   :
//  作    者   : HuangKai
//  修改内容   : 创建文件
// 版权所有,盗版必究。
// Copyright(C) 中景园电子2014/3/16
// All rights reserved
//******************************************************************************/。
#include "oled.h"

#include "oledfont.h"

// OLED的显存
// 存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127

void OLED_WR_Byte(unsigned dat, unsigned cmd)
{
	int ret;
	uint8_t write_buf[2] = {cmd?0x40:0x00, dat};

	ret = i2c_master_write_to_device(0, OLED_ADDR>>1, write_buf, sizeof(write_buf), 1000 / portTICK_RATE_MS);

	if (ret != ESP_OK)
	{
		printf("err\r\n");
	}
}

/********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{
	unsigned char m, n;
	for (m = 0; m < 8; m++)
	{
		OLED_WR_Byte(0xb0 + m, 0); // page0-page1
		OLED_WR_Byte(0x00, 0);	   // low column start address
		OLED_WR_Byte(0x10, 0);	   // high column start address
		for (n = 0; n < 128; n++)
		{
			OLED_WR_Byte(fill_Data, 1);
		}
	}
}

// 坐标设置

void OLED_Set_Pos(unsigned char x, unsigned char y)
{
	OLED_WR_Byte(0xb0 + y, OLED_CMD);
	OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
	OLED_WR_Byte((x & 0x0f), OLED_CMD);
}
// 开启OLED显示
void OLED_Display_On(void)
{
	OLED_WR_Byte(0X8D, OLED_CMD); // SET DCDC命令
	OLED_WR_Byte(0X14, OLED_CMD); // DCDC ON
	OLED_WR_Byte(0XAF, OLED_CMD); // DISPLAY ON
}
// 关闭OLED显示
void OLED_Display_Off(void)
{
	OLED_WR_Byte(0X8D, OLED_CMD); // SET DCDC命令
	OLED_WR_Byte(0X10, OLED_CMD); // DCDC OFF
	OLED_WR_Byte(0XAE, OLED_CMD); // DISPLAY OFF
}
// 清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{
	u8 i, n;
	for (i = 0; i < 8; i++)
	{
		OLED_WR_Byte(0xb0 + i, OLED_CMD); // 设置页地址(0~7)
		OLED_WR_Byte(0x00, OLED_CMD);	  // 设置显示位置—列低地址
		OLED_WR_Byte(0x10, OLED_CMD);	  // 设置显示位置—列高地址
		for (n = 0; n < 128; n++)
			OLED_WR_Byte(0, OLED_DATA);
	} // 更新显示
}
void OLED_On(void)
{
	u8 i, n;
	for (i = 0; i < 8; i++)
	{
		OLED_WR_Byte(0xb0 + i, OLED_CMD); // 设置页地址(0~7)
		OLED_WR_Byte(0x00, OLED_CMD);	  // 设置显示位置—列低地址
		OLED_WR_Byte(0x10, OLED_CMD);	  // 设置显示位置—列高地址
		for (n = 0; n < 128; n++)
			OLED_WR_Byte(1, OLED_DATA);
	} // 更新显示
}
// 在指定位置显示一个字符,包括部分字符
// x:0~127
// y:0~63
// mode:0,反白显示;1,正常显示
// size:选择字体 16/12
void OLED_ShowChar(u8 x, u8 y, u8 chr, u8 Char_Size)
{
	unsigned char c = 0, i = 0;
	c = chr - ' '; // 得到偏移后的值
	if (x > Max_Column - 1)
	{
		x = 0;
		y = y + 2;
	}
	if (Char_Size == 16)
	{
		OLED_Set_Pos(x, y);
		for (i = 0; i < 8; i++)
			OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA);
		OLED_Set_Pos(x, y + 1);
		for (i = 0; i < 8; i++)
			OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
	}
	else
	{
		OLED_Set_Pos(x, y);
		// for(i=0;i<6;i++)
		// OLED_WR_Byte(F6x8[c][i],OLED_DATA);
	}
}
// m^n函数
u32 oled_pow(u8 m, u8 n)
{
	u32 result = 1;
	while (n--)
		result *= m;
	return result;
}
// 显示2个数字
// x,y :起点坐标
// len :数字的位数
// size:字体大小
// mode:模式	0,填充模式;1,叠加模式
// num:数值(0~4294967295);
void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len, u8 size2)
{
	u8 t, temp;
	u8 enshow = 0;
	for (t = 0; t < len; t++)
	{
		temp = (num / oled_pow(10, len - t - 1)) % 10;
		if (enshow == 0 && t < (len - 1))
		{
			if (temp == 0)
			{
				OLED_ShowChar(x + (size2 / 2) * t, y, ' ', size2);
				continue;
			}
			else
				enshow = 1;
		}
		OLED_ShowChar(x + (size2 / 2) * t, y, temp + '0', size2);
	}
}
// 显示一个字符号串
void OLED_ShowString(u8 x, u8 y, u8 *chr, u8 Char_Size)
{
	unsigned char j = 0;
	while (chr[j] != '\0')
	{
		OLED_ShowChar(x, y, chr[j], Char_Size);
		x += 8;
		if (x > 120)
		{
			x = 0;
			y += 2;
		}
		j++;
	}
}
// 显示汉字
void OLED_ShowCHinese(u8 x, u8 y, u8 no)
{
	u8 t, adder = 0;
	OLED_Set_Pos(x, y);
	for (t = 0; t < 16; t++)
	{
		OLED_WR_Byte(Hzk[2 * no][t], OLED_DATA);
		adder += 1;
	}
	OLED_Set_Pos(x, y + 1);
	for (t = 0; t < 16; t++)
	{
		OLED_WR_Byte(Hzk[2 * no + 1][t], OLED_DATA);
		adder += 1;
	}
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char BMP[])
{
	unsigned int j = 0;
	unsigned char x, y;

	if (y1 % 8 == 0)
		y = y1 / 8;
	else
		y = y1 / 8 + 1;
	for (y = y0; y < y1; y++)
	{
		OLED_Set_Pos(x0, y);
		for (x = x0; x < x1; x++)
		{
			OLED_WR_Byte(BMP[j++], OLED_DATA);
		}
	}
}

// 初始化SSD1306
void OLED_Init(void)
{

	OLED_WR_Byte(0xAE, OLED_CMD); //--display off
	OLED_WR_Byte(0x00, OLED_CMD); //---set low column address
	OLED_WR_Byte(0x10, OLED_CMD); //---set high column address
	OLED_WR_Byte(0x40, OLED_CMD); //--set start line address
	OLED_WR_Byte(0xB0, OLED_CMD); //--set page address
	OLED_WR_Byte(0x81, OLED_CMD); // contract control
	OLED_WR_Byte(0xFF, OLED_CMD); //--128
	OLED_WR_Byte(0xA1, OLED_CMD); // set segment remap
	OLED_WR_Byte(0xA6, OLED_CMD); //--normal / reverse
	OLED_WR_Byte(0xA8, OLED_CMD); //--set multiplex ratio(1 to 64)
	OLED_WR_Byte(0x3F, OLED_CMD); //--1/32 duty
	OLED_WR_Byte(0xC8, OLED_CMD); // Com scan direction
	OLED_WR_Byte(0xD3, OLED_CMD); //-set display offset
	OLED_WR_Byte(0x00, OLED_CMD); //

	OLED_WR_Byte(0xD5, OLED_CMD); // set osc division
	OLED_WR_Byte(0x80, OLED_CMD); //

	OLED_WR_Byte(0xD8, OLED_CMD); // set area color mode off
	OLED_WR_Byte(0x05, OLED_CMD); //

	OLED_WR_Byte(0xD9, OLED_CMD); // Set Pre-Charge Period
	OLED_WR_Byte(0xF1, OLED_CMD); //

	OLED_WR_Byte(0xDA, OLED_CMD); // set com pin configuartion
	OLED_WR_Byte(0x12, OLED_CMD); //

	OLED_WR_Byte(0xDB, OLED_CMD); // set Vcomh
	OLED_WR_Byte(0x30, OLED_CMD); //

	OLED_WR_Byte(0x8D, OLED_CMD); // set charge pump enable
	OLED_WR_Byte(0x14, OLED_CMD); //

	OLED_WR_Byte(0xAF, OLED_CMD); //--turn on oled panel
}

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
对于Arduino ESP32S3和I2S的使用,你可以按照以下步骤进行操作: 1. 首先,你需要下载和安装Arduino IDE。你可以在官方网站上找到下载链接。 2. 接下来,你需要下载ESP32S3的板级支持包。你可以在ESP32官方网站上找到下载链接。请注意,这个板级支持包是专门为ESP32S3设计的,不适用于ESP32。 3. 安装完Arduino IDE和ESP32S3板级支持包后,你可以开始编写代码并进行编译。注意,如果你之前安装了ESP32插件,需要先将其卸载,因为ESP32S3ESP32插件不能同时使用。 4. 在编写代码时,你可以使用I2S库来控制ESP32S3的I2S接口。你可以根据需要使用不同的引脚来连接I2S设备。例如,SPI_MOSI_GPIO引脚连接到GPIO 35,SPI_MISO_GPIO引脚连接到GPIO 37,SPI_SCLK_GPIO引脚连接到GPIO 36,SPI_CS_GPIO引脚连接到GPIO 34。 5. 编写完代码后,你可以将代码烧录到ESP32S3开发板上进行测试。 总结起来,你需要下载并安装Arduino IDE、ESP32S3板级支持包,编写代码来控制ESP32S3的I2S接口,并使用合适的引脚连接I2S设备。希望这些信息对你有帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Arduino ESP32S3 基础入门教学大纲](https://blog.csdn.net/weixin_38476200/article/details/129828874)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Arduino ESP32S3 SPIFFS插件](https://download.csdn.net/download/qllaoda/86503364)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【esp32-s3】7.1 I2S——录音及存储](https://blog.csdn.net/qq_38091632/article/details/124506617)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值