当前位置:   article > 正文

ESP32_IDF学习(6)--RMT_esp32 rmt

esp32 rmt

RMT

RMT(远程控制)模块驱动器可用于发送和接收红外远程控制信号。由于RMT模块的灵活性,该驱动器还可用于产生或接收许多其他类型的信号。

该信号由一系列脉冲组成,由RMT的发射器根据一系列数值产生。这些数值定义了脉冲持续时间 和二进制电平,见下文。发射器也可以提供一个载波,并用提供的脉冲对其进行调制。

反向操作由接收器执行,一系列的脉冲被解码成一个包含脉冲持续时间和二进制电平的数值列 表。可以应用一个滤波器来去除输入信号中的高频噪声。

有几个典型的步骤来设置和操作RMT

  1. 配置驱动程序
  2. 发送数据或接受数据
  3. 改变操作参数
  4. 使用中断

RMT有八个通道,编号从0到7。每个通道都能独立发送或接收数据。它们被rmt_channel_t所定义。

配置驱动程序

有几个参数定义了特定通道的运作方式。这些参数中的大多数参数是通过设置结构的rmt_config_t特定成员来配置的。其中一些参数对发射或接收模式都是通用的,有些是特定模式。它们都在下面讨论。

常见参数

  • 要配置的通道,从rmt_channel_t枚举器中选一个。
  • RMT操作模式-这个是用来选择发送还是接收,通过设置rem_modermt_mode_t数值之一来选择。
  • 发送或接收RMT信号引脚编号是什么,通过设置gpio_num选择。
  • 通道将使用多少内存块,用men_block_num设置。
  • 通道的额外杂项可以在标志中设置。
    • RMT_CHANNEL_FLAGS_AWARE_DFS被设置时,RMT通道将采用 REF_ TICK或XTAL作为源时钟。这样做的好处是,即使APB时钟改变,RMT通道也能 继续工作。更多信息请参见电源管理。
  • 一个时钟分频器,它将决定RMT发射器产生的脉冲长度范围或接收器的判别。通过设置 clk_div为[1 … 255]范围内的一个值来选择。RMT的源时钟通常为APB CLK,默认为80Mhz 。但是当RMT_CHANNEL_FLAGS_AWARE_DFS被设置为标志时,RMT的源时钟会被改变为 REF_TICK或XTAL。

时钟分频器之后的方波周期称为 “刻度”。由RMT发射器产生的脉冲或由接收器辨别的脉冲的长度以 "刻度"的数量配置。

还有一些特定的参数需要设置,这取决于所选通道是配置在发射模式还是接收模式

发送模式

当在发送模式下配置通道时,设置tx_config和以下结构体成员的rmt_tx_config_t:

  • 循环传输当前配置的数据项目—loop_en
  • 启用RMT载波信号—carrier_en
  • 载波信号的频率,单位为HZ—carrier_freq_hz
  • 载波信号的占空比,单位是(%)—carrier_duty_percent
  • 使用载波时,RMT输出的电平—carrier_level
  • 空闲时启用RMT输出—idle_output_en
  • 设置空闲时RMT输出信号电平—idle_level
/**
 * @brief Default configuration for Tx channel
 *
 */
