海思hi3518ev300说明书_海思3516dv300方案开发

海思hi3518ev300说明书_海思3516dv300方案开发1.硬件内置AudioCodec/外置FM1288,hi3516dv300为内置audiocodec,硬件上外接FM1288,通过MIC单端/差分输入音频.2.重要概念2.1.I2S相关概念(1)LRCLK(帧时钟,也称为WS) 当LRCLK为低电平时表示左声道,高电平时表示右声道, LRCLK的频率=采样频率(2)SCLK(串行时钟),也叫BCLK(位时钟);方波形式存在 对应数字音频的每一位数据,SCLK都有一个脉冲. SCLK的频率=2*采样频率*采样位数

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

1.硬件

在这里插入图片描述

Hi3516支持内置AudioCodec/外置音频解码芯片; 由于这里硬件上外接FM1288,故走的是外置,通过I2S接入, 通过MIC单端/差分输入音频.
由于之前一直调试内置Codec,这里任然保留内置相关代码;

2.重要概念

2.1. I2S相关概念

(1)LRCLK (帧时钟,也称为WS)
	当LRCLK为低电平时表示传输左声道,高电平时表示传输右声道,
	LRCLK的频率 = 采样频率

(2)SCLK(串行时钟) ,也叫BCLK(位时钟);方波形式存在
	对应数字音频的每一位数据,SCLK都有一个脉冲.
	SCLK的频率 = 2 * 采样频率 * 采样位数;

 (3) SDATA 串行数据,就是二进制补码表示的音频数据.

(4) MCLK(主时钟,也叫系统时钟)
	一般采样频率的256倍或384倍,它并不是必须的,可有可无,具体看要求.

(5)
	I2S是一种比较简单的数字接口协议,没有地址或设备选择机制;
	在I2S总线上,只能同时存在一个主设备和发送设备;
	主设备可以是发送设备,也可以是接收设备,或是协调发送设备和接收设备的其他控制设备;

2.2 关键点

(1)  底层时序不需要我们自己实现,如i2s如何控制FM1288等.
(2) i2c用的连在主芯片(hi3516dv300)上,就可以直接用底层的驱动.
(3) FM1288的i2s,应该已经封装到mpp里面,只需通过i2c配置好codec,然后通过mpp库操作ai/ao接口即可.
(4) 通过i2c配置下寄存器,一般codec都是配置i2s的模式(主/从,采样率等参数),i2s的bclk,ws等;
(5) 主时钟(MCLK)要看看是有海思做主(master)还是由codec()做主 (slave);
(6) 一般都是由主设备提供MCLK,帧时钟和位时钟都是通过这个MLCK计算出来的.

3.音频上行(ai->aenc)

软件设计上参考: 对应SDK/mpp/sample/audio/sample_audio.c

先配置i2c.通过引脚图及hdmi命令配置:
如:system("himm 0x114F004C 0x103");

据手册: 在 AI/AO 设备主模式下,建议用户先配置好AI/AO,在配置codec;

3.1. 输入初始化

	HI_S32 rc ,i;
    AIO_ATTR_S stAioAttr;
    AUDIO_DEV   AiDev = 0;

    stAioAttr.enSamplerate   = AUDIO_SAMPLE_RATE_8000;
    stAioAttr.enBitwidth     = AUDIO_BIT_WIDTH_16;
    stAioAttr.enWorkmode     = AIO_MODE_I2S_MASTER;
    stAioAttr.enSoundmode    = AUDIO_SOUND_MODE_MONO;
    stAioAttr.u32EXFlag      = 1;
    stAioAttr.u32FrmNum      = 30;
    stAioAttr.u32PtNumPerFrm = 320;
    stAioAttr.u32ChnCnt      = 2; //最大只能支持2个
    stAioAttr.u32ClkSel      = 1;
    //stAioAttr.enI2sType = AIO_I2STYPE_INNERCODEC; 选择内置Codec解码
    stAioAttr.enI2sType      = AIO_I2STYPE_EXTERN;//若外部单独有解码芯片,需要选择外部,另需要确认是否支持;
   
    rc = HI_MPI_AI_SetPubAttr(AiDev, &stAioAttr);
  	//rc错误处理,以下均省略...
  	
    rc = HI_MPI_AI_Enable(AiDev);
      
    AI_CHN_PARAM_S pstChnParam;
    for(int j = 0; j < stAioAttr.u32ChnCnt; j++)
    { 
   
        rc = HI_MPI_AI_GetChnParam(AiDev, j, &pstChnParam);
 
        pstChnParam.u32UsrFrmDepth = 30;

        rc = HI_MPI_AI_SetChnParam(AiDev, j,&pstChnParam);

        rc = HI_MPI_AI_EnableChn(AiDev, j);
    }  

