I2S Master & Slave
I2S Master & Slave示例用于验证I2S的数据传输功能,通过宏MASTER_BOARD确定为Master或Slave。
该示例需要两块开发板,一块作为Master,一块作为Slave。
I2S Master & Slave示例的源代码和工程文件位于SDK_Folder\projects\peripheral\i2s\i2s_master_salve\,其中工程文件在文件夹Keil_5下。
代码理解
示例工程流程图如图 20所示:
- 配置I2S模块。
I2S详细配置参数请参考I2S Master Audio。
#ifdef MASTER_BOARD g_i2s_handle.p_instance = I2S_M; g_i2s_handle.init.audio_freq = 48000; #else g_i2s_handle.p_instance = I2S_S; #endif /* MASTER_BOARD */ g_i2s_handle.init.data_size = I2S_DATASIZE_32BIT; g_i2s_handle.init.clock_source = I2S_CLOCK_SRC_96M; hal_i2s_init(&g_i2s_handle); - Master分别使用DMA、中断、轮询方式和Slave进行数据交互。
- 因I2S目前采用用户控制时钟开关状态,故为了防止接收或者发送不必要的数据,需调用i2s_flush_rx_fifo()或者i2s_flush_tx_fifo()接口,清除RX/TX FIFO中的数据。
- Master在操作完成后调用__HAL_I2S_DISABLE_CLOCK()关闭时钟或者重新初始化I2S,防止时钟使能设备一直处于收发阶段。
- 采用非阻塞方式的接口,需在后续步骤中用while判断是否收发完成。代码如下:
i2s_flush_rx_fifo(&g_i2s_handle); hal_i2s_transmit_receive_dma(&g_i2s_handle, wdata, rdata, sizeof(wdata) >> 2); while (!tx_rx_flag); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); sys_delay_ms(1); hal_i2s_deinit(&g_i2s_handle); hal_i2s_init(&g_i2s_handle); hal_i2s_transmit_receive_it(&g_i2s_handle, wdata, rdata, sizeof(wdata) >> 2); while (!tx_rx_flag); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); sys_delay_ms(1); hal_i2s_deinit(&g_i2s_handle); hal_i2s_init(&g_i2s_handle); i2s_flush_rx_fifo(&g_i2s_handle); hal_i2s_transmit_receive(&g_i2s_handle, wdata, rdata, sizeof(wdata) >> 2, 2000); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); sys_delay_ms(1); hal_i2s_deinit(&g_i2s_handle); hal_i2s_init(&g_i2s_handle); i2s_flush_rx_fifo(&g_i2s_handle); hal_i2s_transmit_it(&g_i2s_handle, wdata, sizeof(wdata) >> 2); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); sys_delay_ms(1); hal_i2s_deinit(&g_i2s_handle); hal_i2s_init(&g_i2s_handle); sys_delay_ms(10); i2s_flush_rx_fifo(&g_i2s_handle); hal_i2s_receive_it(&g_i2s_handle, rdata, sizeof(rdata) >> 2); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); sys_delay_ms(1); hal_i2s_deinit(&g_i2s_handle); hal_i2s_init(&g_i2s_handle);
- Slave分别使用DMA,中断,轮询方式和Master进行数据交互。
为了防止接收或者发送不必要的数据,需调用i2s_flush_rx_fifo()或者i2s_flush_tx_fifo()接口,清除RX/TX FIFO中的数据。代码如下:
i2s_flush_rx_fifo(&g_i2s_handle); hal_i2s_transmit_receive_dma(&g_i2s_handle, wdata, rdata, sizeof(wdata) >> 2); while (!tx_rx_flag); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); hal_i2s_deinit(&g_i2s_handle); hal_i2s_init(&g_i2s_handle); i2s_flush_rx_fifo(&g_i2s_handle); hal_i2s_transmit_receive_it(&g_i2s_handle, wdata, rdata, sizeof(wdata) >> 2); while (!tx_rx_flag); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); hal_i2s_deinit(&g_i2s_handle); hal_i2s_init(&g_i2s_handle); i2s_flush_rx_fifo(&g_i2s_handle); hal_i2s_transmit_receive(&g_i2s_handle, wdata, rdata, sizeof(wdata) >> 2, 2000); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); hal_i2s_deinit(&g_i2s_handle); hal_i2s_init(&g_i2s_handle); i2s_flush_rx_fifo(&g_i2s_handle); hal_i2s_receive_it(&g_i2s_handle, rdata, sizeof(rdata) >> 2); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); hal_i2s_deinit(&g_i2s_handle); hal_i2s_init(&g_i2s_handle); i2s_flush_rx_fifo(&g_i2s_handle); hal_i2s_transmit_it(&g_i2s_handle, wdata, sizeof(wdata) >> 2); while (hal_i2s_get_state(&g_i2s_handle) != HAL_I2S_STATE_READY); sys_delay_ms(2); hal_i2s_deinit(&g_i2s_handle);
测试验证
- 在工程配置中定义宏MASTER_BOARD,编译并下载至主设备开发板;工程配置中取消宏定义MASTER_BOARD,编译并下载至从设备开发板。
- 连接主从设备开发板的对应IO引脚。
- 将主从设备开发板的串口分别连接至PC端,打开并配置GRUart。
- 在GRUart的Receive Data窗口中将会显示I2S的数据传输结果。