外设
外设时钟门控
与更新之前相同,外设的时钟仍由驱动处理,用户无需对外设模块的时钟门控进行设置。
但是,如果用户想基于组件 hal
和 soc
开发自己的驱动,请注意时钟门控的头文件引用路径已由 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.h
和esp_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_acquire
和adc_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_BOTH
,ADC_UNIT_ALTER
及ADC_UNIT_MAX
已被删除。由于只有部分芯片支持下列枚举的某些取值,因此将下列枚举删除。如果用户使用了不支持的取值,会造成驱动运行错误。
枚举
ADC_CHANNEL_MAX
枚举
ADC_ATTEN_MAX
枚举
ADC_CONV_UNIT_MAX
ESP32 中的 API
hall_sensor_read
已被删除,因此 ESP32 不再支持霍尔传感器。API
adc_set_i2s_data_source
和adc_i2s_mode_init
已被弃用,相关的枚举adc_i2s_source_t
也已被弃用,请使用esp_adc/adc_continuous.h
进行迁移。API
adc_digi_filter_reset
,adc_digi_filter_set_config
,adc_digi_filter_get_config
和adc_digi_filter_enable
已被移除. 这些接口的行为不被保证。 枚举adc_digi_filter_idx_t
,adc_digi_filter_mode_t
和结构体adc_digi_iir_filter_t
已被移除。API
esp_adc_cal_characterize
已被弃用, 请迁移到adc_cali_create_scheme_curve_fitting
或adc_cali_create_scheme_line_fitting
.API
esp_adc_cal_raw_to_voltage
已被弃用, 请迁移到adc_cali_raw_to_voltage
.API
esp_adc_cal_get_voltage
已被弃用, 请迁移到adc_oneshot_get_calibrated_result
.
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 number
、prescale
只能在通道分配时进行设置。在进行下一步通道操作前,用户应通过调用
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_t
和timer_idx_t
已被删除。在新驱动中,定时器用参数gptimer_handle_t
表示。更新后,定时器的时钟源由
gptimer_clock_source_t
定义,之前的时钟源参数timer_src_clk_t
不再使用。更新后,定时器计数方向由
gptimer_count_direction_t
定义,之前的计数方向参数timer_count_dir_t
不再使用。更新后,仅支持电平触发的中断,
timer_intr_t
和timer_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_isr
与timer_group_get_auto_reload_in_isr
这些函数不再使用。更新后,当报警事件发生时,为更新报警配置,用户可以在中断回调中调用
gptimer_set_alarm_action()
,这样报警事件会被重新使能。更新后,如果用户将
gptimer_alarm_config_t::auto_reload_on_alarm
设置为 true,报警事件将会一直被驱动程序使能。
UART
删除/弃用项目 |
替代 |
备注 |
---|---|---|
|
无 |
更新后,UART 中断由驱动处理。 |
|
无 |
更新后,UART 中断由驱动处理。 |
|
选择时钟源。 |
|
|
使能模式检测中断。 |
I2C
删除/弃用项目 |
替代 |
备注 |
---|---|---|
|
无 |
更新后,I2C 中断由驱动处理。 |
|
无 |
更新后,I2C 中断由驱动处理。 |
|
无 |
更新后,该项不再在 esp-idf 中使用。 |
SPI
删除/弃用项目 |
替代 |
备注 |
---|---|---|
|
获取 SPI 真实的工作频率。 |
内部头文件
spi_common_internal.h
已被移至esp_private/spi_common_internal.h
。
LEDC
删除/弃用项目 |
替代 |
备注 |
---|---|---|
|
设置占空比分辨率。 |
脉冲计数器 (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_t
、pcnt_unit_t
和pcnt_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_t,pcnt_ctrl_mode_t
更新为pcnt_channel_level_action_t
。
主要使用方法更新
更新前,PCNT 的单元配置和通道配置都通过函数
pcnt_unit_config
实现。更新后,PCNT 的单元配置通过工厂 APIpcnt_new_unit()
完成,通道配置通过工厂 APIpcnt_new_channel()
完成。只需配置计数范围即可初始化一个 PCNT 单元。更新后,GPIO 管脚分配通过
pcnt_new_channel()
完成。高/低电平控制模式和上升沿/下降沿计数模式分别通过函数
pcnt_channel_set_edge_action()
和pcnt_channel_set_level_action()
进行设置。
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_enable
与pcnt_intr_disable
已被删除。新的驱动中,通过注册时间回调函数pcnt_unit_register_event_callbacks()
来使能中断。更新后,
pcnt_event_enable
与pcnt_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_value
与pcnt_get_event_status
已被删除。在新的驱动中,这些信息存储在pcnt_watch_event_data_t
的回调函数pcnt_watch_cb_t
中。更新后,
pcnt_isr_register
与pcnt_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_enable
,pcnt_filter_disable
与pcnt_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_install
,pcnt_isr_service_uninstall
,pcnt_isr_handler_add
与pcnt_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_div
与 dac_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_t
与rmt_channel_status_result_t
已被删除,不再使用。通过 RMT 通道发送并不需要用户提供 RMT 符号,但是用户需要提供一个 RMT 编码器用来告诉驱动如何将用户数据转换成 RMT 符号。
主要使用方法更新
更新后,分别通过
rmt_new_tx_channel()
和rmt_new_rx_channel()
安装发送通道和接收通道。更新后,
rmt_set_clk_div
和rmt_get_clk_div
已被删除。通道时钟配置只能在通道安装时完成。更新后,
rmt_set_rx_idle_thresh
和rmt_get_rx_idle_thresh
已被删除。新驱动中,接收通道的空闲状态阈值定义为rmt_receive_config_t::signal_range_max_ns
。更新后,
rmt_set_mem_block_num
和rmt_get_mem_block_num
已被删除。新驱动中,内存块的数量由rmt_tx_channel_config_t::mem_block_symbols
与rmt_rx_channel_config_t::mem_block_symbols
决定。更新后,
rmt_set_tx_carrier
已被删除。新驱动使用rmt_apply_carrier()
来设置载波动作。更新后,
rmt_set_mem_pd
和rmt_get_mem_pd
已被删除,驱动程序自动调整内存的功率。更新后,
rmt_memory_rw_rst
,rmt_tx_memory_reset
和rmt_rx_memory_reset
已被删除,驱动程序自动进行内存重置。更新后,
rmt_tx_start
和rmt_rx_start
被合并为函数rmt_enable()
,该函数同时适用于发射通道和接收通道。更新后,
rmt_tx_stop
和rmt_rx_stop
被合并为函数rmt_disable()
,该函数同时适用于发射通道和接收通道。更新后,
rmt_set_memory_owner
和rmt_get_memory_owner
已被删除,驱动程序自动添加 RMT 内存保护。更新后,
rmt_set_tx_loop_mode
和rmt_get_tx_loop_mode
已被删除。新驱动中,在rmt_transmit_config_t::loop_count
中设置循环模式。更新后,
rmt_set_source_clk
和rmt_get_source_clk
已被删除。仅能在通道安装时通过rmt_tx_channel_config_t::clk_src
和rmt_rx_channel_config_t::clk_src
设置时钟源。更新后,
rmt_set_rx_filter
已被删除。新驱动中,过滤阈值定义为rmt_receive_config_t::signal_range_min_ns
。更新后,
rmt_set_idle_level
和rmt_get_idle_level
已被删除,可在rmt_transmit_config_t::eot_level
中设置发射通道的空闲状态电平。更新后,
rmt_set_rx_intr_en
,rmt_set_err_intr_en
,rmt_set_tx_intr_en
,rmt_set_tx_thr_intr_en
和rmt_set_rx_thr_intr_en
已被删除。新驱动不允许用户在用户端开启/关闭中断,而是提供了回调函数。更新后,
rmt_set_gpio
和rmt_set_pin
已被删除。新驱动不支持运行时动态切换 GPIO 管脚。更新后,
rmt_config
已被删除。新驱动中,基础配置在通道安装阶段完成。更新后,
rmt_isr_register
和rmt_isr_deregister
已被删除,驱动程序负责分配中断。rmt_driver_install
更新为rmt_new_tx_channel()
与rmt_new_rx_channel()
。rmt_driver_uninstall
更新为rmt_del_channel()
。更新后,
rmt_fill_tx_items
,rmt_write_items
和rmt_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_init
,rmt_translator_set_context
和rmt_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_mask
和rmt_clr_intr_enable_mask
已被删除。由于驱动程序负责处理中断,因此用户无需进行处理。rmt_add_channel_to_group
和rmt_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
更新为单独的 APIesp_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_rgb_element_order_t
来描述 RGB 颜色的排列顺序。
MCPWM
MCPWM 驱动已更新(详见 MCPWM)。同时,旧版驱动已被弃用。
新驱动中,每个 MCPWM 子模块相互独立,用户可以自由进行资源连接。
尽管我们推荐使用新的驱动 API,旧版驱动仍然可用,其引用路径为 driver/mcpwm.h
。但是,使用旧版驱动会默认触发如下编译警告,可以通过配置 Kconfig 选项 CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN 来关闭该警告。
legacy MCPWM driver is deprecated, please migrate to the new driver (include driver/mcpwm_prelude.h)
主要概念和使用方法上的更新如下所示:
主要概念更新
更新后,MCPWM 驱动是面向对象的,大多数 MCPWM 子模块都有一个与之相关的驱动对象。驱动对象是由工厂函数创建的,如 mcpwm_new_timer()
。IO 控制函数总是需要对象句柄。
旧版驱动有一个不恰当的假设,即 MCPWM 运算器应连接到不同的 MCPWM 定时器上。但是,硬件上并没有这样的限制。新驱动中,同一个 MCPWM 定时器可以连接多个运算器,这样运算器可以获得最佳的同步性能。
更新前,驱动将生成 PWM 波形的方法预设为所谓的 mcpwm_duty_type_t
,但是,列出的占空比模式远远不够。类似的,旧版驱动有一些预设的 mcpwm_deadtime_type_t
也没有包含所有的使用场景。更重要的是,用户通常会被占空比模式和死区时间模式的名称所迷惑。更新后,驱动没有这些限制,但是用户必须从头开始构建发生器的行为。
在旧版驱动中,通过 GPIO 管脚,软件和其他定时器模块同步 MCPWM 定时器的方法并不统一。这增加了用户的学习成本,因此新驱动统一了同步 API。
旧版驱动混淆了“故障检测器”和“故障处理器”的概念。这让用户对 API 感到非常困惑。新驱动中,故障对象只代表一个故障源,而且我们引入了一个新概念, 制动器,来表示故障处理器。而且,新驱动支持软件故障。
旧版驱动只为获取子模块提供了回调函数,而新驱动为 MCPWM 子模块提供多种回调函数,如停止定时器,比较匹配,故障进入,紧急停止等。
更新后,不再使用
mcpwm_io_signals_t
和mcpwm_pin_config_t
, GPIO 管脚配置被移至子模块的配置结构中。更新后,不再使用
mcpwm_timer_t
和mcpwm_generator_t
,定时器和发生器分别用mcpwm_timer_handle_t
和:cpp:type:mcpwm_gen_handle_t 表示。更新后,不再使用
mcpwm_fault_signal_t
和mcpwm_sync_signal_t
,故障和同步源分别用mcpwm_fault_handle_t
和:cpp:type:mcpwm_sync_handle_t 表示。更新后,不再使用
mcpwm_capture_signal_t
,获取通道用mcpwm_cap_channel_handle_t
表示。
主要使用方法更新
mcpwm_gpio_init
和mcpwm_set_pin
:GPIO 管脚配置在子模块配置中完成,例如在mcpwm_generator_config_t::gen_gpio_num
中设置 PWM GPIO 管脚。mcpwm_init
:为得到预期的 PWM 波形,用户需要至少分配一个 MCPWM 定时器和 MCPWM 运算器,然后通过调用mcpwm_operator_connect_timer()
将二者连接起来。然后,用户需要调用如:cpp:func:mcpwm_generator_set_actions_on_timer_event,mcpwm_generator_set_actions_on_compare_event()
来设置发生器对不同事件的动作。mcpwm_group_set_resolution
:新驱动中,群组分辨率固定为最大值,通常为 80 MHz。mcpwm_timer_set_resolution
:MCPWM 定时器的分辨率在mcpwm_timer_config_t::resolution_hz
中进行设置。mcpwm_set_frequency
:PWM 频率由mcpwm_timer_config_t::resolution_hz
,mcpwm_timer_config_t::count_mode
和:cpp:member:mcpwm_timer_config_t::period_ticks 决定。mcpwm_set_duty
:为设置 PWM 占空比,用户应调用mcpwm_comparator_set_compare_value()
来改变比较器的阈值。mcpwm_set_duty_type
:新驱动中没有预设的占空比模式,通过设置不同的发生器行为,如mcpwm_generator_set_actions_on_timer_event()
,来配置占空比模式。mcpwm_set_signal_high
和mcpwm_set_signal_low
更新为mcpwm_generator_set_force_level()
。新驱动中,这是通过为发生器设置力作用来实现的,而不是在后台将占空比改为 0% 或 100%。mcpwm_start
和mcpwm_stop
更新为mcpwm_timer_start_stop()
。用户可以用更多的模式来启动和停止 MCPWM 定时器,详见mcpwm_timer_start_stop_cmd_t
。mcpwm_carrier_init
更新为mcpwm_operator_apply_carrier()
。mcpwm_carrier_enable
与mcpwm_carrier_disable
:通过检查载波设置结构mcpwm_carrier_config_t
是否为空集来自动使能和停用载波子模块。mcpwm_carrier_set_period
更新为mcpwm_carrier_config_t::frequency_hz
。mcpwm_carrier_set_duty_cycle
更新为mcpwm_carrier_config_t::duty_cycle
。mcpwm_carrier_oneshot_mode_enable
更新为mcpwm_carrier_config_t::first_pulse_duration_us
。更新后,
mcpwm_carrier_oneshot_mode_disable
被删除。硬件不支持停用第一个载波脉冲(即一次性脉冲)。mcpwm_carrier_output_invert
更新为mcpwm_carrier_config_t::invert_before_modulate
和mcpwm_carrier_config_t::invert_after_modulate
。mcpwm_deadtime_enable
与mcpwm_deadtime_disable
更新为mcpwm_generator_set_dead_time()
。mcpwm_fault_init
更新为mcpwm_new_gpio_fault()
。mcpwm_fault_set_oneshot_mode
与mcpwm_fault_set_cyc_mode
更新为mcpwm_operator_set_brake_on_fault()
与mcpwm_generator_set_actions_on_brake_event()
。由于
mcpwm_capture_enable
与mcpwm_capture_enable_channel()
重复,因此在更新后被删除。由于
mcpwm_capture_disable
与mcpwm_capture_capture_disable_channel()
重复,因此在更新后被删除。mcpwm_capture_enable_channel
与mcpwm_capture_disable_channel
更新为mcpwm_capture_channel_enable()
与mcpwm_capture_channel_disable()
。mcpwm_capture_signal_get_value
与mcpwm_capture_signal_get_edge
:通过mcpwm_capture_event_data_t
,获取事件回调函数中提供了计时器的数值和边缘电平。只有获取事件发生时,获取数据才有意义,提供单一的 API 来获取捕获数据是没有意义的。由于
mcpwm_sync_enable
与mcpwm_sync_configure()
重复,因此更新后被删除。mcpwm_sync_configure
更新为mcpwm_timer_set_phase_on_sync()
。mcpwm_sync_disable
相当于将mcpwm_timer_sync_phase_config_t::sync_src
设置为NULL
。mcpwm_set_timer_sync_output
更新为mcpwm_new_timer_sync_src()
。mcpwm_timer_trigger_soft_sync
更新为mcpwm_soft_sync_activate()
。mcpwm_sync_invert_gpio_synchro
与设置mcpwm_gpio_sync_src_config_t::active_neg
功能相同。更新后,
mcpwm_isr_register
已被删除。用户可以注册不同的事件回调函数来替代其功能,例如,可以使用mcpwm_capture_channel_register_event_callbacks()
注册获取事件注册函数。
专用的 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,如 esp_driver_i2s/include/driver/i2s_std.h, esp_driver_i2s/include/driver/i2s_pdm.h 以及 esp_driver_i2s/include/driver/i2s_tdm.h。
为保证前向兼容,旧版驱动的 API 仍然在 driver/deprecated/driver/i2s.h 中可用。但使用旧版 API 会触发编译警告,该警告可通过配置 Kconfig 选项 CONFIG_I2S_SUPPRESS_DEPRECATE_WARN 来关闭。
以下是更新后的 I2S 文件概况。
主要概念更新
独立的发送通道和接收通道
更新后,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(短帧同步)格式,详见 esp_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
进行设置,其时钟频率取决于下采样的配置,详见 esp_driver_i2s/include/driver/i2s_pdm.h。TDM 模式:TDM 模式可支持高达 16 声道,该模式可工作在 Philips,MSB,PCM(短帧同步)和PCM(长帧同步)格式下,详见 esp_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 驱动:
通过调用
i2s_new_channel()
来获取通道句柄。我们应该在此步骤中指定外设为主机还是从机以及 I2S 端口。此外,驱动负责生成发送通道或接收通道的句柄。不需要同时输入发送通道和接收通道句柄,但需要输入至少一个句柄。输入两个句柄时,驱动会工作在双工模式。在同一端口上,发送通道和接收通道同时可用,并且共享 MCLK,BCLK 和 WS 信号。如果只输入了发送通道句柄或接收通道句柄,该通道只能工作在单工模式。通过调用
i2s_channel_init_std_mode()
,i2s_channel_init_pdm_rx_mode()
,i2s_channel_init_pdm_tx_mode()
或i2s_channel_init_tdm_mode()
将通道初始化为指定模式。进行相应的声道、时钟和 GPIO 管脚配置。(可选)通过调用
i2s_channel_register_event_callback()
注册 ISR 事件回调函数。I2S 事件由回调函数同步接收,而不是从事件队列中异步接收。通过调用
i2s_channel_enable()
来开启 I2S 通道的硬件资源。在更新后的驱动中,I2S 在安装后不会再自动开启,用户需要确定通道是否已经开启。分别通过
i2s_channel_read()
和i2s_channel_write()
来读取和写入数据。当然,在i2s_channel_read()
中只能输入接收通道句柄,在i2s_channel_write()
中只能输入发送通道句柄。(可选)通过相应的 'reconfig' 函数可以更改声道、时钟和 GPIO 管脚配置,但是更改配置前必须调用
i2s_channel_disable()
。通过调用
i2s_channel_disable()
可以停止使用 I2S 通道的硬件资源。不再使用某通道时,通过调用
i2s_del_channel()
可以删除和释放该通道资源,但是删除之前必须先停用该通道。
TWAI 驱动程序
CAN
外设驱动程序已弃用并被删除,请使用 TWAI
驱动程序代替(即在应用程序中包括 driver/twai.h
)。
用于访问寄存器的宏
更新前,所有用于访问寄存器的宏都可以作为表达式来使用,所以以下命令是允许的:
uint32_t val = REG_SET_BITS(reg, bits, mask);
在 ESP-IDF v5.0 中,用于写入或读取-修改-写入寄存器的宏不能再作为表达式使用,而只能作为语句使用,这适用于以下宏: REG_WRITE
, REG_SET_BIT
, REG_CLR_BIT
, REG_SET_BITS
, REG_SET_FIELD
, WRITE_PERI_REG
, CLEAR_PERI_REG_MASK
, SET_PERI_REG_MASK
, SET_PERI_REG_BITS
。
为存储要写入寄存器的值,请按以下步骤完成操作:
uint32_t new_val = REG_READ(reg) | mask;
REG_WRITE(reg, new_val);
要获得修改后的寄存器的值(该值可能与写入的值不同),要增加一个显示的读取命令:
REG_SET_BITS(reg, bits, mask);
uint32_t new_val = REG_READ(reg);