#if 1 //这部分据实际情况慢慢调
	//3516dv300输入不支持 HI_MPI_AI_SetVqeAttr,可用HI_MPI_AI_SetTalkVqeAttr
    //声音质量增强功能(Talk)相关属性
    AUDIO_DEV AiDevId = 0;
    AI_CHN AiChn = 0;
    AUDIO_DEV AoDevId = 0;
    AO_CHN AoChn = 0;
    AI_TALKVQE_CONFIG_S pstVqeConfig;
    memset(&pstVqeConfig, 0, sizeof(AI_TALKVQE_CONFIG_S));

    pstVqeConfig.u32OpenMask = AI_TALKVQE_MASK_HPF | AI_TALKVQE_MASK_ANR ;//| AI_TALKVQE_MASK_AGC ;
    pstVqeConfig.s32WorkSampleRate = AUDIO_SAMPLE_RATE_8000;
    pstVqeConfig.s32FrameSample = 320;
    pstVqeConfig.enWorkstate = VQE_WORKSTATE_MUSIC ;

    //去低频,表现为轰轰不舒适声音
    pstVqeConfig.stHpfCfg.bUsrMode = HI_TRUE;
    pstVqeConfig.stHpfCfg.enHpfFreq = AUDIO_HPF_FREQ_150;//建议120或150

    //回声抵消
    pstVqeConfig.stAecCfg.bUsrMode = HI_FALSE;
// pstVqeConfig.stAecCfg.s8CngMode = 1;//舒适噪音模式
// pstVqeConfig.stAecCfg.s8NearAllPassEnergy = 1;//判断是否无光泽传输的远端能量阈值:
// pstVqeConfig.stAecCfg.s8NearCleanSupEnergy = 2;//近端信号强制复位的能量门限:
// pstVqeConfig.stAecCfg.s16DTHnlSortQTh = 16384;
// pstVqeConfig.stAecCfg.s16EchoBandLow = 10;//语音处理band1,低频参数,
// pstVqeConfig.stAecCfg.s16EchoBandHigh = 25;//41;//语音处理band1,高频参数,
// pstVqeConfig.stAecCfg.s16EchoBandLow2 = 28;//47;
// pstVqeConfig.stAecCfg.s16EchoBandHigh2 = 35;//63;

// HI_S16 s16ERLBand[6] = {4, 6, 36, 49, 50, 51};
// HI_S16 s16ERL[7] = {7, 10, 16, 10, 18, 18, 18};
// memcpy(pstVqeConfig.stAecCfg.s16ERLBand,s16ERLBand,sizeof(s16ERLBand));
// memcpy(pstVqeConfig.stAecCfg.s16ERL,s16ERL,sizeof(s16ERL));
// pstVqeConfig.stAecCfg.s16VioceProtectFreqL = 3;
// pstVqeConfig.stAecCfg.s16VioceProtectFreqL1 = 6;


    //去除外界噪音
    pstVqeConfig.stAnrCfg.bUsrMode = HI_TRUE;
    pstVqeConfig.stAnrCfg.s16NrIntensity = 15;//[0~25]越大降噪力度越高,损伤越高.
    pstVqeConfig.stAnrCfg.s16NoiseDbThr = 60;//[30~60]越大,检测力度越弱,声音更平滑
    pstVqeConfig.stAnrCfg.s8SpProSwitch = 1;//[0/1]是否开启对音乐细节检测,喧闹场景不建议开

    //AGC 更多是放大输入源的声音
    pstVqeConfig.stAgcCfg.bUsrMode    = HI_FALSE;

