ESP32-RMT

  • 1. RMT的结构框图
  • 2. ESP32的RMT RAM
  • 3. RMT的程序部分
  • 3.1 RMT的数据结构体
  • 3.2 RMT的 API
  • 4. 测试代码


ESP32作为一款智能家居的常用的芯片搭载了RMT的相关的硬件,使用这一部分的硬件可以很方便的产生我们所需要的波形。我最近刚好准备开发一个可以学习,发射红外的遥控器,所以也要系统的学习一下esp32。
官方文件是这么描述 这个RMT的单元的 (以下部分基本全部来自文档,做笔记)
RMT(红外遥控器)是一个红外发送/接收控制器, 其特殊设计支持生成各类信号。红外遥控发射器从内置的RAM(随机存取存储器)区中读取连续的脉冲码, 并对输出信号进行载波调制。接收器检测输入信号, 并进行滤波, 然后将信号高低电平以及长度值存入 RAM 中。

1. RMT的结构框图

esp32 红外接收原始数据 esp32的红外发射程序_物联网


RMT 有 8 个独立通道, 每个通道内部有一个发送器和一个接收器, 发送和接收不可同时工作。 8 个通道共享一块512x32 bit 的 RAM。 RAM 可由处理器内核通过 APB 总线进行读写。发射器可以对信号进行载波调制。软件可以通过配置 RMT_REF_ALWAYS_ON_CHn 选择每个通道的工作时钟: 80 MHz APB(外围总线)时钟或者REF_TICK。

2. ESP32的RMT RAM

esp32 红外接收原始数据 esp32的红外发射程序_嵌入式_02


RAM 中数据结构如图 15-2 所示,由低 16 位和高 16 位组成。两个字段中 level 表示电平高低值, period 表示level 持续的分频时钟(图 15-1 中 clk_div)周期数。 period 为 0 表示结束标志,发射器停止发送数据,接收器在检测到接收的信号变成空闲状态后会写此值。

RAM 可以通过 APB 总线进行访问,其起始地址为 0x3FF56800。每个通道可使用的 RAM 范围按照 64x32 bit分成 8 个 block。默认情况下每个通道可使用的 block 数量为 1(通道 0 使用 block0,通道 1 使用 block1,以此类推)。当通道 n 发送的数据量大于可使用的 block 时,除了可以通过配置 RMT_MEM_SIZE_CHn 寄存器扩展 block 还可以进行乒乓操作。将 RMT_MEM_SIZE_CHn 寄存器配置为 >1, 意味着此通道会占用下一个通道的block。通道 n 使用的 RAM 地址范围为:

start_addr_chn = 0x3FF56800 + 64 ∗ 4 ∗ n,

end_addr_chn = 0x3FF56800 + (64 ∗ 4 ∗ n + 64 ∗ 4 ∗ RMT_MEM_SIZE_CHn)mod(512 ∗ 4) − 4

为了防止数据覆盖,可以通过配置 RMT_MEM_OWNER_CHn 来表示发射器或者接收器对于信道 n 的 RAM 使用权。当配置不正确时,则会产生 RMT_CHn_ERR 中断。
注意: 当开启连续发送模式(即置位 RMT_REG_TX_CONTI_MODE)时,发送器会连续发送通道中的数据(即从第一个数据发送到最后一个数据,再从第一个发送到最后一个,依此类推)。在连续发送模式下,第 N 次和第N+1 次之间会有一个 clk_div 周期的 IDLE 电平。

3. RMT的程序部分

我是用的是基于idf开发的方法,idf中对于 rmt有很完善的支持。
其中 peripherals\rmt\ir_protocols\ 路径内有一个简单的rmt的应用参考。我的代码也是基于这个应用参考去实现的。
components\driver\include\driver\rmt.h 这个路径中的rmt.h 定义了基本的函数。以及各种的配置结构,这些结构和寄存器最终会对应上。

3.1 RMT的数据结构体

/**
* @brief Data struct of RMT TX configure parameters
*/
typedef struct {
    uint32_t carrier_freq_hz;          /*!< RMT carrier frequency */
    rmt_carrier_level_t carrier_level; /*!< Level of the RMT output, when the carrier is applied */
    rmt_idle_level_t idle_level;       /*!< RMT idle level */
    uint8_t carrier_duty_percent;      /*!< RMT carrier duty (%) */
#if SOC_RMT_SUPPORT_TX_LOOP_COUNT
    uint32_t loop_count;               /*!< Maximum loop count */
#endif
    bool carrier_en;                   /*!< RMT carrier enable */
    bool loop_en;                      /*!< Enable sending RMT items in a loop */
    bool idle_output_en;               /*!< RMT idle level output enable */
} rmt_tx_config_t;

