外设

[English]

外设时钟门控

与更新之前相同,外设的时钟仍由驱动处理,用户无需对外设模块的时钟门控进行设置。

但是,如果用户想基于组件 halsoc 开发自己的驱动,请注意时钟门控的头文件引用路径已由 driver/periph_ctrl.h 更新为 esp_private/periph_ctrl.h

RTC 子系统控制

RTC 控制 API 已经从 driver/rtc_cntl.h 移动到了 esp_private/rtc_ctrl.h

ADC

ADC 单次模式及连续模式驱动

ADC 单次模式的驱动已更新。

  • 新的驱动位于组件 esp_adc 中,头文件引用路径为 esp_adc/adc_oneshot.h

  • 旧版驱动仍然可用,其头文件引用路径为 driver/adc.h

对于 ADC 连续模式驱动,其位置已由组件 driver 更新为 esp_adc

  • 头文件引用路径由 driver/adc.h 更新为 esp_adc/adc_continuous.h

但是,引用两种模式的旧版路径 driver/adc.h 会默认触发如下编译警告,可通过配置 Kconfig 选项 CONFIG_ADC_SUPPRESS_DEPRECATE_WARN 关闭该警告。

legacy adc driver is deprecated, please migrate to use esp_adc/adc_oneshot.h and esp_adc/adc_continuous.h for oneshot mode and continuous mode drivers respectively

ADC 校准驱动

ADC 校准驱动已更新。

  • 新的驱动位于组件 esp_adc 中,头文件引用路径为 esp_adc/adc_cali.hesp_adc/adc_cali_scheme.h

旧版驱动仍然可用,其头文件引用路径为 esp_adc_cal.h。如果用户要使用旧版路径,需要将组件 esp_adc 添加到文件 CMakeLists.txt 的组件需求表中。

默认情况下,引用路径 esp_adc_cal.h 会默认触发如下编译警告,可通过配置 Kconfig 选项 CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN 关闭该警告。

legacy adc calibration driver is deprecated, please migrate to use esp_adc/adc_cali.h and esp_adc/adc_cali_scheme.h

API 更新

  • ADC 电源管理 API adc_power_acquireadc_power_release 已被移至 esp_private/adc_share_hw_ctrl.h,用于内部功能。

    • 更新前,由于硬件勘误表的工作原理,这两个 API 可以被用户调用。

    • 更新后,ADC 电源管理完全由驱动在内部实现。

    • 如果用户仍需调用这个 API,可以通过引用路径 esp_private/adc_share_hw_ctrl.h 来调用它。

  • 更新后, driver/adc2_wifi_private.h 已被移至 esp_private/adc_share_hw_ctrl.h

  • adc_unit_t 中的枚举 ADC_UNIT_BOTHADC_UNIT_ALTERADC_UNIT_MAX 已被删除。

  • 由于只有部分芯片支持下列枚举的某些取值,因此将下列枚举删除。如果用户使用了不支持的取值,会造成驱动运行错误。

    • 枚举 ADC_CHANNEL_MAX

    • 枚举 ADC_ATTEN_MAX

    • 枚举 ADC_CONV_UNIT_MAX

  • ESP32 中的 API hall_sensor_read 已被删除,因此 ESP32 不再支持霍尔传感器。

  • API adc_set_i2s_data_sourceadc_i2s_mode_init 已被弃用,相关的枚举 adc_i2s_source_t 也已被弃用,请使用 esp_adc/adc_continuous.h 进行迁移。

  • API adc_digi_filter_resetadc_digi_filter_set_configadc_digi_filter_get_configadc_digi_filter_enable 已被移除. 这些接口的行为不被保证。 枚举 adc_digi_filter_idx_tadc_digi_filter_mode_t 和结构体 adc_digi_iir_filter_t 已被移除。