#if 0
    pstVqeConfig.stAgcCfg.s8TargetLevel = -2;
    pstVqeConfig.stAgcCfg.s8NoiseFloor = -40;
    pstVqeConfig.stAgcCfg.s8MaxGain = 30;
    pstVqeConfig.stAgcCfg.s8AdjustSpeed = 10;
    pstVqeConfig.stAgcCfg.s8ImproveSNR = 2;//上限6db
    pstVqeConfig.stAgcCfg.s8UseHighPassFilt = 3;
    pstVqeConfig.stAgcCfg.s8OutputMode = 0;
    pstVqeConfig.stAgcCfg.s16NoiseSupSwitch = 1;//开启噪声抑制
#endif

	//遇到库找不到请看下面
    rc = HI_MPI_AI_SetTalkVqeAttr(AiDevId, AiChn, AoDevId, AoChn,&pstVqeConfig);

    rc = HI_MPI_AI_EnableVqe(AiDevId, AiChn);
#endif

3.2. 输出初始化

	HI_S32 rc ,i;
    HI_S32 s32AoChnCnt; 
    AIO_ATTR_S stAioAttr;
	AUDIO_DEV   AoDev = 0;
  
   rc = HI_MPI_AO_Disable(AoDev );//先禁用AO设备

    stAioAttr.enSamplerate   = AUDIO_SAMPLE_RATE_8000;
    stAioAttr.enBitwidth     = AUDIO_BIT_WIDTH_16;
    stAioAttr.enWorkmode     = AIO_MODE_I2S_MASTER;
    stAioAttr.enSoundmode    = AUDIO_SOUND_MODE_MONO;
    stAioAttr.u32EXFlag      = 1;
    stAioAttr.u32FrmNum      = 30;
    stAioAttr.u32PtNumPerFrm = 320;
    stAioAttr.u32ChnCnt      = 2;
    stAioAttr.u32ClkSel      = 1;
    //stAioAttr.enI2sType = AIO_I2STYPE_INNERCODEC;
    stAioAttr.enI2sType      = AIO_I2STYPE_EXTERN;//若外部单独有解码芯片,需要选择外部,另需要确认是否支持;

    rc = HI_MPI_AO_SetPubAttr(AoDev , &stAioAttr);

    rc = HI_MPI_AO_Enable(AoDev );

    /* enable AO channle */
    s32AoChnCnt = stAioAttr.u32ChnCnt;

    for (i = 0; i < s32AoChnCnt >> stAioAttr.enSoundmode; i++)
    { 
   
        rc = HI_MPI_AO_EnableChn(AoDev , i);
    }
	
#if 0 //没用到
	AUDIO_DEV AoDevId = 0;
    AO_CHN AoChn = 0;
    AO_VQE_CONFIG_S pstVqeConfig;
    memset(&pstVqeConfig, 0, sizeof(AO_VQE_CONFIG_S));
    
    pstVqeConfig.u32OpenMask = AO_VQE_MASK_HPF | AO_VQE_MASK_ANR | AO_VQE_MASK_AGC;
    pstVqeConfig.s32WorkSampleRate = AUDIO_SAMPLE_RATE_8000;
    pstVqeConfig.s32FrameSample = 320;
    pstVqeConfig.enWorkstate = VQE_WORKSTATE_COMMON ;

    //高通滤波功能相关配置
    pstVqeConfig.stHpfCfg.bUsrMode = HI_TRUE;
    pstVqeConfig.stHpfCfg.enHpfFreq = AUDIO_HPF_FREQ_150;

    //去噪
    pstVqeConfig.stAnrCfg.bUsrMode = HI_TRUE;//用户模式
    pstVqeConfig.stAnrCfg.s16NrIntensity = 15;//[0~25]越大降噪力度越高,损伤越高.
    pstVqeConfig.stAnrCfg.s16NoiseDbThr = 60;//[30~60]越大,检测力度越弱,声音更平滑
    pstVqeConfig.stAnrCfg.s8SpProSwitch = 1;//[0/1]是否开启对音乐细节检测,喧闹场景不建议开

    //自动增益控制
    pstVqeConfig.stAgcCfg.bUsrMode    = HI_TRUE;
    pstVqeConfig.stAgcCfg.s8TargetLevel = -2;
    pstVqeConfig.stAgcCfg.s8NoiseFloor = -20;
    pstVqeConfig.stAgcCfg.s8MaxGain = 30;
    pstVqeConfig.stAgcCfg.s8AdjustSpeed = 10;
    pstVqeConfig.stAgcCfg.s8ImproveSNR = 0;//上限6db
    pstVqeConfig.stAgcCfg.s8UseHighPassFilt = 0;
    pstVqeConfig.stAgcCfg.s8OutputMode = 0;
    pstVqeConfig.stAgcCfg.s16NoiseSupSwitch = 1;//开启噪声抑制

    rc = HI_MPI_AO_SetVqeAttr(AoDevId, AoChn, &pstVqeConfig);

    rc = HI_MPI_AO_EnableVqe(AoDevId, AoChn);
    printf("HI_MPI_AO_EnableVqe AoDevId[%d] rc[%d] \n",AoDevId,rc);