/**
* @brief Data struct of RMT RX configure parameters
*/
typedef struct {
    uint16_t idle_threshold;     /*!< RMT RX idle threshold */
    uint8_t filter_ticks_thresh; /*!< RMT filter tick number */
    bool filter_en;              /*!< RMT receiver filter enable */
#if SOC_RMT_SUPPORT_RX_DEMODULATION
    bool rm_carrier;                   /*!< RMT receiver remove carrier enable */
    uint32_t carrier_freq_hz;          /*!< RMT carrier frequency */
    uint8_t carrier_duty_percent;      /*!< RMT carrier duty (%) */
    rmt_carrier_level_t carrier_level; /*!< The level to remove the carrier */
#endif
} rmt_rx_config_t;

/**
* @brief Data struct of RMT configure parameters
*/
typedef struct {
    rmt_mode_t rmt_mode;   /*!< RMT mode: transmitter or receiver */
    rmt_channel_t channel; /*!< RMT channel */
    gpio_num_t gpio_num;   /*!< RMT GPIO number */
    uint8_t clk_div;       /*!< RMT channel counter divider */
    uint8_t mem_block_num; /*!< RMT memory block number */
    uint32_t flags;        /*!< RMT channel extra configurations, OR'd with RMT_CHANNEL_FLAGS_[*] */
    union {
        rmt_tx_config_t tx_config; /*!< RMT TX parameter */
        rmt_rx_config_t rx_config; /*!< RMT RX parameter */
    };
} rmt_config_t;

3.2 RMT的 API

API部分的描述全部都是英文的,还算是好理解。 大概就是实现了寄存器参数的读写。
API 列表如下: (个人翻译,可能有错!)

  1. rmt_set_clk_div 设置时钟分频,这个和你的发射的频率以及后续的tick的数量都有直接的关系!
  2. rmt_set_rx_idle_thresh 设置空闲的长度。 单位是tick。 如果到了空闲状态超过了这些tick 就会触发空闲中断(如果开了),证明这一帧数据已经接收完。
  3. rmt_set_mem_block_num 给每一个RMT通道对应内存的块数
  4. rmt_set_tx_carrier 用来生成基波的,设置好基波的高电平持续的tick, 低电平tick等
  5. rmt_tx_start 开始一次rmt的传输
  6. rmt_tx_stop 终止当前的传输
  7. rmt_set_memory_owner 确保不会用错内存 ? 可能和安全性相关,不是很懂
  8. rmt_set_tx_loop_mode 开启循环模式 一直连续发送
  9. rmt_set_rx_filter 接收滤波, 可以滤除一些杂波 短的波形
  10. rmt_set_source_clk 设置时钟源
  11. rmt_set_idle_level 设置空闲状态的电平
  12. rmt_get_status 获得当前的状态
  13. rmt_set_intr_enable_mask 开中断
  14. rmt_clr_intr_enable_mask 关中断
  15. rmt_set_rx_intr_en 开接收的 中断
  16. rmt_set_pin 设置对应的rmt通道的引脚
  17. rmt_config 总体的配置函数
  18. rmt_isr_register 中断处理函数注册
  19. rmt_isr_deregister 反注册
  20. rmt_fill_tx_items 填充发送区
  21. rmt_driver_install 初始化rmt
  22. rmt_driver_uninstall 停止rmt
  23. rmt_get_channel_status 获得状态
  24. rmt_get_counter_clock 获得计数器的频率
  25. rmt_write_items
  26. rmt_wait_tx_done 等待发送结束
  27. rmt_get_ringbuf_handle 处理接收到的数据。接收到的数据将被放入环形缓冲区
  28. rmt_translator_init 协议转换器 一些标准的协议可以用转换器生成对应的 item
  29. rmt_write_sample 发送一些u8 类型的值出去
  30. rmt_register_tx_end_callback 注册发送结束中断函数
/**
* @brief Type of RMT Tx End callback function
*
*/
typedef void (*rmt_tx_end_fn_t)(rmt_channel_t channel, void *arg);

/**
* @brief Structure encapsulating a RMT TX end callback
*/
typedef struct {
    rmt_tx_end_fn_t function; /*!< Function which is called on RMT TX end */
    void *arg;                /*!< Optional argument passed to function */
} rmt_tx_end_callback_t;