GPIO

  • 之前的 Kconfig 选项 RTCIO_SUPPORT_RTC_GPIO_DESC 已被删除,因此数组 rtc_gpio_desc 已不可用,请使用替代数组 rtc_io_desc

  • 更新后,用户回调函数无法再通过读取 GPIO 中断的状态寄存器来获取用于触发中断的 GPIO 管脚的编号。但是,用户可以通过使用回调函数变量来确定该管脚编号。

    • 更新前,GPIO 中断发生时,GPIO 中断状态寄存器调用用户回调函数之后,会被清空。因此,用户可以在回调函数中读取 GPIO 中断状态寄存器,以便确定触发中断的 GPIO 管脚。

    • 但是,在调用回调函数后清空中断状态寄存器可能会导致边沿触发的中断丢失。例如,在调用用户回调函数时,如果某个边沿触发的中断 (re) 被触发,该中断会被清除,并且其注册的用户回调函数还未被处理。

    • 更新后,GPIO 的中断状态寄存器在调用用户回调函数 之前 被清空。因此,用户无法读取 GPIO 中断状态寄存器来确定哪个管脚触发了中断。但是,用户可以通过回调函数变量来传递被触发的管脚编号。

Sigma-Delta 调制器

Sigma-Delta 调制器的驱动现已更新为 SDM

  • 新驱动中实现了工厂模式,SDM 通道都位于内部通道池中,因此用户无需手动将 SDM 通道配置到 GPIO 管脚。

  • SDM 通道会被自动分配。

尽管我们推荐用户使用新的驱动 API,旧版驱动仍然可用,位于头文件引用路径 driver/sigmadelta.h 中。但是,引用 driver/sigmadelta.h 会默认触发如下编译警告,可通过配置 Kconfig 选项 CONFIG_SDM_SUPPRESS_DEPRECATE_WARN 关闭该警告。

The legacy sigma-delta driver is deprecated, please use driver/sdm.h

概念与使用方法上的主要更新如下所示:

主要概念更新

  • SDM 通道名称已由 sigmadelta_channel_t 更新为 sdm_channel_handle_t,后者为一个不透明指针。

  • SDM 通道配置原来存放于 sigmadelta_config_t,现存放于 sdm_config_t

  • 旧版驱动中,用户无需为 SDM 通道设置时钟源。但是在新驱动中,用户需要在 sdm_config_t::clk_src 为 SDM 通道设置合适的时钟源,soc_periph_sdm_clk_src_t 中列出了可用的时钟源。

  • 旧版驱动中,用户需要为通道设置 prescale,该参数会影响调制器输出脉冲的频率。在新的驱动中,用户需要使用 sdm_config_t::sample_rate_hz 实现该功能。

  • 旧版驱动中,用户通过设置 duty 来改变输出的模拟量,现在换成了一个更贴切的名字 density

主要使用方法更新

  • 更新前,通道配置由通道分配在 sdm_new_channel() 完成。在新驱动中,只有 density 可在运行时由 sdm_channel_set_pulse_density() 更新。其他参数如 gpio numberprescale 只能在通道分配时进行设置。

  • 在进行下一步通道操作前,用户应通过调用 sdm_channel_enable() 提前 使能 该通道。该函数有助于管理一些系统级服务,如 电源管理

定时器组驱动

为统一和简化通用定时器的使用,定时器组驱动已更新为 GPTimer

尽管我们推荐使用新的驱动 API, 旧版驱动仍然可用,其头文件引用路径为 driver/timer.h。但是,引用 driver/timer.h 会默认触发如下编译警告,可通过配置 Kconfig 选项 CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN 关闭该警告。

legacy timer group driver is deprecated, please migrate to driver/gptimer.h

概念和使用方法上的主要更新如下所示:

主要概念更新

  • 用于识别定时器的 timer_group_ttimer_idx_t 已被删除。在新驱动中,定时器用参数 gptimer_handle_t 表示。

  • 更新后,定时器的时钟源由 gptimer_clock_source_t 定义,之前的时钟源参数 timer_src_clk_t 不再使用。

  • 更新后,定时器计数方向由 gptimer_count_direction_t 定义,之前的计数方向参数 timer_count_dir_t 不再使用。

  • 更新后,仅支持电平触发的中断, timer_intr_ttimer_intr_mode_t 不再使用。

  • 更新后,通过设置标志位 gptimer_alarm_config_t::auto_reload_on_alarm, 可以使能自动加载。 timer_autoreload_t 不再使用。

