I2S Master Receive

This sample code demonstrates I2S receive data from I2S slave in interrupt mode. In this sample, the I2S is configured as the master, and the chip receives data sent by the I2S slave.

Requirements

For hardware requirements, please refer to the Requirements.

Wiring

Connect P0_0 to the LRCK of the I2S slave, connect P0_1 to the BCLK of the I2S slave, and connect P0_3 to the SDO of the I2S slave.

The hardware connection of I2S sample code is shown in the figure below.

../../../_images/I2S_Master_Receive_Sample_Code_Hardware_Connection_Diagram.png

I2S Sample Code Hardware Connection Diagram

Configurations

  1. The following macros can be configured to modify pin definitions.

    • #define I2S_LRCK_PIN P0_0

    • #define I2S_BCLK_PIN P0_1

    • #define I2S_SDI_PIN P0_3

  2. The entry function is as follows, call this function in main() to run this sample code. For more details, please refer to the Initialization.

    i2s_master_recv_demo();
    

Building and Downloading

For building and downloading, please refer to the Building and Downloading.

Experimental Verification

  1. Press the Reset button on the EVB.

  2. The I2S master device continuously receives data from the I2S slave.

  3. Once the I2S master detects that enough data has been received, I2S RX interrupt will be triggered, and prints the data in Debug Analyzer.

Code Overview

Source Code Directory

  • For project directory, please refer to Source Code Directory.

  • Source code directory: sdk\src\sample\io_demo\i2s\master_recv\i2s_master_recv_demo.c.

Initialization

The initialization flow for peripherals can refer to Initialization Flow.

I2S initialization flow is shown in the following figure.

../../../_images/I2S_Master_Init_Flow.png

I2S Master Init Flow Chart

Note

As mentioned in PINMUX and PAD function descriptions, I2S PAD should be configured as software mode and pulled down when I2S is disabled to prevent PAD from floating during low power mode.

  1. Call Pad_Config() and Pinmux_Config() to initialize the pin.

    static void board_i2s_init(void)
    {
        /* set PAD_SW_MODE & PAD_PULL_DOWN when I2S disable to prevent PAD floating */
        Pad_Config(I2S_LRCK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
        Pad_Config(I2S_BCLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
        Pad_Config(I2S_SDI_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
    
        Pinmux_Config(I2S_BCLK_PIN, I2S_BCLK_PINMUX);
        Pinmux_Config(I2S_LRCK_PIN, I2S_LRCK_PINMUX);
        Pinmux_Config(I2S_SDI_PIN, I2S_SDI_PINMUX);
    }
    
  2. Initialize the I2S peripheral:

    1. Define the I2S_InitTypeDef type I2S_InitStruct, and call I2S_StructInit() to pre-fill I2S_InitStruct with default values.

    2. Modify the I2S_InitStruct parameters as needed. The I2S initialization parameter configuration is shown in the table below.

    3. Call I2S_Init() to initialize the I2S peripheral.

    I2S Initialization Parameters

    I2S Hardware Parameters

    Setting in the I2S_InitStruct

    I2S

    Device Role

    I2S_InitTypeDef::I2S_DeviceMode

    I2S_DeviceMode_Master

    Bit Clock Divider (Mi)

    I2S_InitTypeDef::I2S_BClockMi

    0x271

    Bit Clock Divider (Ni)

    I2S_InitTypeDef::I2S_BClockNi

    0x30

    LR Clock Divider

    I2S_InitTypeDef::I2S_BClockDiv

    0x3F

    Data Width

    I2S_InitTypeDef::I2S_RxDataWidth

    I2S_Data_Width_24Bits

    Channel Width

    I2S_InitTypeDef::I2S_RxChannelWidth

    I2S_Channel_Width_32Bits

    Channel Type

    I2S_InitTypeDef::I2S_RxChannelType

    I2S_Channel_Stereo

    Data Format

    I2S_InitTypeDef::I2S_RxDataFormat

    I2S_Mode

  3. Call I2S_INTConfig() to enable I2S RX interrupt I2S_MCU_INT_RX_READY.

  4. Call NVIC_Init() to enable NVIC of I2S.

  5. Call I2S_Cmd() to enable I2S.

Functional Implementation

Master Receive Data

The I2S master register I2S_RX_Handler, and call I2S_ReceiveData() and read data from I2S slave repeatedly in handler.

static void I2S_RX_Handler(void)
{
    uint32_t data;

    if (I2S_GetINTStatus(I2S_NUM, I2S_MCU_INT_RX_READY))
    {
        uint8_t len = I2S_GetRxFIFOLen(I2S_NUM);

        for (uint8_t i = 0; i < len; i++)
        {
            data = I2S_ReceiveData(I2S_NUM);
            IO_PRINT_TRACE("I2S_RX_Handler: i %d, data 0x%x", i, data);
            /* do something */
        }

        I2S_ClearINTPendingBit(I2S_NUM, I2S_CLEAR_INT_RX_READY);
    }
}

Interrupt Handle

When the I2S master detects that enough data has been received, I2S RX interrupt will be triggered and enters the I2S RX interrupt handler:

  1. Call I2S_GetINTStatus() to check I2S_MCU_INT_RX_READY interrupt status.

  2. Call I2S_ClearINTPendingBit() to clear I2S_CLEAR_INT_RX_READY interrupt.