完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
开发环境:
开发板:ESP32-C3-DEVKITM-1 IDE: Vscode esp-idf 操作系统:win10 IDF 版本:5.1.1 在使用RMT发射设置时,我发现esp-idf提供的例程只有对完整字节的处理,编码器时按照字节处理的。现在如果我有35bit的数据,应该怎样进行处理? 我需要处理的是前导码+35bit数据位+连接码+32bit数据位的数据 之前想用esp-idf 4版本的解决问题,但是4版本的选择不了时钟源 编码器部分: esp_err_t rmt_new_ir_nec_encoder(const ir_nec_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder) { esp_err_t ret = ESP_OK; //创建自定义编码器结构体,用于控制发送编码的流程 rmt_ir_nec_encoder_t *nec_encoder = NULL; ESP_GOTO_ON_FALSE(config ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); nec_encoder = calloc(1, sizeof(rmt_ir_nec_encoder_t)); ESP_GOTO_ON_FALSE(nec_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for ir nec encoder"); nec_encoder->base.encode = rmt_encode_ir_nec; //这个函数会在rmt发送数据的时候被调用,在这个函数增加额外代码进行控制 nec_encoder->base.del = rmt_del_ir_nec_encoder; //这个函数在卸载rmt时被调用 nec_encoder->base.reset = rmt_ir_nec_encoder_reset; //这个函数在复位rmt时被调用 rmt_copy_encoder_config_t copy_encoder_config = {}; ESP_GOTO_ON_ERROR(rmt_new_copy_encoder( copy_encoder_config, nec_encoder->copy_encoder), err, TAG, "create copy encoder failed"); // 拷贝一个编码器,用于传输恒定字符,起始位和连接位 nec_encoder->nec_leading_symbol = (rmt_symbol_word_t) { .level0 = 1, .duration0 = 4500ULL * config->resolution / 1000000, .level1 = 0, .duration1 = 9000ULL * config->resolution / 1000000, }; nec_encoder->nec_ending_symbol = (rmt_symbol_word_t) { .level0 = 1, .duration0 = 20000ULL * config->resolution / 1000000, .level1 = 0, .duration1 = 600 * config->resolution / 1000000, }; //新建一个编码器,用于0,1表示 rmt_bytes_encoder_config_t bytes_encoder_config = { .bit0 = { // .level0 = 1, .duration0 = 600 * config->resolution / 1000000, // T0H=560us .level1 = 0, .duration1 = 600 * config->resolution / 1000000, // T0L=560us }, .bit1 = { .level0 = 1, .duration0 = 1600 * config->resolution / 1000000, // T1H=560us .level1 = 0, .duration1 = 600 * config->resolution / 1000000, // T1L=1690us }, .flags.msb_first = 1, }; //传入编码器配置,获取数据编码器句柄 ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder( bytes_encoder_config, nec_encoder->bytes_encoder), err, TAG, "create bytes encoder failed"); //返回编码器 *ret_encoder = nec_encoder->base; return ESP_OK; err: if (nec_encoder) { if (nec_encoder->bytes_encoder) { rmt_del_encoder(nec_encoder->bytes_encoder); } if (nec_encoder->copy_encoder) { rmt_del_encoder(nec_encoder->copy_encoder); } free(nec_encoder); } return ret; } 自定义 NEC 协议的 RMT 编码器 static size_t rmt_encode_ir_nec(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) { rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base); rmt_encode_state_t session_state = RMT_ENCODING_RESET; rmt_encode_state_t state = RMT_ENCODING_RESET; size_t encoded_symbols = 0; ir_nec_scan_code_t *scan_code = (ir_nec_scan_code_t *)primary_data; rmt_encoder_handle_t copy_encoder = nec_encoder->copy_encoder; rmt_encoder_handle_t bytes_encoder = nec_encoder->bytes_encoder; switch (nec_encoder->state) { case 0: // send leading code encoded_symbols += copy_encoder->encode(copy_encoder, channel, nec_encoder->nec_leading_symbol, sizeof(rmt_symbol_word_t), session_state); if (session_state RMT_ENCODING_COMPLETE) { nec_encoder->state = 1; // we can only switch to next state when current encoder finished } if (session_state RMT_ENCODING_MEM_FULL) { state |= RMT_ENCODING_MEM_FULL; goto out; // yield if there's no free space to put other encoding artifacts } // fall-through case 1: // send DATA_front 35bit encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, scan_code->command, sizeof(uint32_t), session_state); if (session_state RMT_ENCODING_COMPLETE) { nec_encoder->state = 2; // we can only switch to next state when current encoder finished } if (session_state RMT_ENCODING_MEM_FULL) { state |= RMT_ENCODING_MEM_FULL; goto out; // yield if there's no free space to put other encoding artifacts } // fall-through case 2: // encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, scan_code->num, sizeof(ir_front_bit35), session_state); if (session_state RMT_ENCODING_COMPLETE) { nec_encoder->state = 3; // we can only switch to next state when current encoder finished } if (session_state RMT_ENCODING_MEM_FULL) { state |= RMT_ENCODING_MEM_FULL; goto out; // yield if there's no free space to put other encoding artifacts } // fall-through case 3: // send connect code encoded_symbols += copy_encoder->encode(copy_encoder, channel, nec_encoder->nec_ending_symbol, sizeof(rmt_symbol_word_t), session_state); if (session_state RMT_ENCODING_COMPLETE) { nec_encoder->state = 4; // we can only switch to next state when current encoder finished } if (session_state RMT_ENCODING_MEM_FULL) { state |= RMT_ENCODING_MEM_FULL; goto out; // yield if there's no free space to put other encoding artifacts } // fall-through case 4: //send data_rear 32bit encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, scan_code->command1, sizeof(uint32_t), session_state); if (session_state RMT_ENCODING_COMPLETE) { nec_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session state |= RMT_ENCODING_COMPLETE; } if (session_state RMT_ENCODING_MEM_FULL) { state |= RMT_ENCODING_MEM_FULL; goto out; // yield if there's no free space to put other encoding artifacts } } out: *ret_state = state; return encoded_symbols; } 按照上面代码实际上3bit输出了8bit的数据 |
|
相关推荐
1个回答
|
|
您好!根据您的需求,您需要将35bit的数据通过ESP32-C3的RMT模块进行编码。以下是一些建议和步骤,帮助您实现这个目标。
1. **准备工作**: - 确保您的开发环境已经正确设置,包括ESP-IDF、VSCode和ESP32-C3开发板。 2. **了解RMT模块**: - ESP32-C3的RMT模块可以发送和接收PWM信号。在这里,我们将使用RMT模块发送红外信号。 3. **自定义编码器**: - 由于ESP-IDF提供的例程只处理完整字节,您需要自定义一个编码器来处理35bit的数据。您可以创建一个新的C文件(例如:`custom_encoder.c`),并实现以下函数: ```c #include "esp_rmt.h" #include "esp_log.h" static const char *TAG = "CUSTOM_ENCODER"; esp_err_t custom_ir_encoder(const uint8_t *data, size_t data_size, rmt_item32_t *item, size_t *item_size) { size_t index = 0; for (size_t i = 0; i < data_size; i++) { for (int bit = 7; bit >= 0; bit--) { if (data[i] & (1 << bit)) { item[index++] = {{{1, 1, 0, 0, 0, 0, 0}, 0, 1}}; // 1 bit } else { item[index++] = {{{0, 1, 0, 0, 0, 0, 0}, 0, 0}}; // 0 bit } } } *item_size = index; return ESP_OK; } ``` 4. **发送数据**: - 在您的主程序中,创建一个RMT通道并初始化。然后,使用自定义编码器将35bit数据编码为RMT项目数组。 ```c #include "esp_rmt.h" #include "custom_encoder.h" #define RMT_CHANNEL RMT_CHANNEL_0 #define RMT_PIN 4 void app_main() { esp_rmt_config_t rmt_config = { .channel = RMT_CHANNEL, .gpio_num = RMT_PIN, .mem_block_num = 1, .clk_src = RMT_BASECLK_APB, .tx_config = { .loop_en = false, .carrier_freq_hz = 38000, .carrier_level = RMT_CARRIER_LEVEL_HIGH, .carrier_duty_percent = 33, .idle_level = RMT_IDLE_LEVEL_LOW, .idle_output_en = true, }, }; esp_err_t ret = esp_rmt_init(&rmt_config); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize RMT: %d", ret); return; } uint8_t data[5] = {0x12, 0x34, 0x56, 0x78, 0x9A}; // 35bit data rmt_item32_t items[35]; size_t item_size; ret = custom_ir_encoder(data, sizeof(data), items, &item_size); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to encode data: %d", ret); return; } ret = esp_rmt_write_items(RMT_CHANNEL, items, item_size, true); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to send data: %d", ret); return; } ESP_LOGI(TAG, "Data sent successfully"); } ``` 5. **编译和烧录**: - 使用ESP-IDF构建系统编译您的程序,并将其烧录到ESP32-C3开发板上。 通过以上步骤,您应该能够实现将35bit数据通过ESP32-C3的RMT模块进行编码和发送。希望这些信息对您有所帮助! |
|
|
|
只有小组成员才能发言,加入小组>>
191个成员聚集在这个小组
加入小组470 浏览 1 评论
1640 浏览 2 评论
641浏览 6评论
536浏览 5评论
有没有办法在不使用混杂模式的情况下实现Wifi驱动程序接收缓冲区访问中断呢?
515浏览 5评论
517浏览 4评论
507浏览 4评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-2-22 22:13 , Processed in 0.649395 second(s), Total 46, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191