• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

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

clinkme

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


Код:
/******************************************************************************
 * FunctionName : gen_carrier_clk
 * Description  : gen 38khz carrier clk
 * Parameters  : NONE
 * Returns  :  NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
gen_carrier_clk()
{
   //ENABLE I2S CLK SOURCE
   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);
   //CONFIG AS I2S
#if (IR_NEC_TX_IO_MUX==PERIPHS_IO_MUX_GPIO2_U)
   //set i2s clk freq  GPIO2!!!
   WRITE_PERI_REG(I2SCONF,  READ_PERI_REG(I2SCONF) & 0xf0000fff|
    ( (( 62&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
    ((2&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|
    ((1&I2S_BITS_MOD  )  <<  I2S_BITS_MOD_S )  )  );

   WRITE_PERI_REG(IR_NEC_TX_IO_MUX, (READ_PERI_REG(IR_NEC_TX_IO_MUX)&0xfffffe0f)| (0x1<<4) );
   WRITE_PERI_REG(0x60000e08, READ_PERI_REG(0x60000e08) & 0xfffffdff | (0x1<<8) ); //i2s tx  start
#endif

#if (IR_NEC_TX_IO_MUX==PERIPHS_IO_MUX_MTMS_U)
   //set i2s clk freq
   WRITE_PERI_REG(I2SCONF,  READ_PERI_REG(I2SCONF) & 0xf0000fff|
    ( (( 62&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|  
    ((2&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|   
    ((1&I2S_BITS_MOD  )  <<  I2S_BITS_MOD_S )  )  );

   WRITE_PERI_REG(IR_NEC_TX_IO_MUX, (READ_PERI_REG(IR_NEC_TX_IO_MUX)&0xfffffe0f)| (0x1<<4) );
   WRITE_PERI_REG(0x60000e08, READ_PERI_REG(0x60000e08) & 0xfffffdff | (0x2<<8) ) ;//i2s rx  start
#endif
#if (IR_NEC_TX_IO_MUX==PERIPHS_IO_MUX_MTCK_U)
   //set i2s clk freq GPIO13!!!
   WRITE_PERI_REG(I2SCONF,  READ_PERI_REG(I2SCONF) & 0xf0000fff|
    ( (( 63&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
    ((63&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|
    ((1&I2S_BITS_MOD  )  <<  I2S_BITS_MOD_S )  )  );

   WRITE_PERI_REG(IR_NEC_TX_IO_MUX, (READ_PERI_REG(IR_NEC_TX_IO_MUX)&0xfffffe0f)| (0x1<<4) );
   WRITE_PERI_REG(0x60000e08, READ_PERI_REG(0x60000e08) & 0xfffffdff | (0x2<<8) ) ;//i2s rx  start
#endif
#if (IR_NEC_TX_IO_MUX==PERIPHS_IO_MUX_MTDO_U)
   //set i2s clk freq
   WRITE_PERI_REG(I2SCONF,  READ_PERI_REG(I2SCONF) & 0xf0000fff|
    ( (( 63&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
    ((63&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|
    ((1&I2S_BITS_MOD  )  <<  I2S_BITS_MOD_S )));

   WRITE_PERI_REG(IR_NEC_TX_IO_MUX, (READ_PERI_REG(IR_NEC_TX_IO_MUX)&0xfffffe0f)| (0x1<<4) );
   WRITE_PERI_REG(0x60000e08, READ_PERI_REG(0x60000e08) & 0xfffffdff | (0x1<<8) ); //i2s tx  start
#endif
}
 

pvvx

Активный участник сообщества
Там завязка с 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
 
Последнее редактирование:

clinkme

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

pvvx

Активный участник сообщества
Не совcем так, но примерно для данного случая "(1&I2S_BITS_MOD)" :)
Перепишите пример для заливки в IRAM и заливайте в память из компилятора без прошивки flash и всяких SDK хоть тысчи раз с разными вариантами.
Подключите логер или многоканальный осел и наблюдайте. Я так и сделал.
Примерный код инициализации PLL и других мелочей для старта теста из IRAM
Код:
#include "bios.h"
#include "osapi.h"
#include "os_type.h"
#include "hw/esp8266.h"
#include "hw/eagle_soc.h"
#include "hw/uart_register.h"
//=============================================================================
void tests(void)
{
    ets_set_idle_cb(NULL, NULL);
    ets_intr_unlock();
  // ваш код
}
//=============================================================================
// Стандартный вывод putc (UART1)
//-----------------------------------------------------------------------------
void uart1_write_char(char c)
{
    if (c != '\r') {
        do {
            MEMW();
            if(((UART1_STATUS >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT) <= 125) break;
        } while(1);
        if (c != '\n') UART1_FIFO = c;
        else {
           UART1_FIFO = '\r';
           UART1_FIFO = '\n';
        }
    }
}
void uart1_init(uint32 baud, uint32 parity)
{
    GPIO2_MUX = (1<<GPIO_MUX_FUN_BIT1);
    UART1_CLKDIV = ((ets_get_cpu_frequency()  * 1000000) >> (CLK_PRE_PORT & 1)) / baud;
    UART1_CONF0 = 0x1C | (parity & 3) | ((parity & UART_PARITY_EN)? 0 : 2 << UART_STOP_BIT_NUM_S);
    os_install_putc1((void *)uart1_write_char); // install uart1 putc callback
}

extern uint8 _bss_start;
extern uint8 _bss_end;

void call_user_start(void)
{
    IO_RTC_4 = 0; // отключить WiFi
    GPIO0_MUX = 0; // отключить вывод Q_CLK
    // Очистка сегмента bss //    mem_clr_bss();
    uint8 * ptr = &_bss_start;
    while(ptr < &_bss_end) *ptr++ = 0;
    // CLK CPU 160 MHz (настройка pll на 80MHz при кварце 26MHz)
    rom_i2c_writeReg(103, 4, 1, 136);
    rom_i2c_writeReg(103, 4, 2, 145);
    CLK_PRE_PORT |= 1;
    ets_update_cpu_frequency(80 * 2);
    ets_timer_init();
    uart1_init(230400, 0);
    ets_printf("\nStart.\n");
    IO_RTC_4 |= 0x80000000; // переключить источник тактирования i2s и т.д. к PLL
    ets_delay_us(100000);
    ets_set_idle_cb(tests, NULL);
    ets_run();
}
Хидеры из https://github.com/pvvx/esp8266web/tree/master/include
 
Последнее редактирование:
Сверху Снизу