首页 > 评测 > PSoC 6评测第四篇-录音与放音

PSoC 6评测第四篇-录音与放音

PSoC 6   耳机   PDM   PCM   ADC采样   
  • 作者:zhanzr
  • 来源:21ic
  • [导读]
  • 写上一篇关于EInk的文章的时候,就想着要写这一篇了.因为作者本人除了喜欢阅读之外,还比较喜欢音乐.也喜欢听也喜欢唱K,故此对音频相关的技术也较为感兴趣,至于水平只能说稍知一二.看到这个CY8CKIT开发套件上带有数字麦克风,就动了心思.本文使用开发板子上的资源做一个简单的录音与放音实验,研究一下相关知识.
image11.png

图 8 KHz定时器用作播放更新

注意产生的频率有一定的误差,只要在一定范围内是可以接受的.某些要求苛刻的音频设备使用比较不常见的晶体频率即是为了最大程度提高播放精度.

根据现有条件,直接将耳机的两个通道分别接在VDAC与PWM输出上:

image12.jpg

图 硬件连接细节

根据实验,阻抗大的耳机效果好一点点,因为引脚驱动有限的缘故.

image13.jpg

图 入耳式的耳机阻抗稍大一点

软件

因为主要模块都是硬件生成的,所以软件上也只是控制一个流程而已.流程就是录制-播放两个过程进行循环.此例子与上一篇的例子不同,仅仅使用了Cortex M4的内核,M0+内核除了使能Cortex M4之外没有做任何事情.

初始化各模块:

/* Enable global interrupts. */

__enable_irq();

/* Initialize the PCM interrupt and enable it */

Cy_SysInt_Init(&PCM_ISR_cfg, PCM_ISR_Handler);

NVIC_EnableIRQ(PCM_ISR_cfg.intrSrc);

//The Audio Play ISR

Cy_SysInt_Init(&AudioPlayISR_cfg, AudioPlay_ISR_Handler);

NVIC_EnableIRQ(AudioPlayISR_cfg.intrSrc);

/* Start the UART component for reporting the volume */

UART_Start();

AudioTimer_Start();

VDAC_Start();

AudioPWM_Start();

/* Star the PCM component */

Cy_PDM_PCM_Init(PDM_PCM_HW, &PDM_PCM_config);

Cy_PDM_PCM_Enable(PDM_PCM_HW);

此时各模块已经开始工作,刚刚开始是录音模式.

PDM_PCM的ISR:

void PCM_ISR_Handler(void)

{

/* Set the PCM flag */

flag = 1;

/* Disable PCM ISR to avoid multiple calls to this ISR */

NVIC_DisableIRQ(PCM_ISR_cfg.intrSrc);

}

此处做标记表示有一个FIFO的数据转换为PCM完成需要拿走.主循环中将其放入播放buffer:

for (uint32_t i = 0; i < PDM_PCM_RX_FIFO_TRG_LVL; i++)

{

g_AudioBuff[g_RecIdx++]=(int16_t)PDM_PCM_ReadFifo();

}

一旦buffer满了即转为播放模式,当中需要用户按下SW2按钮:

printf("To Enter Play Mode.\n");

printf("Press SW2\n");

/* Clear SW2 interrupt */

Cy_GPIO_ClearInterrupt(SW2_PORT, SW2_NUM);

while(0 == (Cy_GPIO_GetInterruptStatus(SW2_PORT, SW2_NUM)))

{

__WFI();

}

printf("Play...\n");

g_playRecFlag = true;

g_PlayIdx = 0;

在Audio Timer的ISR中更新播放Sample:

void AudioPlay_ISR_Handler(void)

{

if((true == g_playRecFlag) && (g_PlayIdx < SAMPLE_SIZE))

{

int16_t tmpV16 = g_AudioBuff[g_PlayIdx++];

VDAC_SetValueBuffered(tmpV16>>4);

int8_t tmpV8 = tmpV16/256;

if(tmpV8 < 0)

{

AudioPWM_SetCompare0(256 - tmpV8);

}

else

{

AudioPWM_SetCompare0(127 + tmpV8);

}

}

AudioTimer_ClearInterrupt(CY_TCPWM_INT_ON_CC_OR_TC);

}

注意采集进来的数据为16bit有符号数据,而DAC为12bit,PWM为8bit,需要加以转换.一旦播放完毕需要用户按下SW2重新开始录音.过程与上面的过程类似,反复循环.

根据实际体验,目前这个PDM_PCM转换结果不是很完美,噪音较多,也有可能是本人使用不当.如有进一步的研究结果再来汇报.

总结,资源与参考

Cypress的这个开发板子CY8CKIT能玩的点较多,拿到板子忍不住做了不少实验.其实编辑说搞一两篇就算交差了,这次也算超额完成任务.官方也有一篇音频例程,讲的是检测当前环境的噪音水平,本人认为过于简单于是在此基础上完成了本文的实验.

关于音频,本人一向很感兴趣,以前也写过不少此方面的文章.包括本文做的一些实验其实是之前文章的延伸,故此一些过于细节的部分不想赘述,感兴趣的读者可以在本站找一下之前的文章配合阅读.目前人工智能,语音识别比较热门,作者也有心再做一点此方面的实验,但是这个话题就太大,不知道能否写出文章来.

代码下载连接:

链接: https://pan.baidu.com/s/1nw4o2Pr 密码: cjtc

  • 本文系21ic原创,未经许可禁止转载!

网友评论