#endif

3.3. codec配置

如果是外置解码芯片,这里不需要配置内部Codec; 外置解码芯片就相当于codec;
应该不需要配置这么多,视情况而定!
	//func(enSamplerate) enSamplerate传进来
	HI_S32 fdAcodec= -1;
    HI_S32 ret = HI_SUCCESS;
    ACODEC_FS_E i2s_fs_sel;   

    switch (enSamplerate)
    { 
   
    case AUDIO_SAMPLE_RATE_8000:
        i2s_fs_sel = ACODEC_FS_8000;
        break;
    case AUDIO_SAMPLE_RATE_16000:
        i2s_fs_sel = ACODEC_FS_16000;
        break;
    case AUDIO_SAMPLE_RATE_32000:
        i2s_fs_sel = ACODEC_FS_32000;
        break;
    case AUDIO_SAMPLE_RATE_48000:
        i2s_fs_sel = ACODEC_FS_48000;
        break;
    default:
        i2s_fs_sel = ACODEC_FS_8000;
        break;
    }

    fdAcodec = open("/dev/acodec",O_RDWR);
    if(fdAcodec < 0)
    { 
   
        printf("[%s %d] open dev/acodec failed!\n",__FUNCTION__,__LINE__);
        return HI_FALSE;
    }

    //将内置Codec恢复为默认设置
    if(ioctl(fdAcodec, ACODEC_SOFT_RESET_CTRL))
    { 
   
        printf("reset the audio code to the default config error\n");
    }

    //设置I2s1采样率
    if(ioctl(fdAcodec, ACODEC_SET_I2S1_FS, &i2s_fs_sel))
    { 
   
        printf("[%s %d] set i2s1 fs failed!\n",__FUNCTION__,__LINE__);
        return HI_FALSE;
    }


    //输入方式选择
    ACODEC_MIXER_E input_mode = ACODEC_MIXER_IN1;//单端输入 ACODEC_MIXER_IN_D;//:差分
    if (ioctl(fdAcodec, ACODEC_SET_MIXER_MIC, &input_mode))
    { 
   
        printf("%s: select acodec input_mode failed\n", __FUNCTION__);
        ret = HI_FAILURE;
    }

    int iVol = 50;//[-78-80] 建议[19-50]