主要使用方法更新

  • 更新后,通过从 gptimer_new_timer() 创建定时器示例可以初始化定时器。用户可以在 gptimer_config_t 进行一些基本设置,如时钟源,分辨率和计数方向。请注意,无需在驱动安装阶段进行报警事件的特殊设置。

  • 更新后,报警事件在 gptimer_set_alarm_action() 中进行设置,参数在 gptimer_alarm_config_t 中进行设置。

  • 更新后,通过 gptimer_get_raw_count() 设置计数数值,通过 gptimer_set_raw_count() 获取计数数值。驱动不会自动将原始数据同步到 UTC 时间戳。由于定时器的分辨率已知,用户可以自行转换数据。

  • 更新后,如果 gptimer_event_callbacks_t::on_alarm 被设置为有效的回调函数,驱动程序也会安装中断服务。在回调函数中,用户无需配置底层寄存器,如用于“清除中断状态”,“重新使能事件”的寄存器等。因此, timer_group_get_intr_status_in_isrtimer_group_get_auto_reload_in_isr 这些函数不再使用。

  • 更新后,当报警事件发生时,为更新报警配置,用户可以在中断回调中调用 gptimer_set_alarm_action(),这样报警事件会被重新使能。

  • 更新后,如果用户将 gptimer_alarm_config_t::auto_reload_on_alarm 设置为 true,报警事件将会一直被驱动程序使能。

UART

删除/弃用项目

替代

备注

uart_isr_register()

更新后,UART 中断由驱动处理。

uart_isr_free()

更新后,UART 中断由驱动处理。

uart_config_t 中的 use_ref_tick

uart_config_t::source_clk

选择时钟源。

uart_enable_pattern_det_intr()

uart_enable_pattern_det_baud_intr()

使能模式检测中断。

I2C

删除/弃用项目

替代

备注

i2c_isr_register()

更新后,I2C 中断由驱动处理。

i2c_isr_register()

更新后,I2C 中断由驱动处理。

i2c_opmode_t

更新后,该项不再在 esp-idf 中使用。

SPI

删除/弃用项目

替代

备注

spi_cal_clock()

spi_get_actual_clock()

获取 SPI 真实的工作频率。

  • 内部头文件 spi_common_internal.h 已被移至 esp_private/spi_common_internal.h

LEDC

删除/弃用项目

替代

备注

ledc_timer_config_t 中的 bit_num

ledc_timer_config_t::duty_resolution

设置占空比分辨率。

脉冲计数器 (PCNT) 驱动

为统一和简化 PCNT 外设,PCNT 驱动已更新,详见 PCNT

尽管我们推荐使用新的驱动 API,旧版驱动仍然可用,保留在头文件引用路径 driver/pcnt.h 中。但是,引用路径 driver/pcnt.h 会默认触发如下编译警告,可通过配置 Kconfig 选项 CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN 来关闭该警告。

legacy pcnt driver is deprecated, please migrate to use driver/pulse_cnt.h

主要概念和使用方法上的更新如下所示:

主要概念更新

  • 更新后, pcnt_port_tpcnt_unit_tpcnt_channel_t 这些用于识别 PCNT 单元和通道的参数已被删除。在新的驱动中,PCNT 单元由参数 pcnt_unit_handle_t 表示,PCNT 通道由参数 pcnt_channel_handle_t 表示,这两个参数都是不透明指针。

  • 更新后,不再使用 pcnt_evt_type_t,它们由统一的 观察点事件 表示。在事件回调函数 pcnt_watch_cb_t 中,通过 pcnt_watch_event_data_t 可以分辨不同观察点。

  • pcnt_count_mode_t 更新为:cpp:type:pcnt_channel_edge_action_tpcnt_ctrl_mode_t 更新为 pcnt_channel_level_action_t

