发现esp32 Arduino示例RMTloopback发送与返回的值不同,存在每4个十六进制数向前位移,应该是库的问题?搞了好几天了
// RMT模块双工通信示例(发送端GPIO13,接收端GPIO12)
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h" // 事件组用于异步通知
#include "Arduino.h" // Arduino核心库
#include "esp32-hal.h" // ESP32硬件抽象层
// RMT数据缓冲区(注意:ESP32 RMT每个数据项包含高低电平两个时段)
// 使用sizeof(rmt_data_t)确认结构体大小为4字节(32位)
rmt_data_t my_data[256]; // 接收缓冲区
rmt_data_t data[256]; // 发送缓冲区
// RMT对象指针
rmt_obj_t* rmt_send = NULL; // 发送器实例
rmt_obj_t* rmt_recv = NULL; // 接收器实例
static EventGroupHandle_t events; // 用于接收完成事件通知
void setup()
{
Serial.begin(115200);
events = xEventGroupCreate(); // 创建事件组
// 初始化发送器(GPIO13,发送模式,64个RMT内存块)
if ((rmt_send = rmtInit(13, true, RMT_MEM_64)) == NULL)
{
Serial.println("init sender failed\n"); // 需检查GPIO复用情况
}
// 初始化接收器(GPIO12,接收模式,192个RMT内存块)
if ((rmt_recv = rmtInit(12, false, RMT_MEM_192)) == NULL)
{
Serial.println("init receiver failed\n"); // 注意内存分配是否充足
}
// 设置发送器时钟(目标100ns/tick,返回实际设置值)
float realSendTick = rmtSetTick(rmt_send, 100); // 实际值可能受时钟分频限制
float realRecvTick = rmtSetTick(rmt_recv, 100); // 接收端设置相同时钟
printf("real realSendTick set to: %fns\n", realSendTick); // 建议检查是否接近预期值
printf("real realRecvTick set to: %fns\n", realRecvTick); // 建议检查是否接近预期值
}
void loop()
{
// 初始化发送数据(生成特定测试模式)
int i;
for (i = 0; i < 64; i++) {
// 15位的duration字段最大值为32767(0x7FFF),超限会截断
//
// 数据格式:0x80010001 + ((i%13)<<16) + 13-(i%13)
// xx 高位:0x8001表示电平持续时间(高电平800ns,低电平100ns)
// 中间:i%13的循环模式
// 低位:13-(i%13)的反向模式
data[i].val = 0x80010001 + ((i % 13) << 16) + 13 - (i % 13);
}
data[63].val = 0; // 结束标志(持续时间为0)
// 启动异步接收(最大等待时间100 ticks)
// 参数说明:接收对象,接收缓冲区,最大接收项数,事件组,是否阻塞等待数据,超时时间
rmtReadAsync(rmt_recv, my_data, 64, events, false, 0);
// 发送数据(连续模式)
// 参数说明:发送对象,数据指针,发送项数(注意实际发送可能超过100项)
rmtWrite(rmt_send, data, 64);
// 等待接收完成事件(阻塞等待)
// xEventGroupWaitBits(事件组句柄, 等待事件位组合, 等待后是否清除事件位, 需满足所有事件位(pdFALSE为任一), 等待超时时间)
xEventGroupWaitBits(events, RMT_FLAG_RX_DONE, 1, 1, portMAX_DELAY);
// 打印前60项对比数据(每行4组)
for (i = 0; i < 64; i++)
{
// 格式:接收值=发送值
Serial.printf("%08x=%08x ", my_data[i].val, data[i].val );
if (!((i + 1) % 4)) Serial.println("------------------\n"); // 每4组换行
/*
Serial.printf("0X%08x = 0X%08x \n", my_data[i].val, data[i].val );
Serial.printf("duration0 = 0X%04x duration1 = 0X%04x \n", data[i].duration0, data[i].duration1 );
Serial.printf("level0 = %d level1 = %d \n", data[i].level0, data[i].level1 );
Serial.printf("duration0 = 0X%04x duration1 = 0X%04x \n", my_data[i].duration0, my_data[i].duration1 );
Serial.printf("level0 = %d level1 = %d \n", my_data[i].level0, my_data[i].level1 );
*/
}
Serial.println("\n");
delay(3000); // 延时(可根据需要调整)
}
/*
以下是串口结果
02:55:57.803 -> 000d8001=8001000e 000c8002=8002000d 000b8003=8003000c 000a8004=8004000b
02:55:57.803 ->
02:55:57.803 -> 00098005=8005000a 00088006=80060009 00078007=80070008 00068008=80080007
02:55:57.803 ->
02:55:57.803 -> 00058009=80090006 0004800a=800a0005 0003800b=800b0004 0002800c=800c0003
02:55:57.837 ->
02:55:57.837 -> 000e800d=800d0002 000d8001=8001000e 000c8002=8002000d 000b8003=8003000c
02:55:57.837 ->
02:55:57.837 -> 000a8004=8004000b 00098005=8005000a 00088006=80060009 00078007=80070008
02:55:57.837 ->
02:55:57.837 -> 00068008=80080007 00058009=80090006 0004800a=800a0005 0003800b=800b0004
02:55:57.837 ->
02:55:57.837 -> 0002800c=800c0003 000e800d=800d0002 000d8001=8001000e 000c8002=8002000d
02:55:57.837 ->
02:55:57.837 -> 000b8003=8003000c 000a8004=8004000b 00098005=8005000a 00088006=80060009
*/
// RMT模块双工通信示例(发送端GPIO13,接收端GPIO12)
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h" // 事件组用于异步通知
#include "Arduino.h" // Arduino核心库
#include "esp32-hal.h" // ESP32硬件抽象层
// RMT数据缓冲区(注意:ESP32 RMT每个数据项包含高低电平两个时段)
// 使用sizeof(rmt_data_t)确认结构体大小为4字节(32位)
rmt_data_t my_data[256]; // 接收缓冲区
rmt_data_t data[256]; // 发送缓冲区
// RMT对象指针
rmt_obj_t* rmt_send = NULL; // 发送器实例
rmt_obj_t* rmt_recv = NULL; // 接收器实例
static EventGroupHandle_t events; // 用于接收完成事件通知
void setup()
{
Serial.begin(115200);
events = xEventGroupCreate(); // 创建事件组
// 初始化发送器(GPIO13,发送模式,64个RMT内存块)
if ((rmt_send = rmtInit(13, true, RMT_MEM_64)) == NULL)
{
Serial.println("init sender failed\n"); // 需检查GPIO复用情况
}
// 初始化接收器(GPIO12,接收模式,192个RMT内存块)
if ((rmt_recv = rmtInit(12, false, RMT_MEM_192)) == NULL)
{
Serial.println("init receiver failed\n"); // 注意内存分配是否充足
}
// 设置发送器时钟(目标100ns/tick,返回实际设置值)
float realSendTick = rmtSetTick(rmt_send, 100); // 实际值可能受时钟分频限制
float realRecvTick = rmtSetTick(rmt_recv, 100); // 接收端设置相同时钟
printf("real realSendTick set to: %fns\n", realSendTick); // 建议检查是否接近预期值
printf("real realRecvTick set to: %fns\n", realRecvTick); // 建议检查是否接近预期值
}
void loop()
{
// 初始化发送数据(生成特定测试模式)
int i;
for (i = 0; i < 64; i++) {
// 15位的duration字段最大值为32767(0x7FFF),超限会截断
//
// 数据格式:0x80010001 + ((i%13)<<16) + 13-(i%13)
// xx 高位:0x8001表示电平持续时间(高电平800ns,低电平100ns)
// 中间:i%13的循环模式
// 低位:13-(i%13)的反向模式
data[i].val = 0x80010001 + ((i % 13) << 16) + 13 - (i % 13);
}
data[63].val = 0; // 结束标志(持续时间为0)
// 启动异步接收(最大等待时间100 ticks)
// 参数说明:接收对象,接收缓冲区,最大接收项数,事件组,是否阻塞等待数据,超时时间
rmtReadAsync(rmt_recv, my_data, 64, events, false, 0);
// 发送数据(连续模式)
// 参数说明:发送对象,数据指针,发送项数(注意实际发送可能超过100项)
rmtWrite(rmt_send, data, 64);
// 等待接收完成事件(阻塞等待)
// xEventGroupWaitBits(事件组句柄, 等待事件位组合, 等待后是否清除事件位, 需满足所有事件位(pdFALSE为任一), 等待超时时间)
xEventGroupWaitBits(events, RMT_FLAG_RX_DONE, 1, 1, portMAX_DELAY);
// 打印前60项对比数据(每行4组)
for (i = 0; i < 64; i++)
{
// 格式:接收值=发送值
Serial.printf("%08x=%08x ", my_data[i].val, data[i].val );
if (!((i + 1) % 4)) Serial.println("------------------\n"); // 每4组换行
/*
Serial.printf("0X%08x = 0X%08x \n", my_data[i].val, data[i].val );
Serial.printf("duration0 = 0X%04x duration1 = 0X%04x \n", data[i].duration0, data[i].duration1 );
Serial.printf("level0 = %d level1 = %d \n", data[i].level0, data[i].level1 );
Serial.printf("duration0 = 0X%04x duration1 = 0X%04x \n", my_data[i].duration0, my_data[i].duration1 );
Serial.printf("level0 = %d level1 = %d \n", my_data[i].level0, my_data[i].level1 );
*/
}
Serial.println("\n");
delay(3000); // 延时(可根据需要调整)
}
/*
以下是串口结果
02:55:57.803 -> 000d8001=8001000e 000c8002=8002000d 000b8003=8003000c 000a8004=8004000b
02:55:57.803 ->
02:55:57.803 -> 00098005=8005000a 00088006=80060009 00078007=80070008 00068008=80080007
02:55:57.803 ->
02:55:57.803 -> 00058009=80090006 0004800a=800a0005 0003800b=800b0004 0002800c=800c0003
02:55:57.837 ->
02:55:57.837 -> 000e800d=800d0002 000d8001=8001000e 000c8002=8002000d 000b8003=8003000c
02:55:57.837 ->
02:55:57.837 -> 000a8004=8004000b 00098005=8005000a 00088006=80060009 00078007=80070008
02:55:57.837 ->
02:55:57.837 -> 00068008=80080007 00058009=80090006 0004800a=800a0005 0003800b=800b0004
02:55:57.837 ->
02:55:57.837 -> 0002800c=800c0003 000e800d=800d0002 000d8001=8001000e 000c8002=8002000d
02:55:57.837 ->
02:55:57.837 -> 000b8003=8003000c 000a8004=8004000b 00098005=8005000a 00088006=80060009
*/