/**
* @brief User callback function to convert uint8_t type data to rmt format(rmt_item32_t).
*
*        This function may be called from an ISR, so, the code should be short and efficient.
*
* @param  src Pointer to the buffer storing the raw data that needs to be converted to rmt format.
* @param[out] dest Pointer to the buffer storing the rmt format data.
* @param  src_size The raw data size.
* @param  wanted_num The number of rmt format data that wanted to get.
* @param[out] translated_size The size of the raw data that has been converted to rmt format,
*             it should return 0 if no data is converted in user callback.
* @param[out] item_num The number of the rmt format data that actually converted to,
*             it can be less than wanted_num if there is not enough raw data, but cannot exceed wanted_num.
*             it should return 0 if no data was converted.
*
* @note
*       In fact, item_num should be a multiple of translated_size, e.g. :
*       When we convert each byte of uint8_t type data to rmt format data,
*       the relation between item_num and translated_size should be `item_num = translated_size*8`.
*/
typedef void (*sample_to_rmt_t)(const void *src, rmt_item32_t *dest, size_t src_size, size_t wanted_num, size_t *translated_size, size_t *item_num);

/**
* @brief Set RMT clock divider, channel clock is divided from source clock.
*
* @param channel RMT channel
* @param div_cnt RMT counter clock divider
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_clk_div(rmt_channel_t channel, uint8_t div_cnt);

/**
* @brief Get RMT clock divider, channel clock is divided from source clock.
*
* @param channel RMT channel
* @param div_cnt pointer to accept RMT counter divider
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_clk_div(rmt_channel_t channel, uint8_t *div_cnt);

/**
* @brief Set RMT RX idle threshold value
*
*        In receive mode, when no edge is detected on the input signal
*        for longer than idle_thres channel clock cycles,
*        the receive process is finished.
*
* @param channel RMT channel
* @param thresh RMT RX idle threshold
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_rx_idle_thresh(rmt_channel_t channel, uint16_t thresh);

/**
* @brief Get RMT idle threshold value.
*
*        In receive mode, when no edge is detected on the input signal
*        for longer than idle_thres channel clock cycles,
*        the receive process is finished.
*
* @param channel RMT channel
* @param thresh pointer to accept RMT RX idle threshold value
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_rx_idle_thresh(rmt_channel_t channel, uint16_t *thresh);

/**
* @brief Set RMT memory block number for RMT channel
*
*        This function is used to configure the amount of memory blocks allocated to channel n
*        The 8 channels share a 512x32-bit RAM block which can be read and written
*        by the processor cores over the APB bus, as well as read by the transmitters
*        and written by the receivers.
*
*        The RAM address range for channel n is start_addr_CHn to end_addr_CHn, which are defined by:
*        Memory block start address is RMT_CHANNEL_MEM(n) (in soc/rmt_reg.h),
*        that is, start_addr_chn = RMT base address + 0x800 + 64 ∗ 4 ∗ n, and
*        end_addr_chn = RMT base address + 0x800 +  64 ∗ 4 ∗ n + 64 ∗ 4 ∗ RMT_MEM_SIZE_CHn mod 512 ∗ 4
*
*        @note
*        If memory block number of one channel is set to a value greater than 1, this channel will occupy the memory
*        block of the next channel.
*        Channel 0 can use at most 8 blocks of memory, accordingly channel 7 can only use one memory block.
*
* @param channel RMT channel
* @param rmt_mem_num RMT RX memory block number, one block has 64 * 32 bits.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_mem_block_num(rmt_channel_t channel, uint8_t rmt_mem_num);

/**
* @brief Get RMT memory block number
*
* @param channel RMT channel
* @param rmt_mem_num Pointer to accept RMT RX memory block number
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_mem_block_num(rmt_channel_t channel, uint8_t *rmt_mem_num);

/**
* @brief Configure RMT carrier for TX signal.
*
*        Set different values for carrier_high and carrier_low to set different frequency of carrier.
*        The unit of carrier_high/low is the source clock tick, not the divided channel counter clock.
*
* @param channel RMT channel
* @param carrier_en Whether to enable output carrier.
* @param high_level High level duration of carrier
* @param low_level Low level duration of carrier.
* @param carrier_level Configure the way carrier wave is modulated for channel.
*     - 1'b1:transmit on low output level
*     - 1'b0:transmit on high output level
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_tx_carrier(rmt_channel_t channel, bool carrier_en, uint16_t high_level, uint16_t low_level, rmt_carrier_level_t carrier_level);

/**
* @brief Set RMT memory in low power mode.
*
*        Reduce power consumed by memory. 1:memory is in low power state.
*
* @param channel RMT channel
* @param pd_en RMT memory low power enable.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_mem_pd(rmt_channel_t channel, bool pd_en);

/**
* @brief Get RMT memory low power mode.
*
* @param channel RMT channel
* @param pd_en Pointer to accept RMT memory low power mode.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_mem_pd(rmt_channel_t channel, bool *pd_en);

/**
* @brief Set RMT start sending data from memory.
*
* @param channel RMT channel
* @param tx_idx_rst Set true to reset memory index for TX.
*                   Otherwise, transmitter will continue sending from the last index in memory.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_tx_start(rmt_channel_t channel, bool tx_idx_rst);

/**
* @brief Set RMT stop sending.
*
* @param channel RMT channel
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_tx_stop(rmt_channel_t channel);

/**
* @brief Set RMT start receiving data.
*
* @param channel RMT channel
* @param rx_idx_rst Set true to reset memory index for receiver.
*                   Otherwise, receiver will continue receiving data to the last index in memory.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_rx_start(rmt_channel_t channel, bool rx_idx_rst);

/**
* @brief Set RMT stop receiving data.
*
* @param channel RMT channel
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_rx_stop(rmt_channel_t channel);

/**
* @brief Reset RMT TX/RX memory index.
*
* @param channel RMT channel
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_memory_rw_rst(rmt_channel_t channel);

/**
* @brief Set RMT memory owner.
*
* @param channel RMT channel
* @param owner To set when the transmitter or receiver can process the memory of channel.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_memory_owner(rmt_channel_t channel, rmt_mem_owner_t owner);

/**
* @brief Get RMT memory owner.
*
* @param channel RMT channel
* @param owner Pointer to get memory owner.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_memory_owner(rmt_channel_t channel, rmt_mem_owner_t *owner);

/**
* @brief Set RMT tx loop mode.
*
* @param channel RMT channel
* @param loop_en Enable RMT transmitter loop sending mode.
*                If set true, transmitter will continue sending from the first data
*                to the last data in channel over and over again in a loop.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_tx_loop_mode(rmt_channel_t channel, bool loop_en);

/**
* @brief Get RMT tx loop mode.
*
* @param channel RMT channel
* @param loop_en Pointer to accept RMT transmitter loop sending mode.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_tx_loop_mode(rmt_channel_t channel, bool *loop_en);

/**
* @brief Set RMT RX filter.
*
*        In receive mode, channel will ignore input pulse when the pulse width is smaller than threshold.
*        Counted in source clock, not divided counter clock.
*
* @param channel RMT channel
* @param rx_filter_en To enable RMT receiver filter.
* @param thresh Threshold of pulse width for receiver.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_rx_filter(rmt_channel_t channel, bool rx_filter_en, uint8_t thresh);

/**
* @brief Set RMT source clock
*
*        RMT module has two clock sources:
*        1. APB clock which is 80Mhz
*        2. REF tick clock, which would be 1Mhz (not supported in this version).
*
* @param channel RMT channel
* @param base_clk To choose source clock for RMT module.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_source_clk(rmt_channel_t channel, rmt_source_clk_t base_clk);

/**
* @brief Get RMT source clock
*
*        RMT module has two clock sources:
*        1. APB clock which is 80Mhz
*        2. REF tick clock, which would be 1Mhz (not supported in this version).
*
* @param channel RMT channel
* @param src_clk Pointer to accept source clock for RMT module.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_source_clk(rmt_channel_t channel, rmt_source_clk_t *src_clk);

/**
* @brief Set RMT idle output level for transmitter
*
* @param channel RMT channel
* @param idle_out_en To enable idle level output.
* @param level To set the output signal's level for channel in idle state.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_idle_level(rmt_channel_t channel, bool idle_out_en, rmt_idle_level_t level);

/**
* @brief Get RMT idle output level for transmitter
*
* @param channel RMT channel
* @param idle_out_en Pointer to accept value of enable idle.
* @param level Pointer to accept value of output signal's level in idle state for specified channel.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_idle_level(rmt_channel_t channel, bool *idle_out_en, rmt_idle_level_t *level);

/**
* @brief Get RMT status
*
* @param channel RMT channel
* @param status Pointer to accept channel status.
*        Please refer to RMT_CHnSTATUS_REG(n=0~7) in `rmt_reg.h` for more details of each field.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_status(rmt_channel_t channel, uint32_t *status);

/**
* @brief Set mask value to RMT interrupt enable register.
*
* @param mask Bit mask to set to the register
*
*/
void rmt_set_intr_enable_mask(uint32_t mask);