主要使用方法更新

  • 更新前,PCNT 的单元配置和通道配置都通过函数 pcnt_unit_config 实现。更新后,PCNT 的单元配置通过工厂 API pcnt_new_unit() 完成,通道配置通过工厂 API pcnt_new_channel() 完成。

  • pcnt_get_counter_value 更新为 pcnt_unit_get_count()

  • pcnt_counter_pause 更新为 pcnt_unit_stop()

  • pcnt_counter_resume 更新为 pcnt_unit_start()

  • pcnt_counter_clear 更新为 pcnt_unit_clear_count()

  • 更新后, pcnt_intr_enablepcnt_intr_disable 已被删除。新的驱动中,通过注册时间回调函数 pcnt_unit_register_event_callbacks() 来使能中断。

  • 更新后, pcnt_event_enablepcnt_event_disable 已被删除。新的驱动中,可通过 pcnt_unit_add_watch_point()pcnt_unit_remove_watch_point() 来增加/删除观察点,以使能/停用 PCNT 事件。

  • 更新后, pcnt_set_event_value 已被删除。新的驱动中,通过 pcnt_unit_add_watch_point() 增加观察点时,也同时设置了事件的数值。

  • 更新后, pcnt_get_event_valuepcnt_get_event_status 已被删除。在新的驱动中,这些信息存储在 pcnt_watch_event_data_t 的回调函数 pcnt_watch_cb_t 中。

  • 更新后, pcnt_isr_registerpcnt_isr_unregister 已被删除,不允许注册 ISR 句柄。 用户可以通过调用:cpp:func:pcnt_unit_register_event_callbacks 来注册事件回调函数。

  • 更新后, pcnt_set_pin 已被删除,新的驱动不再允许在运行时切换 GPIO 管脚。如果用户想切换为其他 GPIO 管脚,可通过:cpp:func:pcnt_del_channel 删除当前的 PCNT 通道,然后通过:cpp:func:pcnt_new_channel 安装新的 GPIO 管脚。

  • pcnt_filter_enablepcnt_filter_disablepcnt_set_filter_value 更新为 pcnt_unit_set_glitch_filter()。同时, pcnt_get_filter_value 已被删除。

  • pcnt_set_mode 更新为 pcnt_channel_set_edge_action()pcnt_channel_set_level_action()

  • pcnt_isr_service_installpcnt_isr_service_uninstallpcnt_isr_handler_addpcnt_isr_handler_remove 更新为 pcnt_unit_register_event_callbacks()。默认的 ISR 句柄已安装在新的驱动中。

温度传感器驱动

温度传感器的驱动已更新,推荐用户使用新驱动。旧版驱动仍然可用,但是无法与新驱动同时使用。

新驱动的头文件引用路径为 driver/temperature_sensor.h。旧版驱动仍然可用,保留在引用路径 driver/temp_sensor.h 中。但是,引用路径 driver/temp_sensor.h 会默认触发如下编译警告,可通过设置 Kconfig 选项 CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN 来关闭该警告。

legacy temperature sensor driver is deprecated, please migrate to driver/temperature_sensor.h

配置内容已更新。更新前,用户需要设置 clk_divdac_offset。更新后,用户仅需设置 tsens_range

温度传感器的使用过程也已更新。更新前,用户可通过 config->start->read_celsius 获取数据。更新后,用户需要通过 temperature_sensor_install 先安装温度传感器的驱动,测量完成后需卸载驱动,详情请参考 Temperature Sensor

RMT 驱动

为统一和扩展 RMT 外设的使用,RMT 驱动已更新,详见 RMT transceiver

尽管我们建议使用新的驱动 API,旧版驱动仍然可用,保留在头文件引用路径 driver/rmt.h``中。但是,引用路径 ``driver/rmt.h 会默认触发如下编译警告,可通过配置 Kconfig 选项 CONFIG_RMT_SUPPRESS_DEPRECATE_WARN 来关闭该警告。

The legacy RMT driver is deprecated, please use driver/rmt_tx.h and/or driver/rmt_rx.h

主要概念和使用方法更新如下所示:

