完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我正在尝试使用 I2S 直接来自 ADC 的功能,以立体声方式运行。我正在使用在 Ubuntu 18.04 上开发的 Wemos Lolin D32,它使用 ESP32-WROOM-32。
我的 IDF 版本是 v3.3-beta2,但它需要对 IDF 进行一些修改才能公开必要的功能(我也通过直接操作寄存器尝试过);我将在下面详细说明。 我的问题是,无论我做什么,我都会看到 ADC 数据加倍或跳过通道。我有从 I2S 读取的 ADC 数据中提取通道的代码,如下所示: 代码: static void show_some_data(uint16_t * data) { const unsigned rows = 8; for (unsigned row = 0; row < rows; row++) { ESP_LOGI( TAG, "CH: %d %d %d %d %d %d %d %d", (data[8*row + 0] & 0xF000) >> 12, (data[8*row + 1] & 0xF000) >> 12, (data[8*row + 2] & 0xF000) >> 12, (data[8*row + 3] & 0xF000) >> 12, (data[8*row + 4] & 0xF000) >> 12, (data[8*row + 5] & 0xF000) >> 12, (data[8*row + 6] & 0xF000) >> 12, (data[8*row + 7] & 0xF000) >> 12 ); } } 我在串行日志中看到的结果是: 代码: I (324) I2S: PLL_D2: Req RATE: 24000, real rate: 1515.000, BITS: 16, CLKM: 55, BCK: 60, MCLK: 55.556, SCLK: 48480.000000, diva: 64, divb: 35 I (334) i2s-test: CH: 6 6 6 6 6 6 0 0 I (334) i2s-test: CH: 0 0 0 0 0 0 0 0 I (344) i2s-test: CH: 0 0 0 0 0 0 0 0 I (344) i2s-test: CH: 0 0 0 0 0 0 0 0 I (354) i2s-test: CH: 0 0 0 0 0 0 0 0 I (354) i2s-test: CH: 0 0 0 0 0 0 0 0 I (364) i2s-test: CH: 0 0 0 0 0 0 0 0 I (364) i2s-test: CH: 0 0 0 0 0 0 0 0 I (364) i2s-test: CH: 5 5 6 6 5 5 6 6 I (374) i2s-test: CH: 5 5 6 6 5 5 6 6 I (374) i2s-test: CH: 5 5 6 6 5 5 6 6 I (384) i2s-test: CH: 5 5 6 6 5 5 6 6 I (384) i2s-test: CH: 5 5 6 6 5 5 6 6 I (394) i2s-test: CH: 5 5 6 6 5 5 6 6 I (394) i2s-test: CH: 5 5 6 6 5 5 6 6 I (394) i2s-test: CH: 5 5 6 6 5 5 6 6 I (404) i2s-test: CH: 6 6 5 5 6 6 5 5 配置相当简单: 代码: i2s_config_t i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN, .sample_rate = SAMPLE_RATE, // 24kHz .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .communication_format = I2S_COMM_FORMAT_I2S, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 2, .dma_buf_len = NUM_SAMPLES, // 64 .use_apll = 0, .fixed_mclk = 0 }; i2s_driver_install(i2s_num, &i2s_config, 4, i2s_queue); i2s_set_clk(i2s_num, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO); i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_6); adc_set_i2s_data_pattern(ADC_UNIT_1, 0, ADC_CHANNEL_6, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11); adc_set_i2s_data_pattern(ADC_UNIT_1, 1, ADC_CHANNEL_5, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11); adc_set_i2s_data_len(ADC_UNIT_1, 2); 正如我提到的,我必须对 IDF 进行一些更改才能使用 ADC 模式表:公开函数 adc_set_i2s_data_len() 和 adc_set_i2s_data_pattern() 并注释掉 i2s_adc_enable() 中的 _i2s_adc_mode_recover() 调用。生成的代码在 我的 fork 中可用。 它可以通过检查并执行“idf.py build”来构建。 我完全无法弄清楚出了什么问题。我检查了我的代码和 IDF 库以确保正确设置了寄存器。我已经从头到尾阅读了技术参考手册。我已经尝试过使用和不使用队列,使用和不使用 DMA 清除。我已经使用示波器来验证 WS 信号确实以 24kHz 的频率运行(尽管这不应该影响通道顺序)。 即使只是让其他人尝试我的示例项目并告诉我他们是否在他们的硬件上看到相同的东西,这对我来说也是一个巨大的帮助。但是,如果您看到我在这里犯的一个错误,或者对更多调试有任何想法,请告诉我。 |
|
相关推荐
1个回答
|
|
你可以试试...
代码: .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_spi_flash.h" #include "esp_err.h" #include "esp_log.h" #include "esp_partition.h" #include "driver/i2s.h" #include "driver/adc.h" #include "driver/gpio.h" #include "esp_adc_cal.h" #include "esp_rom_sys.h" #include static const char* TAG = "adc"; //i2s number #define EXAMPLE_I2S_NUM (0) //i2s sample rate #define EXAMPLE_I2S_SAMPLE_RATE (17000) //i2s data bits #define EXAMPLE_I2S_SAMPLE_BITS (16) //I2S read buffer length #define EXAMPLE_I2S_READ_LEN (1700 * 4) //I2S built-in ADC unit #define I2S_ADC_UNIT ADC_UNIT_1 void example_i2s_init(void) { i2s_config_t i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN, // I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN .sample_rate = EXAMPLE_I2S_SAMPLE_RATE * 2, .bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS, .communication_format = I2S_COMM_FORMAT_STAND_MSB, .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, .intr_alloc_flags = 0, .dma_buf_count = 4, .dma_buf_len = 1024, .use_apll = true, }; //install and start i2s driver i2s_driver_install(EXAMPLE_I2S_NUM, &i2s_config, 0, NULL); ESP_ERROR_CHECK(i2s_set_adc_mode(I2S_ADC_UNIT, ADC1_CHANNEL_6)); ESP_ERROR_CHECK(i2s_set_adc_mode(I2S_ADC_UNIT, ADC1_CHANNEL_7)); SYSCON.saradc_ctrl2.max_meas_num = 255; SYSCON.saradc_ctrl2.meas_num_limit = 1; } void example_i2s_adc_dac(void) { size_t bytes_read; //, bytes_written; //I2S_EVENT_RX_Q_OVF char* i2s_read_buff = (char*) calloc(EXAMPLE_I2S_READ_LEN, sizeof(char)); //i2s_event_t evt; while (1) { vTaskDelay(100); ESP_LOGI(TAG, "Starting"); i2s_adc_enable(EXAMPLE_I2S_NUM); // Overwrite oattern register to get 2 channels scanning SYSCON.saradc_sar1_patt_tab[0] = 0x07F6F0F0F; SYSCON.saradc_ctrl.sar1_patt_len = 1; //rstb_wait: 8 sample_cycle: 2 standby_wait: 100 start_wait: 16 //ESP_LOGI(TAG, " rstb_wait: %u sample_cycle: %u standby_wait: %u start_wait: %u", SYSCON.saradc_fsm.rstb_wait, SYSCON.saradc_fsm.sample_cycle, SYSCON.saradc_fsm.standby_wait, SYSCON.saradc_fsm.start_wait); //read data from I2S bus, in this case, from ADC. i2s_read(EXAMPLE_I2S_NUM, (void*) i2s_read_buff, EXAMPLE_I2S_READ_LEN, &bytes_read, portMAX_DELAY); ESP_LOGI(TAG, "Stopping"); i2s_adc_disable(EXAMPLE_I2S_NUM); vTaskDelay(100); for (size_t i = 0; i < EXAMPLE_I2S_READ_LEN; i += 2) { ESP_LOGI(TAG, " %1x %u", ((i2s_read_buff[i + 1] & 0xf0) >> 4), (i2s_read_buff | ((i2s_read_buff[i + 1] & 0x0f) << 8))); } } } esp_err_t app_main(void) { example_i2s_init(); esp_log_level_set("I2S", ESP_LOG_INFO); example_i2s_adc_dac(); return ESP_OK; } |
|
|
|
只有小组成员才能发言,加入小组>>
1140 浏览 1 评论
577浏览 6评论
478浏览 5评论
有没有办法在不使用混杂模式的情况下实现Wifi驱动程序接收缓冲区访问中断呢?
462浏览 5评论
463浏览 4评论
438浏览 4评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 21:25 , Processed in 0.816000 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号