#if 1
     //输入音量之PGA模块
    if (ioctl(fdAcodec, ACODEC_SET_INPUT_VOL, &iVol))
    { 
   
        printf("%s: ioctl ACODEC_SET_INPUT_VOL failed\n", __FUNCTION__);
        return HI_FALSE;
    }

    unsigned int gain_mac;
    gain_mac = 15;//15为最大增益30db 16:-1.5db
    if (ioctl(fdAcodec, ACODEC_SET_GAIN_MICL, &gain_mac))
    { 
   
        printf("%s: ioctl ACODEC_SET_GAIN_MICL failed\n", __FUNCTION__);
        ret = HI_FAILURE;
    }
    if (ioctl(fdAcodec, ACODEC_SET_GAIN_MICR, &gain_mac))
    { 
   
        printf("%s: ioctl ACODEC_SET_GAIN_MICR failed\n", __FUNCTION__);
        ret = HI_FAILURE;
    }


    //输入音量之BOOST模块
    if (ioctl(fdAcodec, ACODEC_SET_INPUT_VOL, &iVol))
    { 
   
        printf("%s: ioctl ACODEC_SET_INPUT_VOL failed\n", __FUNCTION__);
        return HI_FALSE;
    }
    unsigned int enable_boostl;
    enable_boostl = 0x1;//取1时模拟增益增加20db
    if (ioctl(fdAcodec, ACODEC_ENABLE_BOOSTL, &enable_boostl))
    { 
   
        printf("%s: ioctl ACODEC_ENABLE_BOOSTL failed\n", __FUNCTION__);
        return HI_FALSE;
    }
    unsigned int enable_boostr;
    enable_boostr = 0x1;//取1时模拟增益增加20db
    if (ioctl(fdAcodec, ACODEC_ENABLE_BOOSTR, &enable_boostr))
    { 
   
        printf("%s: ioctl ACODEC_ENABLE_BOOSTR failed\n", __FUNCTION__);
        return HI_FALSE;
    }
//#else
    //输入音量之ADC模块
    if (ioctl(fdAcodec, ACODEC_SET_INPUT_VOL, &iVol))
    { 
   
        printf("%s: ioctl ACODEC_SET_INPUT_VOL failed\n", __FUNCTION__);
        return HI_FALSE;
    }
    ACODEC_VOL_CTRL vol_ctrl;
    vol_ctrl.vol_ctrl_mute = 0;//不静音
    vol_ctrl.vol_ctrl = 0;//[0~127] 0音量最大
    //左声道输入音量控制
    if(ioctl(fdAcodec, ACODEC_SET_ADCL_VOL, &vol_ctrl))
    { 
   
        printf("%s: acodec set adcl vol failed\n", __FUNCTION__);
        ret = HI_FAILURE;
    }
    if(ioctl(fdAcodec, ACODEC_SET_ADCR_VOL, &vol_ctrl))
    { 
   
        printf("%s: acodec set adcr vol failed\n", __FUNCTION__);
        ret = HI_FAILURE;
    }
#endif

    //输出总音量控制
    iVol = 4; //[-126~6]
    if (ioctl(fdAcodec, ACODEC_SET_OUTPUT_VOL, &iVol))
    { 
   
        printf("[%s %d] set output vol fs failed!\n",__FUNCTION__,__LINE__);

    }

    //把MICIN静音(MUTE)功能关闭
#if 1
    HI_U32 u32MuteCtrl = 0;
    if(ioctl(fdAcodec, ACODEC_SET_MICL_MUTE, &u32MuteCtrl))
    { 
   
     printf("%s: select acodec mute_l failed\n", __FUNCTION__);
     ret = HI_FAILURE;
    }
    if(ioctl(fdAcodec, ACODEC_SET_MICR_MUTE, &u32MuteCtrl))
    { 
   
     printf("%s: select acodec mute_r failed\n", __FUNCTION__);
     ret = HI_FAILURE;
    }
#endif

    close(fdAcodec);

4.音频下行 (adec->ao)

一般情况上行没问题,下行只是方向相反而已!
伪代码:

	HI_MPI_ADEC_CreateChn(chn,&解码参数)HI_MPI_SYS_Bind(HI_ID_ADEC,..HI_ID_AO);

	while(获取流)
	{ 
   
		HI_MPI_ADEC_SendStream(chn,&码流结构体,阻塞否?);
	}

5.遇到的问题

问题1:
	HI3516DV300 HI_MPI_AI_EnableVqe调节音频使能Vqe时出现.
	dlopen libhive_common.so/libsecurec.so or libhive_AEC.so failed

解决方案: 
	在sdk中找到对应的.so文件,放到 usr/lib 下并记得改权限(重要).
	
