SYD8821 I2S模块接收功能使用说明

SYD8821是具有全球领先低功耗(RX 2.4mA @-94.5dBm灵敏度,TX 4.3mA @0dBm输出功率)的蓝牙低功耗SOC芯片,在极低电流下实现了优异的射频性能,搭配176kB SRAM,512kB flash,非常适合中高阶可穿戴、智能家居、物联网等低功耗应用。具体可咨询:http://www.syd-tek.com/

SYD8821 I2S_RX模块接收功能使用说明

本博客介绍I2S模块的接收功能,关于I2S的发送功能请看:https://blog.csdn.net/chengdong1314/article/details/81210103

这里I2S从机为MSM261S4030H0,其管脚图如下:

这里写图片描述
这里连接图如下:
1、2和5脚接到电源地
8和4脚接到电源的供电端3.3V
SCK连接到SYD8821的M_I2S_SCLK,这里是GPIO8
SD连接到SYD8821的M_I2S_SDI,这里是GPIO11
WS连接到SYD8821的LRCLK,这里是GPIO10
这里和SYD8821连接实物图如下:
这里写图片描述这里写图片描述这里写图片描述
打开工程可看到源代码如下:
/*
UART例程main.c

作者:北京盛源达科技有限公司
日期:2018/3/19
*/

include “ARMCM0.h”

include “gpio.h”

include “pad_mux_ctrl.h”

include “delay.h”

include “led_key.h”

include “uart.h”

include “queue.h”

include “debug.h”

include “i2s.h”

include

include “DebugLog.h”

include “main.h”

define I2S_CTRL ((I2S_CTRL_TYPE *) I2S_CTRL_BASE)

define RAM_BUFF_LEN 16*1024

static __align(4) uint8_t buf_Ram[RAM_BUFF_LEN]={0};
uint8_t buf_const[READ_BUFF_LEN]={0};
int DMA_size = 0;

define DEBUG_I2S_DMA

ifdef DEBUG_I2S_DMA

unsigned char DMA_cnt = 0,DMA_cnt_last = 0;

endif

uint8_t * audio_data_p=buf_const;
uint8_t * audio_rambuff_p=buf_Ram;
/*
0:空闲状态
1:接收状态
*/
char audio_state=0;

void i2s_test_init(void)
{
int i;

for (i = 7; i < 12; i++)
    pad_mux_write(i, 9); // MCK, SCK, LRCK, DO, DI

// 8K 16-bit configuration
i2s_set_mclk(I2S_CLK_DIV31);
i2s_set_bit_clk(I2S_MCLK_DIV4);

i2s_set_channel_clock(I2S_LEFT_LOW);    //设置左声道的LRCLK的极性为低电平
i2s_set_channel(I2S_MONO_LEFT);   //捕获左声道数据
i2s_set_bit_order(I2S_RX, I2S_MSB_FIRST);   //传输数据的时候高位在前
i2s_set_transfer_format(I2S_FISRT_BIT_SECOND_CYCLE);   //LRCLK变化后第二个时钟采集数据

i2s_set_sample_width(I2S_16BIT);   //16BIT模式
i2s_enable_int(I2S_DMA_ALL_INT);
NVIC_EnableIRQ(I2S_IRQn);

}

static void i2s_test_slient_irq_cb(uint32_t int_st)
{
DMA_cnt++;
if(audio_state==0)
{
//DBG(“idle dma_cnt:%x\r\n”,DMA_cnt);
}
else if(audio_state==1) //进入接收数据模式
{
gpo_toggle(LED2); //翻转LED2表示发生了DMA中断
//DBG(“play dma_cnt:%x “,DMA_cnt);
if (int_st & I2S_DMA_HALF_DONE_INT_ST) { //发生了DMA半中断,代表buf_Ram数组前面的数据已经接收完成
audio_rambuff_p=buf_Ram;
//memcpy(audio_data_p,audio_rambuff_p,DMA_size/2); //这里可以把数据拷贝走
SEGGER_RTT_Write(0,audio_rambuff_p,DMA_size/2); //本工程并没有做拷贝数据的步骤,而是使用SEGGER_RTT_Write的函数间接的把数据拷贝到buf_const数组中,同时这样做后就可以用RTT来读取buf_const数组的数据了
audio_data_p+=DMA_size/2; //一次拷贝一半的数据
//DBG(“buf_Ram_p2:%x “,(buf_Ram+DMA_size/2));
}
else if (int_st & I2S_DMA_DONE_INT_ST) { ///发生了DMA全中断,代表buf_Ram数组后面的数据已经接收完成
audio_rambuff_p=buf_Ram+DMA_size/2;
//memcpy(audio_data_p,audio_rambuff_p+DMA_size/2,DMA_size/2);
SEGGER_RTT_Write(0,audio_rambuff_p,DMA_size/2);
audio_data_p+=DMA_size/2;
//DBG(“buf_Ram_p1:%x “,buf_Ram);
}
if(audio_data_p>=(buf_const+READ_BUFF_LEN)) //接收数据完成
{
i2s_stop(); //停止I2S
audio_state=0;
}
//DBG(“data_p:%x\r\n”,audio_data_p);
}
}