/**
* @brief Clear mask value to RMT interrupt enable register.
*
* @param mask Bit mask to clear the register
*
*/
void rmt_clr_intr_enable_mask(uint32_t mask);

/**
* @brief Set RMT RX interrupt enable
*
* @param channel RMT channel
* @param en enable or disable RX interrupt.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_rx_intr_en(rmt_channel_t channel, bool en);

/**
* @brief Set RMT RX error interrupt enable
*
* @param channel RMT channel
* @param en enable or disable RX err interrupt.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_err_intr_en(rmt_channel_t channel, bool en);

/**
* @brief Set RMT TX interrupt enable
*
* @param channel RMT channel
* @param en enable or disable TX interrupt.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en);

/**
* @brief Set RMT TX threshold event interrupt enable
*
* An interrupt will be triggered when the number of transmitted items reaches the threshold value
*
* @param channel RMT channel
* @param en enable or disable TX event interrupt.
* @param evt_thresh RMT event interrupt threshold value
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_tx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh);

/**
* @brief Set RMT pin
*
* @param channel RMT channel
* @param mode TX or RX mode for RMT
* @param gpio_num GPIO number to transmit or receive the signal.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_num);

/**
* @brief Configure RMT parameters
*
* @param rmt_param RMT parameter struct
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_config(const rmt_config_t *rmt_param);

/**
* @brief Register RMT interrupt handler, the handler is an ISR.
*
*        The handler will be attached to the same CPU core that this function is running on.
*
* @note  If you already called rmt_driver_install to use system RMT driver,
*        please do not register ISR handler again.
*
* @param fn Interrupt handler function.
* @param arg Parameter for the handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
*        ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param handle If non-zero, a handle to later clean up the ISR gets stored here.
*
* @return
*     - ESP_OK Success
*     - ESP_ERR_INVALID_ARG Function pointer error.
*     - ESP_FAIL System driver installed, can not register ISR handler for RMT
*/
esp_err_t rmt_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, rmt_isr_handle_t *handle);

