Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

Настройка I2S, нужна помощь

Тема в разделе "Общие вопросы по esp8266", создана пользователем clinkme, 20 ноя 2015.

  1. clinkme

    clinkme Новичок

    Сообщения:
    32
    Симпатии:
    3
    Планирую использовать блок I2S для генерации несущей для IR-передатчика, как в примере espressif.
    Они предлагают использовать GPIO2 (I2SO_WS), GPIO14 (I2SI_WS), GPIO13(I2SI_BCK), при этом расчет в примере делается для 38 кГц.
    Перебирал делители и так и эдак, но так и не понял идею расчета (например, что надо изменить, чтобы получить несущую 36 или 40 кГц вместо 38?).


    Код (Text):
    1.  
    2. /******************************************************************************
    3.  * FunctionName : gen_carrier_clk
    4.  * Description  : gen 38khz carrier clk
    5.  * Parameters  : NONE
    6.  * Returns  :  NONE
    7. *******************************************************************************/
    8. void ICACHE_FLASH_ATTR
    9. gen_carrier_clk()
    10. {
    11.    //ENABLE I2S CLK SOURCE
    12.    rom_i2c_writeReg_Mask(i2c_bbpll, i2c_bbpll_hostid, i2c_bbpll_en_audio_clock_out, i2c_bbpll_en_audio_clock_out_msb, i2c_bbpll_en_audio_clock_out_lsb, 1);
    13.    //CONFIG AS I2S
    14. #if (IR_NEC_TX_IO_MUX==PERIPHS_IO_MUX_GPIO2_U)
    15.    //set i2s clk freq  GPIO2!!!
    16.    WRITE_PERI_REG(I2SCONF,  READ_PERI_REG(I2SCONF) & 0xf0000fff|
    17.     ( (( 62&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
    18.     ((2&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|
    19.     ((1&I2S_BITS_MOD  )  <<  I2S_BITS_MOD_S )  )  );
    20.  
    21.    WRITE_PERI_REG(IR_NEC_TX_IO_MUX, (READ_PERI_REG(IR_NEC_TX_IO_MUX)&0xfffffe0f)| (0x1<<4) );
    22.    WRITE_PERI_REG(0x60000e08, READ_PERI_REG(0x60000e08) & 0xfffffdff | (0x1<<8) ); //i2s tx  start
    23. #endif
    24.  
    25. #if (IR_NEC_TX_IO_MUX==PERIPHS_IO_MUX_MTMS_U)
    26.    //set i2s clk freq
    27.    WRITE_PERI_REG(I2SCONF,  READ_PERI_REG(I2SCONF) & 0xf0000fff|
    28.     ( (( 62&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|  
    29.     ((2&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|  
    30.     ((1&I2S_BITS_MOD  )  <<  I2S_BITS_MOD_S )  )  );
    31.  
    32.    WRITE_PERI_REG(IR_NEC_TX_IO_MUX, (READ_PERI_REG(IR_NEC_TX_IO_MUX)&0xfffffe0f)| (0x1<<4) );
    33.    WRITE_PERI_REG(0x60000e08, READ_PERI_REG(0x60000e08) & 0xfffffdff | (0x2<<8) ) ;//i2s rx  start
    34. #endif
    35. #if (IR_NEC_TX_IO_MUX==PERIPHS_IO_MUX_MTCK_U)
    36.    //set i2s clk freq GPIO13!!!
    37.    WRITE_PERI_REG(I2SCONF,  READ_PERI_REG(I2SCONF) & 0xf0000fff|
    38.     ( (( 63&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
    39.     ((63&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|
    40.     ((1&I2S_BITS_MOD  )  <<  I2S_BITS_MOD_S )  )  );
    41.  
    42.    WRITE_PERI_REG(IR_NEC_TX_IO_MUX, (READ_PERI_REG(IR_NEC_TX_IO_MUX)&0xfffffe0f)| (0x1<<4) );
    43.    WRITE_PERI_REG(0x60000e08, READ_PERI_REG(0x60000e08) & 0xfffffdff | (0x2<<8) ) ;//i2s rx  start
    44. #endif
    45. #if (IR_NEC_TX_IO_MUX==PERIPHS_IO_MUX_MTDO_U)
    46.    //set i2s clk freq
    47.    WRITE_PERI_REG(I2SCONF,  READ_PERI_REG(I2SCONF) & 0xf0000fff|
    48.     ( (( 63&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
    49.     ((63&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|
    50.     ((1&I2S_BITS_MOD  )  <<  I2S_BITS_MOD_S )));
    51.  
    52.    WRITE_PERI_REG(IR_NEC_TX_IO_MUX, (READ_PERI_REG(IR_NEC_TX_IO_MUX)&0xfffffe0f)| (0x1<<4) );
    53.    WRITE_PERI_REG(0x60000e08, READ_PERI_REG(0x60000e08) & 0xfffffdff | (0x1<<8) ); //i2s tx  start
    54. #endif
    55. }
    56.  
    57.  
     
  2. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    10.240
    Симпатии:
    1.349
    Там завязка с I2S_BITS_MOD.
    Для вашего варианта (куска кода) выходит, к примеру I2S_BCK_DIV_NUM =16, I2S_CLKM_DIV_NUM=8 -> I2SO_BCK (GPOI15) = 1.25MHz, I2SO_WS (GPIO2) = 1250/17/2 = 36.76 kHz
    I2S_BCK_DIV_NUM = 43, I2S_CLKM_DIV_NUM= 3 -> I2SO_BCK (GPOI15) = 1.241MHz, I2SO_WS (GPIO2) = 36.48 kHz

    http://bbs.espressif.com/viewtopic.php?t=958
     
    Последнее редактирование: 21 ноя 2015
    clinkme нравится это.
  3. clinkme

    clinkme Новичок

    Сообщения:
    32
    Симпатии:
    3
    Т.е. окончательная формула для частоты
    будет выглядеть так (для сигнала _WS):
    Код (Text):
    1. freq = (160000000 / I2S_BCK_DIV_NUM / I2S_CLKM_DIV_NUM) / 2*(16+I2S_BITS_MOD)
    И минимальная частота получается около 800 Hz. Можно еще куда применить.
     
  4. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    10.240
    Симпатии:
    1.349
    Не совcем так, но примерно для данного случая "(1&I2S_BITS_MOD)" :)
    Перепишите пример для заливки в IRAM и заливайте в память из компилятора без прошивки flash и всяких SDK хоть тысчи раз с разными вариантами.
    Подключите логер или многоканальный осел и наблюдайте. Я так и сделал.
    Примерный код инициализации PLL и других мелочей для старта теста из IRAM
    Код (C):
    1.  
    2. #include "bios.h"
    3. #include "osapi.h"
    4. #include "os_type.h"
    5. #include "hw/esp8266.h"
    6. #include "hw/eagle_soc.h"
    7. #include "hw/uart_register.h"
    8. //=============================================================================
    9. void tests(void)
    10. {
    11.     ets_set_idle_cb(NULL, NULL);
    12.     ets_intr_unlock();
    13.   // ваш код
    14. }
    15. //=============================================================================
    16. // Стандартный вывод putc (UART1)
    17. //-----------------------------------------------------------------------------
    18. void uart1_write_char(char c)
    19. {
    20.     if (c != '\r') {
    21.         do {
    22.             MEMW();
    23.             if(((UART1_STATUS >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT) <= 125) break;
    24.         } while(1);
    25.         if (c != '\n') UART1_FIFO = c;
    26.         else {
    27.            UART1_FIFO = '\r';
    28.            UART1_FIFO = '\n';
    29.         }
    30.     }
    31. }
    32. void uart1_init(uint32 baud, uint32 parity)
    33. {
    34.     GPIO2_MUX = (1<<GPIO_MUX_FUN_BIT1);
    35.     UART1_CLKDIV = ((ets_get_cpu_frequency()  * 1000000) >> (CLK_PRE_PORT & 1)) / baud;
    36.     UART1_CONF0 = 0x1C | (parity & 3) | ((parity & UART_PARITY_EN)? 0 : 2 << UART_STOP_BIT_NUM_S);
    37.     os_install_putc1((void *)uart1_write_char); // install uart1 putc callback
    38. }
    39.  
    40. extern uint8 _bss_start;
    41. extern uint8 _bss_end;
    42.  
    43. void call_user_start(void)
    44. {
    45.     IO_RTC_4 = 0; // отключить WiFi
    46.     GPIO0_MUX = 0; // отключить вывод Q_CLK
    47.     // Очистка сегмента bss //    mem_clr_bss();
    48.     uint8 * ptr = &_bss_start;
    49.     while(ptr < &_bss_end) *ptr++ = 0;
    50.     // CLK CPU 160 MHz (настройка pll на 80MHz при кварце 26MHz)
    51.     rom_i2c_writeReg(103, 4, 1, 136);
    52.     rom_i2c_writeReg(103, 4, 2, 145);
    53.     CLK_PRE_PORT |= 1;
    54.     ets_update_cpu_frequency(80 * 2);
    55.     ets_timer_init();
    56.     uart1_init(230400, 0);
    57.     ets_printf("\nStart.\n");
    58.     IO_RTC_4 |= 0x80000000; // переключить источник тактирования i2s и т.д. к PLL
    59.     ets_delay_us(100000);
    60.     ets_set_idle_cb(tests, NULL);
    61.     ets_run();
    62. }
    63.  
    Хидеры из https://github.com/pvvx/esp8266web/tree/master/include
     
    Последнее редактирование: 21 ноя 2015
    aloika нравится это.

Поделиться этой страницей