void i2s_test_Silent_RX(void) //开始I2S接收函数
{
DMA_size=RAM_BUFF_LEN;

memset(buf_Ram,0xff,DMA_size);

i2s_set_irq_callback(i2s_test_slient_irq_cb);
//i2s_trigger_TXDMA(buf_Ram, DMA_size);
i2s_trigger_RXDMA(buf_Ram,DMA_size);  //设置I2S接收数据的大小

}

int main()
{
__disable_irq();
//GPO
pad_mux_write(LED1, 0);
pad_mux_write(LED2, 0);
pad_mux_write(LED3, 0);
pad_mux_write(LED4, 0);
gpo_config(LED1,1);
gpo_config(LED2,1);
gpo_config(LED3,1);
gpo_config(LED4,1);

//GPI
pad_mux_write(KEY1, 0);
pad_mux_write(KEY2, 0);
pad_mux_write(KEY3, 0);
pad_mux_write(KEY4, 0);
gpi_config(KEY1, PULL_UP);
gpi_config(KEY2, PULL_UP);
gpi_config(KEY3, PULL_UP);
gpi_config(KEY4, PULL_UP);

//uart 0
pad_mux_write(20, 7);
pad_mux_write(21, 7);
dbg_init();
dbg_printf(“SYD8821 IIS DEMO\r\n”);

i2s_test_init();

DebugLogInit();   //初始化RTT
QPRINTF("SYD8821 IIS DEMO\r\n");

__enable_irq();

DMA_cnt=0;
audio_state=0;

while(1)
{
    gpo_toggle(LED4);

    #ifdef DEBUG_I2S_DMA
    if(DMA_cnt !=DMA_cnt_last)
    {
        DMA_cnt_last=DMA_cnt;
        if(audio_state==0)
        {
            dbg_printf("idle dma_cnt:%x\r\n",DMA_cnt);
        }
        else if(audio_state==1)
        {
            dbg_printf("record dma_cnt:%x buf_Ram_p2:%x data_p:%x",DMA_cnt,audio_rambuff_p,audio_data_p);

        }
        else if(audio_state==2)
        {
            dbg_printf("record finish dma_cnt:%x\r\n",DMA_cnt);
        }
    }
    #endif

    if(!gpi_get_val(KEY1)){
        gpo_toggle(LED1);
        if(audio_state==0)
        {
            audio_data_p=buf_const;
            audio_state=1;
            i2s_test_Silent_RX();  //开始I2S接收
        }
    }
}       

}
因为在本博客中I2S的接收占用大量的内存,所以这里要想办法把RTT的缓存指定到buf_const数组,为了和之前的工程不造成冲突,这里自定义一下RTT的代码,也就是本工程的RTT代码和其他的工程是不一样的,具体实现如下:
1.在本工程目录下拷贝一份RTT的源码,并且添加到工程中:
这里写图片描述这里写图片描述
2.修改RTT的初始化函数(_DoInit),修改后如下:
这里写图片描述
这样RTT的缓存就指定到了buf_const数组!
一切准备好后,下载代码,进入仿真状态运行后在i2s_stop();函数后打一个断点:
这里写图片描述
然后让逻辑分析仪处于捕获模式,并且使《EVBUtility.exe》tool进入rtt的状态:
这里写图片描述
接下来按下KEY1按键,可看到逻辑分析仪抓到的波形如下:
这里写图片描述
注意:因为逻辑分析仪软件并不会分析第一个波形的数据,所以这里请自己分析,另外逻辑分析仪属于数字仪器,所以波形的最后一个bit可能会和SYD8821读到的数据有差异!
更加详细的数据请看:https://download.csdn.net/download/chengdong1314/10577899
在KEIL的仿真界面可以看到各个数组的数据如下:
这里写图片描述这里写图片描述
因为在进行I2S数据接收之前RTT上已经有一些数据打印了,所以这里buf_Ram数组的前面有些字节被I2S最后的一些数据覆盖了!所以第一个I2S的数据并不是从0开始的,这里数据从0x18开始(根据具体的情况而定)!
_SEGGER_RTT结构体内容如下:
这里写图片描述
在RTT中可以看到打印内容如下:
这里写图片描述这里写图片描述
更加详细的数据请看:https://download.csdn.net/download/chengdong1314/10577891
可以看到SYD8821正确捕获到了I2S总线上的数据,并且传到RTT上的数组也是正确的!

这里上传本博客的源码:https://download.csdn.net/download/chengdong1314/10577913,工程在《Source Code\SYD8821\iis_RX\Keil》
上传本博客使用的《EVBUtility.exe》:https://download.csdn.net/download/chengdong1314/10577920
上传本博客的MIC的规格书:https://download.csdn.net/download/chengdong1314/10577923

猜你喜欢

转载自blog.csdn.net/chengdong1314/article/details/81347923
今日推荐