# 外设

[English]

## 外设时钟门控

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

但是，如果用户想基于组件 `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 中断状态寄存器来确定哪个管脚触发了中断。但是，用户可以通过回调函数变量来传递被触发的管脚编号。

## 定时器组驱动

为统一和简化通用定时器的使用，定时器组驱动已更新为 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_set_raw_count()` 设置计数数值，通过 `gptimer_get_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_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` | 设置占空比分辨率。

## 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_rgb_element_order_t` 来描述 RGB 颜色的排列顺序。

## 用于访问寄存器的宏

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

    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);

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。