Использование I2S в качестве генератора частоты

vad7

Active member
Пробую заставить I2S работать как генератор частоты. Готовой библиотеки не нашел.
Собрал i2s.c на основе i2s_freertos.c (mp3_decoder) и ардуиновской core_esp8266_i2s.c.

Запускаю i2sInit(153600, 0, 0xAAAAAAAA) - получаю сброс/эксепшн после "os_printf("1.4\n");" на WRITE_PERI_REG(SLC_INT_ENA, SLC_RX_EOF_INT_ENA).
Если закомментить эту строку, то падает на следующим доступе к регистрам SLC.
Чего ему не хватает то?
 

Вложения

  • 11 KB Просмотры: 1
  • 493 байт Просмотры: 1

vad7

Active member
У меня даже это не работает: Настройка I2S, нужна помощь

Падение на первой строчке. Я правда, вебсвалку использую, может какой инициализации не хватает или наоборот, что "подкручено"...

Ps. Ага - ошибка в esp8266.h.
 
Последнее редактирование:

clinkme

Member
Вот простой код для IR-передатчика (частоты 36-40 кГц) на базе non-os SDK (любой версии).
В качестве выхода использует пин I2SO_WS (GPIO2).

Код:
void ICACHE_FLASH_ATTR ir_carrier_init(int khz) {
    uint32_t bck, clkm;
   
    //Enable a 160MHz clock to i2s subsystem
    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);
   
    //Reset I2S (?)
    CLEAR_PERI_REG_MASK(I2SCONF, I2S_I2S_RESET_MASK);
    SET_PERI_REG_MASK(I2SCONF, I2S_I2S_RESET_MASK);
    CLEAR_PERI_REG_MASK(I2SCONF, I2S_I2S_RESET_MASK);
   
    switch(khz) {
        /* 160000000/bck/clkm/2/(bits+16) */
        case 36: bck = 26; clkm = 5; break; //36199
        case 37: bck = 32; clkm = 4; break; //36764           
        case 40: bck = 59; clkm = 2; break; //39880
        case 38: //break through
        default: //bck = 62; clkm = 2;        //37950
                 bck = 41; clkm = 3;     //38259
    }
       
    //set i2s clk freq
    WRITE_PERI_REG(I2SCONF, READ_PERI_REG(I2SCONF) & 0xf0000fff|
                    ( (( bck & I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
                    (( clkm & I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|
                    ((1 & I2S_BITS_MOD)<<I2S_BITS_MOD_S )  )  );
}



/******************************************************************************
* FunctionName : ir_carrier_ctl
* Description  : control ir carrier
* Parameters   : NONE
* Returns      : NONE
* Drive: GPIO2|I2SO_WS
*******************************************************************************/
void  ir_carrier_ctl(int val) {

    if(val) {
        //Pin as I2SO_WS
        PIN_FUNC_SELECT(IR_GPIO_OUT_MUX, FUNC_I2SO_WS);   
        //Start i2s clock
        //CLEAR_PERI_REG_MASK(I2SCONF, I2S_I2S_TX_START);
        SET_PERI_REG_MASK(I2SCONF, I2S_I2S_TX_START);
    }
    else {
        //Pin as GPIO
        PIN_FUNC_SELECT(IR_GPIO_OUT_MUX, FUNC_GPIO2);
        //Set pin LOW
        GPIO_OUTPUT_SET(GPIO_ID_PIN(IR_GPIO_OUT_NUM), 0);         
        //Stop i2s clock
        CLEAR_PERI_REG_MASK(I2SCONF, I2S_I2S_TX_START);
    }       
}
 
  • Like
Реакции: vad7

vad7

Active member
Прошил обычную esp12e вместо Nodemcu, узнал какой эксепшен.
У меня почему-то падает на доступе к регистрам I2S:
Fatal exception (28):
epc1=0x40230bd7, epc2=0x00000000, epc3=0x00000000, excvaddr=0x02190000, depc=0x00000000

LoadProhibitedCause (28) - A load referenced a page mapped with an
attribute that does not permit loads [Region
Protection Option or MMU Option]

В этом месте:
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 ) ) );

/* I2SCONF:0x60000E08 */
#define I2SCONF i2s_[2]
 

vad7

Active member
На чистом SDK нормально работает.
Видать вебсвалка не всю периферию нормально инициализирует...
 

vad7

Active member
@clinkme, вот посмотрел на duty cycle - 53.85% на ноге I2SO_BCK. Что-то криво...
У вас также?
 

vad7

Active member
У I2SO_WS стабильность получше, в основном 50%, треть периодов +-0.03%.
 
Сверху Снизу