Slave Receive
该示例通过使用 I2S 外设实现接收功能。
测试该示例时,可以使用另一颗 EVB 烧录发送程序作为发送端,与该 EVB 进行数据通信。
I2S 接收到数据后,触发中断,在中断函数内接收数据。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL8752H HDK |
RTL8752H EVB |
更多信息请参考 快速入门。
硬件连线
连接 P3_2(LRCK)至发送端的 LRCK 引脚,连接 P3_3(BCLK)至发送端的 BCLK 引脚,连接 P4_0(DATA_RX)至发送端的 DATA 引脚。
编译和下载
该示例的工程路径如下:
Project file: board\evb\io_sample\I2S\I2S_Slave_Recv\mdk
Project file: board\evb\io_sample\I2S\I2S_Slave_Recv\gcc
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译 APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下 reset 按键,开始运行。
测试验证
Slave 端收到数据后,在中断函数内,打印收到的数据。
length = xx
data[0] = xxx
data[1] = xxx
data[2] = xxx
...
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
sdk\board\evb\io_sample\I2S\I2S_Slave_Recv
源码路径:
sdk\src\sample\io_sample\I2S\I2S_Slave_Recv
该工程的工程文件代码结构如下:
└── Project: i2s_slave_recv
└── secure_only_app
└── include
├── app_define.h
└── rom_uuid.h
├── cmsis includes CMSIS header files and startup files
├── overlay_mgr.c
├── system_rtl876x.c
└── startup_rtl876x.s
├── lib includes all binary symbol files that user application is built on
├── rtl8752h_sdk.lib
├── gap_utils.lib
└── ROM.lib
├── peripheral includes all peripheral drivers and module code used by the application
├── rtl876x_rcc.c
├── rtl876x_pinmux.c
├── rtl876x_nvic.c
└── rtl876x_i2s.c
├── profile
└── app includes the ble_peripheral user application implementation
└── main.c
初始化
当 EVB 复位启动时,执行 main
函数,执行以下流程:
int main(void)
{
__enable_irq();
i2s_demo();
while (1)
{
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
}
}
在 i2s_demo
中,包含了 PAD/PINMUX 设置,I2S 外设的初始化流程。
void i2s_demo(void)
{
board_i2s_init();
driver_i2s_init();
}
board_i2s_init
为 PAD 与 PINMUX 设置,包含如下流程:
配置 PAD:设置引脚、PINMUX 模式、Power On、无内部上拉。
配置 PINMUX:分配引脚分别为 BCLK_SPORT0、LRC_SPORT0、ADCDAT_SPORT0 功能。
driver_i2s_init
为对 I2S 外设的初始化,包含如下流程:
使能 RCC 时钟。
设置 I2S 时钟源为 40MHz。
设置采样率为 16kHz。
设置 I2S 为从设备模式。
设置 I2S 为双声道模式。
设置数据宽度和数据格式。
关闭 I2S DMA 传输。
将 I2S 的数据通信选择为外部通道。
使能 I2S TX 模式。
配置 I2S 接收完毕中断。
备注
BCLK=I2S_ClockSource*(I2S_BClockNi/I2S_BClockMi)=1024K,LRCK=BCLK/64=16K
void driver_i2s_init(void) { RCC_PeriphClockCmd(APB_I2S, APB_I2S_CLOCK, ENABLE); I2S_InitTypeDef I2S_InitStruct; I2S_StructInit(&I2S_InitStruct); I2S_InitStruct.I2S_ClockSource = I2S_CLK_40M; /* BCLK = 40MHz*(ni/mi), LRCK = BCLK/64 */ I2S_InitStruct.I2S_BClockMi = 0x271; /* <!LRCK = 16K */ I2S_InitStruct.I2S_BClockNi = 0x10; /* <!BCLK = 1024K */ I2S_InitStruct.I2S_DeviceMode = I2S_DeviceMode_Slave; I2S_InitStruct.I2S_ChannelType = I2S_Channel_stereo; I2S_InitStruct.I2S_DataWidth = I2S_Width_16Bits; I2S_InitStruct.I2S_DataFormat = I2S_Mode; I2S_InitStruct.I2S_DMACmd = I2S_DMA_DISABLE; I2S_Init(I2S_NUM, &I2S_InitStruct); /* Change the I2S transmission into external codec .*/ I2S_CLK_SOURCE_REG_224 |= BIT(3); // DBG_DIRECT("I2S_CLK_SOURCE_REG_224 = 0x%X",I2S_CLK_SOURCE_REG_224); I2S_Cmd(I2S_NUM, I2S_MODE_RX, ENABLE); I2S_INTConfig(I2S_NUM, I2S_INT_RX_READY, ENABLE); NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = I2S0_RX_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority = 3; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); }
功能实现
当 I2S 接收到数据后,触发 I2S_INT_RX_READY
,进入中断处理函数 I2S0_RX_Handler
,读取收到的数据并打印。
void I2S0_RX_Handler(void)
{
/* Notes: DBG_DIRECT is only used in debug demo, do not use in app project.*/
DBG_DIRECT("I2S0_RX_Handler");
if (I2S_GetINTStatus(I2S_NUM, I2S_INT_RX_READY))
{
uint8_t len = I2S_GetRxFIFOLen(I2S_NUM);
DBG_DIRECT("length = %d", len);
for (uint8_t i = 0; i < len; i++)
{
DBG_DIRECT("data[%d] = 0x%X", i, I2S_ReceiveData(I2S_NUM));
}
I2S_ClearINTPendingBit(I2S_NUM, I2S_INT_RX_READY);
}
}