/**
* @brief   Deregister previously registered RMT interrupt handler
*
* @param handle Handle obtained from rmt_isr_register
*
* @return
*     - ESP_OK Success
*     - ESP_ERR_INVALID_ARG Handle invalid
*/
esp_err_t rmt_isr_deregister(rmt_isr_handle_t handle);

/**
* @brief Fill memory data of channel with given RMT items.
*
* @param channel RMT channel
* @param item Pointer of items.
* @param item_num RMT sending items number.
* @param mem_offset Index offset of memory.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_fill_tx_items(rmt_channel_t channel, const rmt_item32_t *item, uint16_t item_num, uint16_t mem_offset);

/**
* @brief Initialize RMT driver
*
* @param channel RMT channel
* @param rx_buf_size Size of RMT RX ringbuffer. Can be 0 if the RX ringbuffer is not used.
* @param intr_alloc_flags Flags for the RMT driver interrupt handler. Pass 0 for default flags. See esp_intr_alloc.h for details.
*        If ESP_INTR_FLAG_IRAM is used, please do not use the memory allocated from psram when calling rmt_write_items.
*
* @return
*     - ESP_ERR_INVALID_STATE Driver is already installed, call rmt_driver_uninstall first.
*     - ESP_ERR_NO_MEM Memory allocation failure
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr_alloc_flags);

/**
* @brief Uninstall RMT driver.
*
* @param channel RMT channel
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_driver_uninstall(rmt_channel_t channel);

/**
* @brief Get the current status of eight channels.
*
* @note Do not call this function if it is possible that `rmt_driver_uninstall` will be called at the same time.
*
* @param[out] channel_status store the current status of each channel
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter is NULL
*     - ESP_OK Success
*/
esp_err_t rmt_get_channel_status(rmt_channel_status_result_t *channel_status);

/**
* @brief Get speed of channel's internal counter clock.
*
* @param channel RMT channel
* @param[out] clock_hz counter clock speed, in hz
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter is NULL
*     - ESP_OK Success
*/
esp_err_t rmt_get_counter_clock(rmt_channel_t channel, uint32_t *clock_hz);

