1. 技术背景
最近公司在用ESP32的模组方案实现智能音箱的相关功能的项目。需要展示模组的网络状态以及音箱的语音交互状态,找了一家RGB灯板供应商。需要模组通过一个io口输出脉冲波形,来控制灯板切换模式,展示不同的状态。供应商给到控制灯效模式的文档大概如下图:
看到这个波形我首先想到的是PWM,和timer中断控制io状态翻转。由于每个脉冲的占空比都可能要改变,使用ESP32的PWM并不好生成准确的脉冲。使用timer的中断触发翻转io电平虽然可以实现基本的波形。但是由于频繁进入中断,比较耗费CPU的资源。
于是重新翻看乐鑫官网的ESP32 datasheet,终于在数据手册中找到了一章关于红外远程控制的功能描述,发现可以通过RMT模块来指定IO输出指定的脉冲,实在是太方便了。
在乐鑫的ESP32开发指南页面也有RMT功能和API详细的描述。
我这里基于乐鑫SDK的demo code修改实现指定脉冲波形输出。
esp-idf/examples/peripherals/rmt_tx/main/rmt_tx_main.c
主要修改rmt初始化配置参数
rmt_item32_t items[] = {
// E : dot
{{{ 32767, 1, 32767, 0 }}}, // dot
//
{{{ 32767, 0, 32767, 0 }}}, // SPACE
// S : dot, dot, dot
{{{ 32767, 1, 32767, 0 }}}, // dot
{{{ 32767, 1, 32767, 0 }}}, // dot
{{{ 32767, 1, 32767, 0 }}}, // dot
//
{{{ 32767, 0, 32767, 0 }}}, // SPACE
// P : dot, dash, dash, dot
{{{ 32767, 1, 32767, 0 }}}, // dot
{{{ 32767, 1, 32767, 1 }}},
{{{ 32767, 1, 32767, 0 }}}, // dash
{{{ 32767, 1, 32767, 1 }}},
{{{ 32767, 1, 32767, 0 }}}, // dash
{{{ 32767, 1, 32767, 0 }}}, // dot
// RMT end marker
{{{ 0, 1, 0, 0 }}}
};
rmt_config_t config;
config.rmt_mode = RMT_MODE_TX; //发送
config.channel = RMT_TX_CHANNEL; //通道
config.gpio_num = RMT_TX_GPIO; //脉冲输出的管脚
config.mem_block_num = 1;
config.tx_config.loop_en = false;
config.tx_config.carrier_en = false;
config.tx_config.idle_output_en = true;
config.tx_config.idle_level = 0;
config.clk_div = LED_RMT_DIVIDER; //时钟分频
ESP_ERROR_CHECK(rmt_config(&config));
ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
最后通过 rmt_write_items(RMT_TX_CHANNEL, items, LED_ITEM_MAX, true);来输出我们定义在items中的波形,可以通过逻辑分析仪抓取输出的波形,还是很标准的。
感谢大佬的奉献,让我可以快速完成这个功能的开发。
GitHub分享ESP32 RMT demo