主要概念更新

  • 更新后,用于识别硬件通道的 rmt_channel_t 已删除。在新的驱动中,RMT 通道用参数 rmt_channel_handle_t 表示,该通道由驱动程序动态分配,而不是由用户指定。

  • rmt_item32_t 更新为 rmt_symbol_word_t,以避免在结构体中出现嵌套的共用体。

  • 更新后, rmt_mem_t 已被删除,因为我们不允许用户直接访问 RMT 内存块(即 RMTMEM)。直接访问 RMTMEM 没有意义,反而会引发错误,特别是当 RMT 通道与 DMA 通道相连时。

  • 更新后,由于 rmt_mem_owner_t 由驱动控制,而不是用户,因此 rmt_mem_owner_t 已被删除。

  • rmt_source_clk_t 更新为 rmt_clock_source_t,后者不支持二进制兼容。

  • 更新后, rmt_data_mode_t 已被删除,RMT 内存访问模式配置为始终使用 Non-FIFO 和 DMA 模式。

  • 更新后,由于驱动有独立的发送和接收通道安装函数,因此 rmt_mode_t 已被删除。

  • 更新后, rmt_idle_level_t 已被删除,在 rmt_transmit_config_t::eot_level 中可为发送通道设置空闲状态电平。

  • 更新后, rmt_carrier_level_t 已被删除,可在 rmt_carrier_config_t::polarity_active_low 设置载流子极性。

  • 更新后, rmt_channel_status_trmt_channel_status_result_t 已被删除,不再使用。

  • 通过 RMT 通道发送并不需要用户提供 RMT 符号,但是用户需要提供一个 RMT 编码器用来告诉驱动如何将用户数据转换成 RMT 符号。

主要使用方法更新

  • 更新后,分别通过 rmt_new_tx_channel()rmt_new_rx_channel() 安装发送通道和接收通道。

  • 更新后, rmt_set_clk_divrmt_get_clk_div 已被删除。通道时钟配置只能在通道安装时完成。

  • 更新后, rmt_set_rx_idle_threshrmt_get_rx_idle_thresh 已被删除。新驱动中,接收通道的空闲状态阈值定义为 rmt_receive_config_t::signal_range_max_ns

  • 更新后, rmt_set_mem_block_numrmt_get_mem_block_num 已被删除。新驱动中,内存块的数量由 rmt_tx_channel_config_t::mem_block_symbolsrmt_rx_channel_config_t::mem_block_symbols 决定。

  • 更新后, rmt_set_tx_carrier 已被删除。新驱动使用 rmt_apply_carrier() 来设置载波动作。

  • 更新后, rmt_set_mem_pdrmt_get_mem_pd 已被删除,驱动程序自动调整内存的功率。

  • 更新后, rmt_memory_rw_rstrmt_tx_memory_resetrmt_rx_memory_reset 已被删除,驱动程序自动进行内存重置。

  • 更新后, rmt_tx_startrmt_rx_start 被合并为函数 rmt_enable(),该函数同时适用于发射通道和接收通道。

  • 更新后, rmt_tx_stoprmt_rx_stop 被合并为函数 rmt_disable(),该函数同时适用于发射通道和接收通道。

  • 更新后, rmt_set_memory_ownerrmt_get_memory_owner 已被删除,驱动程序自动添加 RMT 内存保护。

  • 更新后, rmt_set_tx_loop_modermt_get_tx_loop_mode 已被删除。新驱动中,在 rmt_transmit_config_t::loop_count 中设置循环模式。

  • 更新后, rmt_set_source_clkrmt_get_source_clk 已被删除。仅能在通道安装时通过 rmt_tx_channel_config_t::clk_srcrmt_rx_channel_config_t::clk_src 设置时钟源。

  • 更新后, rmt_set_rx_filter 已被删除。新驱动中,过滤阈值定义为 rmt_receive_config_t::signal_range_min_ns

  • 更新后, rmt_set_idle_levelrmt_get_idle_level 已被删除,可在 rmt_transmit_config_t::eot_level 中设置发射通道的空闲状态电平。

  • 更新后, rmt_set_rx_intr_enrmt_set_err_intr_enrmt_set_tx_intr_enrmt_set_tx_thr_intr_enrmt_set_rx_thr_intr_en 已被删除。新驱动不允许用户在用户端开启/关闭中断,而是提供了回调函数。

  • 更新后, rmt_set_gpiormt_set_pin 已被删除。新驱动不支持运行时动态切换 GPIO 管脚。

  • 更新后, rmt_config 已被删除。新驱动中,基础配置在通道安装阶段完成。

  • 更新后, rmt_isr_registerrmt_isr_deregister 已被删除,驱动程序负责分配中断。

  • rmt_driver_install 更新为 rmt_new_tx_channel()rmt_new_rx_channel()

  • rmt_driver_uninstall 更新为 rmt_del_channel()

  • 更新后, rmt_fill_tx_itemsrmt_write_itemsrmt_write_sample 已被删除。新驱动中,用户需要提供一个编码器用来将用户数据“翻译”为 RMT 符号。

  • 更新后,由于用户可以通过 rmt_tx_channel_config_t::resolution_hz 配置通道的时钟分辨率, rmt_get_counter_clock 已被删除。

  • rmt_wait_tx_done 更新为 rmt_tx_wait_all_done()

  • 更新后, rmt_translator_initrmt_translator_set_contextrmt_translator_get_context 已被删除。新驱动中,翻译器更新为 RMT 译码器。

  • 更新后, rmt_get_ringbuf_handle 已被删除。新驱动程序不再使用 Ringbuffer 来保存 RMT 符号。输入数据会直接保存到用户提供的缓冲区中,这些缓冲区甚至可以直接被挂载到 DMA 链接内部。

  • rmt_register_tx_end_callback 更新为 rmt_tx_register_event_callbacks(),用户可以在这个参数里面注册事件回调函数 rmt_tx_event_callbacks_t::on_trans_done

  • 更新后, rmt_set_intr_enable_maskrmt_clr_intr_enable_mask 已被删除。由于驱动程序负责处理中断,因此用户无需进行处理。

  • rmt_add_channel_to_grouprmt_remove_channel_from_group 更新为 RMT 同步管理器,详见 rmt_new_sync_manager()

  • 更新后, rmt_set_tx_loop_count 已被删除。新驱动中,循环计数在 rmt_transmit_config_t::loop_count 进行配置。

  • 更新后, rmt_enable_tx_loop_autostop 已被删除。新驱动中,发射循环自动终止一直使能,用户无法进行配置。