/**
* @brief RMT send waveform from rmt_item array.
*
*        This API allows user to send waveform with any length.
*
* @param channel RMT channel
* @param rmt_item head point of RMT items array.
*        If ESP_INTR_FLAG_IRAM is used, please do not use the memory allocated from psram when calling rmt_write_items.
* @param item_num RMT data item number.
* @param wait_tx_done
*        - If set 1, it will block the task and wait for sending done.
*        - If set 0, it will not wait and return immediately.
*
*         @note
*         This function will not copy data, instead, it will point to the original items,
*         and send the waveform items.
*         If wait_tx_done is set to true, this function will block and will not return until
*         all items have been sent out.
*         If wait_tx_done is set to false, this function will return immediately, and the driver
*         interrupt will continue sending the items. We must make sure the item data will not be
*         damaged when the driver is still sending items in driver interrupt.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t *rmt_item, int item_num, bool wait_tx_done);

/**
* @brief Wait RMT TX finished.
*
* @param channel RMT channel
* @param wait_time Maximum time in ticks to wait for transmission to be complete.  If set 0, return immediately with ESP_ERR_TIMEOUT if TX is busy (polling).
*
* @return
*     - ESP_OK RMT Tx done successfully
*     - ESP_ERR_TIMEOUT Exceeded the 'wait_time' given
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_FAIL Driver not installed
*/
esp_err_t rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time);

/**
* @brief Get ringbuffer from RMT.
*
*        Users can get the RMT RX ringbuffer handle, and process the RX data.
*
* @param channel RMT channel
* @param buf_handle Pointer to buffer handle to accept RX ringbuffer handle.
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_get_ringbuf_handle(rmt_channel_t channel, RingbufHandle_t *buf_handle);

/**
* @brief Init rmt translator and register user callback.
*        The callback will convert the raw data that needs to be sent to rmt format.
*        If a channel is initialized more than once, tha user callback will be replaced by the later.
*
* @param channel RMT channel .
* @param fn Point to the data conversion function.
*
* @return
*     - ESP_FAIL Init fail.
*     - ESP_OK Init success.
*/
esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn);

/**
* @brief Translate uint8_t type of data into rmt format and send it out.
*        Requires rmt_translator_init to init the translator first.
*
* @param channel RMT channel .
* @param src Pointer to the raw data.
* @param src_size The size of the raw data.
* @param wait_tx_done Set true to wait all data send done.
*
* @return
*     - ESP_FAIL Send fail
*     - ESP_OK Send success
*/
esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src_size, bool wait_tx_done);

/**
* @brief Registers a callback that will be called when transmission ends.
*
*        Called by rmt_driver_isr_default in interrupt context.
*
* @note Requires rmt_driver_install to install the default ISR handler.
*
* @param function Function to be called from the default interrupt handler or NULL.
* @param arg Argument which will be provided to the callback when it is called.
*
* @return the previous callback settings (members will be set to NULL if there was none)
*/
rmt_tx_end_callback_t rmt_register_tx_end_callback(rmt_tx_end_fn_t function, void *arg);

#if SOC_RMT_SUPPORT_RX_PINGPONG
/**
* @brief Set RMT RX threshold event interrupt enable
*
* An interrupt will be triggered when the number of received items reaches the threshold value
*
* @param channel RMT channel
* @param en enable or disable RX event interrupt.
* @param evt_thresh RMT event interrupt threshold value
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_set_rx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh);
#endif

#if SOC_RMT_SUPPORT_TX_GROUP
/**
* @brief Add channel into a group (channels in the same group will transmit simultaneously)
*
* @param channel RMT channel
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_add_channel_to_group(rmt_channel_t channel);

/**
* @brief Remove channel out of a group
*
* @param channel RMT channel
*
* @return
*     - ESP_ERR_INVALID_ARG Parameter error
*     - ESP_OK Success
*/
esp_err_t rmt_remove_channel_from_group(rmt_channel_t channel);

4. 测试代码

官方在这里提供了三个测试例程:
分别是

  1. 摩斯密码发送 “ESP”
  2. 红外的IR_NEC协议向0x10 地址发送 自增的指令码
  3. WS2812 的控制代码
    官方的代码我就不去展示了,没意思,可以去这个路径自己去找一下
examples\peripherals\rmt

esp32 红外接收原始数据 esp32的红外发射程序_ESP32_03

我需要做的是学习空调的数据发送形式,空调的发送中间存在一个40ms的间隔,绝大多数的学习型遥控器还不能学习那么多的bit,任重而道远啊