#define RMT_DEFAULT_CONFIG_TX(gpio, channel_id)      \
    {                                                \
        .rmt_mode = RMT_MODE_TX,                     \
        .channel = channel_id,                       \
        .gpio_num = gpio,                            \
        .clk_div = 80,                               \
        .mem_block_num = 1,                          \
        .flags = 0,                                  \
        .tx_config = {                               \
            .carrier_freq_hz = 38000,                \
            .carrier_level = RMT_CARRIER_LEVEL_HIGH, \
            .idle_level = RMT_IDLE_LEVEL_LOW,        \
            .carrier_duty_percent = 33,              \
            .carrier_en = false,                     \
            .loop_en = false,                        \
            .idle_output_en = true,                  \
        }                                            \
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

接受模式

在接受模式下,设置rx_config和以下结构体成员rmt_rx_config_t

  • 在RMT接收器的输入端启用一个过滤器—filter_en
  • 滤波器的阈值,以”刻度“数设置—filter_ticks_thresh。短于此设置的脉冲将被过滤掉。注意 :输入刻度值的范围是[0…255]。
  • 脉冲长度阈值,将使RMT接收器处于空闲状态,以“刻度”数为单位设置—idle_threshold。接收器将忽略长于此设置的脉冲。
/**
 * @brief Default configuration for RX channel
 *
 */
#define RMT_DEFAULT_CONFIG_RX(gpio, channel_id) \
    {                                           \
        .rmt_mode = RMT_MODE_RX,                \
        .channel = channel_id,                  \
        .gpio_num = gpio,                       \
        .clk_div = 80,                          \
        .mem_block_num = 1,                     \
        .flags = 0,                             \
        .rx_config = {                          \
            .idle_threshold = 12000,            \
            .filter_ticks_thresh = 100,         \
            .filter_en = true,                  \
        }                                       \
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

最终设置

一旦给rmt_config_t结构体被填充了参数,然后应该调用rmt_config()以使配置生效。

最后一个配置步骤是在内存中安装驱动程序,调用rmt_driver_install()。如果这个函数的参数rx_buf_size>0,那么就有一个环形缓冲器用于传入的数据将被分配。一个默认的ISR处理程序将被安装,参见使用中断中的说明。

现在,根据通道的配置情况,我们已经准备好发送数据接收数据了,这将在下两节中描述。

发送数据

在能够发射一些RMT脉冲之前,我们需要定义脉冲模式。RMT控制器识别的最小模式,后来被称为 “项目”,以rmt_item32_t结构提供 。每个项目由两对两个值组成。一对中的第一个值描述了信号的持续时间,长度为15bits,第二项提供了信号的电平(高或低),包含在一个bits中。下面介绍一个由几个项目组成的块和一个项目的结构。

这些项目是通过调用函数rmt_write_items()提供给RMT控制器的。这个函数也自动触发了传输的开始。它可能被调用以等待传输完成或在传输开始后退出。在这种情况下,你可以等待传输结束后,通过调用rmt_wait_tx_done()。这个函数不限制数据项目进行传输。它使用一个中断来连续复制新的数据块到RMT的内部存储器,因为之前提供的数据被送出了。

另一种提供数据传输的方式是通过调用rmt_fill_tx_items()。在这种情况下传输不会自动开始。要控制传输过程,请使用rmt_tx_start()rmt_tx_stop()。要发送的项目数量受限于在RMT控制器的内部存储器中分配的内存块,详细见rmt_set_mem_block_num()

接收数据

RMT RX通道不能接收项目大于其内存块大小的数据包。如果你把内存块数量设置为1,那么这个RX通道就不能接收超过64个项目的数据包。这是一个硬件限制。

在启动接收机之前,我们需要一些存储空间来存放传入的项目。RMT控制器有512 x 32位的内部RAM,由所有八个通道共享。

在通常情况下,它不足以作为所有传入(和传出)项目的最终存储。因此,这个API支持实时检索传入的项目,将它们保存在一个由用户决定大小的环形缓冲区。这个大小是在调用 rmt_driver_install()上面讨论过。为了得到这个缓冲区的句柄,可以调用rmt_get_ringbuf_handle()

完成上述步骤后,我们可以通过rmt_rx_start()调用和转到检查缓冲区内的内容。要做到这一点,你可以使用FreeRTOS的普通函数与环形缓冲区互动。

要停止接收机,请使用rmt_rx_stop()

改变操作参数

前面描述的rmt_config()函数提供了一个方便的方法来设置几个配置参数一次就能完成。这通常是在应用程序启动时完成的。然后,当应用程序运行时,API提供了另一种方法,通过调用专用函数来更新各个参数。每个函数指的是作为第一个输入参数提供的特定RMT通道。大多数函数都有对应的_get_来读回当前配置的值。

发送和接收模式的共同参数

  • 在RMT的输入或输出端选择一个GPIO引脚编号——rmt_set_pin()
  • 为传入或传出的数据分配的内存块的数量——rmt_set_mem_pd()
  • 设置时钟分频器——rmt_set_clk_div()
  • 选择时钟源,注意目前只支持一个时钟源,即80Mhz的APB时钟——rmt_set_source_clk()

发送模式参数

  • 启用或禁用发射器的回环模式——rmt_set_tx_loop_mode()
  • 在输出端应用载波的二进制电平——rmt_set_tx_carrier(),选自rmt_carrier_level_t
  • 决定发射器空闲时输出的二进制电平——rmt_set_idle_level(),选自rmt_idle_level_t

接收模式参数

  • 滤波器的设置——rmt_set_rx_filter()
  • 接收器的阈值设置——rmt_set_rx_idle_thresh()
  • 发送方或接收方是否有权访问RMT的内存——rmt_set_memory_owner(),选自rmt_men_owner_t

使用中断

为RMT控制器注册一个中断处理程序是通过调用rmt_isr_register()

rmt_driver_install()调用系统RMT驱动时,一个默认的ISR正在被调用安装。在这种情况下,你不需要注册rmt_isr_register()一个通用的ISR处理程序。

RMT控制器在下面描述的四个特定事件中触发中断。为了启用这些事件的中断,提供了以下功能。

  • RMT接收器已经完成了对信号的接收——rmt_set_rx_intr_en()
  • RMT发射器已经完成了信号的传输——rmt_set_tx_intr_en()
  • 发射器发送的事件数量与一个阈值相符——rmt_set_tx_thr_intr_en()
  • 违反了对RMT内存块的所有权——rmt_set_err_intr_en()

设置或清除特定通道和事件的中断使能掩码也可以通过rmt_set_intr_enable_mask()rmt_set_intr_enable_mask()

如果你不再需要一个ISR,你可以通过调用一个函数来取消它的注册rmt_isr_deregister()

我们不建议用户在他们的应用程序中注册一个中断处理程序。RMT驱动高度依赖于中断,尤其是在以“ping-pong”方式时,所以驱动本身已经注册了一个默认的处理程序,叫做rmt_driver_isr_default相反,如果你想要的是在处理完成后得到一个通知,那么就用rmt_register_tx_end_callback()

卸载驱动程序

如果RMT驱动程序已经安装rmt_driver_install()了一段特定的时间。的时间,然后就不需要了,可以通过调用以下命令删除驱动程序以释放分配的资源rmt_driver_uninstall()
反,如果你想要的是在处理完成后得到一个通知,那么就用rmt_register_tx_end_callback()

卸载驱动程序

如果RMT驱动程序已经安装rmt_driver_install()了一段特定的时间。的时间,然后就不需要了,可以通过调用以下命令删除驱动程序以释放分配的资源rmt_driver_uninstall()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/389973
推荐阅读
相关标签
  

闽ICP备14008679号