LCD

  • LCD 面板的初始化流程也有一些更新。更新后,esp_lcd_panel_init() 不再会自动打开显示器。用户需要调用 esp_lcd_panel_disp_on_off() 来手动打开显示器。请注意,打开显示器与打开背光是不同的。更新后,打开屏幕前,用户可以烧录一个预定义的图案,这可以避免开机复位后屏幕上的随机噪音。

  • 更新后, esp_lcd_panel_disp_off() 已被弃用,请使用 esp_lcd_panel_disp_on_off() 作为替代。

  • 更新后, dc_as_cmd_phase 已被删除,SPI LCD 驱动不再支持 9-bit 的 SPI LCD。请使用专用的 GPIO 管脚来控制 LCD D/C 线。

  • 更新后,用于注册 RGB 面板的事件回调函数已从 esp_lcd_rgb_panel_config_t 更新为单独的 API esp_lcd_rgb_panel_register_event_callbacks()。但是,事件回调签名仍保持不变。

  • 更新后, esp_lcd_rgb_panel_config_t 中的标志位 relax_on_idle 被重命名为 esp_lcd_rgb_panel_config_t::refresh_on_demand,后者虽表达了同样的含义,但是其命名更有意义。

  • 更新后,如果创建 RGB LCD 时,标志位 refresh_on_demand 使能,驱动不会在 esp_lcd_panel_draw_bitmap() 中进行刷新,用户需要调用 esp_lcd_rgb_panel_refresh() 来刷新屏幕。

  • 更新后,esp_lcd_color_space_t 已被弃用,请使用 lcd_color_space_t 来描述色彩空间,使用 lcd_color_rgb_endian_t 来描述 RGB 颜色的排列顺序。

