秃头老弟 2023-12-20 09:27 采纳率: 0%
浏览 36
已结题

i2S驱动SPH0645

我买了一块SPH0645的数字硅麦,我看手册是24位的,i2s的硅麦,下面是我单片机i2s的配置,采样频率是16Khz,CLK是1MHz,符合手册上给的时钟,通过DMA搬运数据,存放在uint32_t audio_buffer[4]里。采集到数据了,但是不管我制造多大声音,所采集的数据几乎不变,所以我想问问有没有懂得人,驱动过这款硅麦的,看看是否是我i2s配置有问题还是数据解析有问题。下面是我的配置代码

/*i2s的相关配置*/
void i2s_config ( void )
{
    /*引脚初始化*/
    gpio_config();
    
    dma_init_type dma_init_struct;

    i2s_init_type i2s_init_struct;

    crm_periph_clock_enable ( CRM_DMA1_PERIPH_CLOCK, TRUE ); /*使能 DMA1 时钟*/
    dma_reset ( DMA1_CHANNEL2 ); /*复位 DMA1 channel4,使 channel4 处于默认配置*/

    dma_default_para_init ( &dma_init_struct );/*将 DMA 初始化变量置为默认值*/
    dma_init_struct.buffer_size = 4;/*设置 DMA buffer 长度: 和12S 通信数据长度一致*/
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;/*数据传输方向:从外设到内存*/
    dma_init_struct.memory_base_addr = ( uint32_t ) audio_buffer;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_WORD;//DMA 内存数据总线宽度 16 位
    dma_init_struct.memory_inc_enable = TRUE;/*内存地址自增: 使能 (每收/发一个数据后,内存地址要加一*/
    dma_init_struct.peripheral_base_addr = ( uint32_t ) 0x4001300C; //外设地址
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_WORD;//DMA 外设数据总线宽度 16 位
    dma_init_struct.peripheral_inc_enable = FALSE;/*外设地址自增:关闭(一直是 SPI 数据寄存器,不变)*/
    dma_init_struct.priority = DMA_PRIORITY_HIGH;//优先级:高优先级
    dma_init_struct.loop_mode_enable = TRUE;//循环模式:关闭
    dma_init ( DMA1_CHANNEL2, &dma_init_struct );

    crm_periph_clock_enable ( CRM_SPI1_PERIPH_CLOCK, TRUE );

    i2s_default_para_init ( &i2s_init_struct );

    i2s_init_struct.operation_mode = I2S_MODE_MASTER_RX;//设置i2S为主机接收模式
    i2s_init_struct.audio_protocol = I2S_AUDIO_PROTOCOL_MSB;//设置I2S为飞利浦标准
    i2s_init_struct.audio_sampling_freq = I2S_AUDIO_FREQUENCY_16K;//配置i2s采样率为16K;
    i2s_init_struct.data_channel_format = I2S_DATA_24BIT_CHANNEL_32BIT;//设置i2s帧格式为:数据位数为24bit,声道位数为32bit
    i2s_init_struct.clock_polarity = I2S_CLOCK_POLARITY_LOW;//设置时钟空闲电平为低电平
    i2s_init_struct.mclk_output_enable = FALSE;//使能MCLK时钟输出
    i2s_init ( SPI1, &i2s_init_struct );

    spi_i2s_dma_receiver_enable ( SPI1, TRUE );
    dma_channel_enable ( DMA1_CHANNEL2, TRUE );
    i2s_enable ( SPI1, TRUE );
}
/*采集的数据处理*/
void get_db_value ( void )
{
    //dat32 example: 0000fffb 00004f00
    val24 = (( audio_buffer[0] << 8 ) + ( audio_buffer[1]  ))>>8;


    //24位有符号整型扩展到32if ( val24 & 0x800000 ) //negative
    {
        val32 = 0xff000000 | val24;
    }
    else  //positive
    {
        val32 = val24;
    }

}
  • 写回答

16条回答 默认 最新

  • 专家-郭老师 Java领域新星创作者 2023-12-20 09:28
    关注
    获得1.80元问题酬金

    由人工智能和答主提供,可以参考如下,如果回答的不正确,及时评论区回复,我追加回答,谢谢。


    从你的代码来看,你已经正确地配置了I2S和DMA。但是,你提到采集到的数据几乎不变,这可能是由于以下原因:

    1. 采样率设置不正确:根据手册,SPH0645的采样率为16KHz,但是你的代码中设置的采样率为16K。请检查并确保采样率设置正确。

    2. 数据位宽设置不正确:根据手册,SPH0645的数据位宽为24位,但是你的代码中设置的数据位宽为32位。请检查并确保数据位宽设置正确。

    3. 数据处理问题:在get_db_value()函数中,你将24位有符号整数扩展到32位整数。但是,你没有处理负数的情况。当val24的最高位(第24位)为1时,表示这是一个负数。你需要在扩展之前检查这个位,并根据需要设置最高位为1。

    你可以尝试修改get_db_value()函数,如下所示:

    void get_db_value ( void ){
        //dat32 example: 0000fffb 00004f00
        val24 = (( audio_buffer[0] << 8 ) + ( audio_buffer[1]  ))>>8;
        //将24位有符号整型扩展到32位
        if ( val24 & 0x800000 ) //negative
        {
            val32 = 0xff000000 | val24;
        }
        else  //positive
        {
            val32 = val24;
        }
    }
    

    如果问题仍然存在,建议你检查硬件连接和信号完整性,以及使用示波器或其他调试工具验证I2S和DMA传输是否正确。

    评论

报告相同问题?

问题事件

  • 系统已结题 12月28日
  • 创建了问题 12月20日

悬赏问题

  • ¥15 征集Python提取PDF文字属性的代码
  • ¥15 有偿求苍穹外卖环境配置
  • ¥15 代码在keil5里变成了这样怎么办啊,文件图像也变了,
  • ¥20 Ue4.26打包win64bit报错,如何解决?(语言-c++)
  • ¥15 clousx6整点报时指令怎么写
  • ¥30 远程帮我安装软件及库文件
  • ¥15 关于#自动化#的问题:如何通过电脑控制多相机同步拍照或摄影(相机或者摄影模组数量大于60),并将所有采集的照片或视频以一定编码规则存放至规定电脑文件夹内
  • ¥20 深信服vpn-2050这台设备如何配置才能成功联网?
  • ¥15 Arduino的wifi连接,如何关闭低功耗模式?
  • ¥15 Android studio 无法定位adb是什么问题?