问题2:
	下行过程遇到的问题:HI_MPI_ADEC_SendStream 0xA0188040(码流错误);
	排查过程:
	1> 初步怀疑解码参数问题,检查后排除;可以在send_stream前面将下行码流保存成对应格式,如.g711a格式,在pc上播放;首先确保码流到这里能播放;
	2> 第一步能通过,那么试试自编自解是否可行(首先确保上行ok,音频功放ok),在上行前先创建解码通道并绑定ao,在HI_MPI_AENC_GetStream获取流后立马又发给ao;
	3> 第二步基本都没问题,记录下发送成功的字节长度;最终将问题定位到海思头(一定确保上行码流长度和下行码流长度一致)
	如上行324字节(320+4字节海思头),下行也要保证一样,多了少了可能就有问题!!!

6.fm1288芯片

  1. 首先,向厂家要一份linux的驱动参考代码,方便参考配置;
  2. fm1288芯片使能的标志是MIC_BIAS引脚输出高电平;
  3. PWD# 引脚需要上电, RST#引脚需要复位在拉高,且需要在其后的90ms的软件初始化;
  4. I2S类型需选择AIO_I2STYPE_EXTERN才能通过I2C配置成功,不然一直显示超时;
  5. 参考 https://blog.csdn.net/qq_37565330/article/details/79460692

7.总结

多看手册,一般手册上都能找到答案.
结合sdk示例.
若软件上没啥问题,可适当排查硬件.硬件时钟,与示波器结合.分析时序等等一步步排查;

参考:https://baike.baidu.com/item/I2S/3443390?fr=aladdin

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/190250.html原文链接:https://javaforall.net

(0)
上一篇 2026年2月24日 下午3:22
下一篇 2026年2月24日 下午4:01


相关推荐

  • Can not issue data manipulation statements with executeQuery()错误解决

    Can not issue data manipulation statements with executeQuery()错误解决强烈建议 尽信书 不如无书 nbsp nbsp 下午没事 就练习了下连接数据库 结果发现了一个问题 哈哈 Cannotissued nbsp 原因是这句 st executeQuery insert nbsp into nbsp student nbsp values name age intr

    2026年3月19日
    2
  • 推荐几个非常不错的富文本编辑器

    推荐几个非常不错的富文本编辑器1、wangEditor——基于javascript和css开发的Web富文本编辑器,轻量、简洁、界面美观、易用、开源免费。界面截图:官网地址2、TinyMCE——TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器,由JavaScript写成。它对IE6+和Firefox1.5+都有着非常良好的支持。功能齐全,界面美观,就是文档是英文的,对开发人员英文水平有一定要求。界面…

    2022年6月10日
    230
  • 怎么从电脑中的cmd进入mysql_在cmd中怎么进入mysql?

    怎么从电脑中的cmd进入mysql_在cmd中怎么进入mysql?在cmd中进入mysql的步骤:1、按win+r打开,输入cmd,快速打开命令行界面,然后进入cmd2、启动MySQL服务使用以下命令:netstartmyql3、进入mysql数据库输入以下命令:mysql-hlocalhost-uroot-p执行上面的命令后,会提示输入密码,输入密码后回车,当显示下面的界面时表示成功链接到了mysql数据库。3、输入”showdatabases”回…

    2022年5月7日
    68
  • whith ~ as 用法[通俗易懂]

    whith ~ as 用法[通俗易懂]个人理解withself.client.get("/",catch_response=True)asresponse:其实就是response=self.clien

    2022年8月3日
    12
  • php 7.2 if else endif 模板语法错误提示的处理

    php 7.2 if else endif 模板语法错误提示的处理

    2022年2月18日
    54
  • Ubuntu18.04 Pycharm卸载安装

    Ubuntu18.04 Pycharm卸载安装前言 Pycharm 版本有些老旧 需要卸载并重新下载最新版本进行安装 2021 年 3 月测试可用注 版本不同名称不同这里旧版本以 Pycharm2018 1 为例 1 删除 Pycharm 安装文件夹 cd ls asudorm r Pycharm 2 删除 Pycharm 配置文件夹 cd ls asudorm

    2026年3月27日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号