专用的 GPIO 驱动

  • 更新后,所有与专用 GPIO 管脚相关的底层 (LL) 函数从 cpu_ll.h 中被移至 dedic_gpio_cpu_ll.h,并重新命名。

I2S 驱动

旧版 I2S 驱动在支持 ESP32-C3 和 ESP32-S3 新功能时暴露了很多缺点,为解决这些缺点,I2S 驱动已更新(请参考:doc:I2S Driver <../../../api-reference/peripherals/i2s>)。用户可以通过引用不同 I2S 模式对应的头文件来使用新版驱动的 API,如 driver/i2s/include/driver/i2s_std.hdriver/i2s/include/driver/i2s_pdm.h 以及 driver/i2s/include/driver/i2s_tdm.h

为保证前向兼容,旧版驱动的 API 仍然在 driver/deprecated/driver/i2s.h 中可用。但使用旧版 API 会触发编译警告,该警告可通过配置 Kconfig 选项 CONFIG_I2S_SUPPRESS_DEPRECATE_WARN 来关闭。

以下是更新后的 I2S 文件概况。

I2S File Structure

主要概念更新

独立的发送通道和接收通道

更新后,I2S 驱动的最小控制单元是发送/接收通道,而不是整个 I2S 控制器(控制器包括多个通道)。

  • 用户可以分别控制同一个 I2S 控制器的发送通道和接收通道,即可以通过配置实现分别开启和关闭发送通道和接收通道。

  • i2s_chan_handle_t 句柄类型用于唯一地识别 I2S 通道。所有的 API 都需要该通道句柄,用户需要对这些通道句柄进行维护。

  • 对于 ESP32-C3 和 ESP32-S3,同一个控制器中的发送通道和接收通道可以配置为不同的时钟或不同的模式。

  • 但是对于 ESP32 和 ESP32-S2, 同一个控制器中的发送通道和接收通道共享某些硬件资源。因此,配置可能会造成一个通道影响同一个控制器中的另一个通道。

  • 通过将 i2s_port_t::I2S_NUM_AUTO 设置为 I2S 端口 ID,驱动会搜索可用的发送/接收通道,之后通道会被自动注册到可用的 I2S 控制器上。但是,驱动仍然支持将通道注册到一个特定的端口上。

  • 为区分发送/接收通道和声音通道,在更新后的驱动中,“通道 (channel)”一词仅代表发送/接收通道,用“声道 (slot)”来表示声音通道。

I2S 模式分类

I2S 通信模式包括以下三种模式,请注意:

  • 标准模式:标准模式通常包括两个声道,支持 Philips,MSB 和 PCM(短帧同步)格式,详见 driver/i2s/include/driver/i2s_std.h

  • PDM模式:PDM 模式仅支持两个声道,16 bit 数据位宽,但是 PDM TX 和 PDM RX 的配置略有不同。对于 PDM TX,采样率可通过 i2s_pdm_tx_clk_config_t::sample_rate 进行设置,其时钟频率取决于上采样的配置。对于 PDM RX,采样率可通过 i2s_pdm_rx_clk_config_t::sample_rate 进行设置,其时钟频率取决于下采样的配置,详见 driver/i2s/include/driver/i2s_pdm.h

  • TDM 模式:TDM 模式可支持高达 16 声道,该模式可工作在 Philips,MSB,PCM(短帧同步)和PCM(长帧同步)格式下,详见 driver/i2s/include/driver/i2s_tdm.h

在某个模式下分配新通道时,必须通过相应的函数初始化这个通道。我们强烈建议使用辅助宏来生成默认配置,以避免默认值被改动。

独立的声道配置和时钟配置

可以单独进行声道配置和时钟配置。

  • 通过调用 i2s_channel_init_std_mode()i2s_channel_init_pdm_rx_mode()i2s_channel_init_pdm_tx_mode() 或:cpp:func:i2s_channel_init_tdm_mode 初始化声道/时钟/GPIO 管脚配置。

  • 通过调用 i2s_channel_reconfig_std_slot()i2s_channel_reconfig_pdm_rx_slot()i2s_channel_reconfig_pdm_tx_slot()i2s_channel_reconfig_tdm_slot() 可以在初始化之后改变声道配置。

  • 通过调用 i2s_channel_reconfig_std_clock()i2s_channel_reconfig_pdm_rx_clock()i2s_channel_reconfig_pdm_tx_clock()i2s_channel_reconfig_tdm_clock() 可以在初始化之后改变时钟配置。

  • 通过调用 i2s_channel_reconfig_std_gpio()i2s_channel_reconfig_pdm_rx_gpio()i2s_channel_reconfig_pdm_tx_gpio()i2s_channel_reconfig_tdm_gpio() 可以在初始化之后改变 GPIO 管脚配置。

Misc

  • 更新后,I2S 驱动利用状态和状态机避免在错误状态下调用 API。

  • 更新后,ADC 和 DAC 模式已被删除,只有它们各自专用的驱动及 I2S 旧版驱动还支持这两种模式。

主要使用方法更新

请参考以下步骤使用更新后的 I2S 驱动:

  1. 通过调用 i2s_new_channel() 来获取通道句柄。我们应该在此步骤中指定外设为主机还是从机以及 I2S 端口。此外,驱动负责生成发送通道或接收通道的句柄。不需要同时输入发送通道和接收通道句柄,但需要输入至少一个句柄。输入两个句柄时,驱动会工作在双工模式。在同一端口上,发送通道和接收通道同时可用,并且共享 MCLK,BCLK 和 WS 信号。如果只输入了发送通道句柄或接收通道句柄,该通道只能工作在单工模式。

  2. 通过调用 i2s_channel_init_std_mode()i2s_channel_init_pdm_rx_mode()i2s_channel_init_pdm_tx_mode()i2s_channel_init_tdm_mode() 将通道初始化为指定模式。进行相应的声道、时钟和 GPIO 管脚配置。

  3. (可选)通过调用 i2s_channel_register_event_callback() 注册 ISR 事件回调函数。I2S 事件由回调函数同步接收,而不是从事件队列中异步接收。

  4. 通过调用 i2s_channel_enable() 来开启 I2S 通道的硬件资源。在更新后的驱动中,I2S 在安装后不会再自动开启,用户需要确定通道是否已经开启。

  5. 分别通过 i2s_channel_read()i2s_channel_write() 来读取和写入数据。当然,在 i2s_channel_read() 中只能输入接收通道句柄,在 i2s_channel_write() 中只能输入发送通道句柄。

  6. (可选)通过相应的 ‘reconfig’ 函数可以更改声道、时钟和 GPIO 管脚配置,但是更改配置前必须调用 i2s_channel_disable()

  7. 通过调用 i2s_channel_disable() 可以停止使用 I2S 通道的硬件资源。

  8. 不再使用某通道时,通过调用 i2s_del_channel() 可以删除和释放该通道资源,但是删除之前必须先停用该通道。

TWAI 驱动程序

CAN 外设驱动程序已弃用并被删除,请使用 TWAI 驱动程序代替(即在应用程序中包括 driver/twai.h)。

用于访问寄存器的宏

更新前,所有用于访问寄存器的宏都可以作为表达式来使用,所以以下命令是允许的:

uint32_t val = REG_SET_BITS(reg, mask);

在 ESP-IDF v5.0 中,用于写入或读取-修改-写入寄存器的宏不能再作为表达式使用,而只能作为语句使用,这适用于以下宏: REG_WRITEREG_SET_BITREG_CLR_BITREG_SET_BITSREG_SET_FIELDWRITE_PERI_REGCLEAR_PERI_REG_MASKSET_PERI_REG_MASKSET_PERI_REG_BITS

为存储要写入寄存器的值,请按以下步骤完成操作:

uint32_t new_val = REG_READ(reg) | mask;
REG_WRITE(reg, new_val);

要获得修改后的寄存器的值(该值可能与写入的值不同),要增加一个显示的读取命令:

REG_SET_BITS(reg, mask);
uint32_t new_val = REG_READ(reg);