本文初步介绍了PCM1770配置方法与调试过程,希望能起到抛砖引玉的作用。PCM1770是24位的DAC,支持I2S信号输入,可直接驱动耳机,也可加后级功放来驱动喇叭,应用电压范围为-0.3V至4V,普通的3V3就可以。
如图1所示,该DAC对22KHZ以上频率有60dB的衰减,相当于自带一个低通滤波,减少了后级的干扰。
如图2所示,该DAC在3V3电压条件下有100dB的信噪比,72dB的分离度确实低了点,用来玩玩还行。
图1
图2
接下来讲PCM1770的上电时序,芯片手册中如图3对上电时序描写的很清楚,就是在VCC起来至少1ms之后,将PD引脚拉高,在1024个内部系统时钟后,芯片内部会自动复位,之后双输出会拉高表示复位成功。可以利用GPIO进行PD的操作,也可利用单片机内部的Reset引脚进行硬件复位,我采用了第二种方法,复位电路如图4,时序如图5,CH1是RESET端(PD),CH2是VCC,可见,PD拉高是在VCC拉高1.2ms之后,满足PCM1770的复位时序要求。
图3
图4 图5
再来看看PCM1770的配置寄存器和寄存器的写入时序,常用到的寄存器如图6,关于软件静音、音量衰减、模拟混合等功能可按自己的需求去配置,因为我们用到的数据传输格式为I2S,故在这里必须要配置音频数据传输格式选择寄存器,由图7可得,输出传输数据协议的选择主要是配置FMT寄存器的3个位,使用I2S进行数据传输需将FMT配置为001,从图6看出FMT的3个位位于寄存器3,地址为03h,因此可知要写入数据为0000 0011 0000 0001b。
图6
图7
图8
图9
寄存器的写入时序如图8和图9,图8对其进行了简单的描述,就是指MS拉低,MC作为时钟运行,MD发送16位的数据,前8位为写入寄存器的地址,后8位为写入的数据;图9对时序进行了详细的规定,对此编写的简单代码如下。
void init_hardware(){
int i=15;
GPIO_ResetBits(GPIOC, GPIO_Pin_10);//MC
delay_nms(2);
GPIO_ResetBits(GPIOC, GPIO_Pin_7);//MS
delay_nms(2);
while(i>=0){
delay_nms(1);
GPIO_ResetBits(GPIOC, GPIO_Pin_10);//第1次上升沿
if(i==0){
GPIO_SetBits(GPIOC, GPIO_Pin_12);
}else if(i==9){
GPIO_SetBits(GPIOC, GPIO_Pin_12);
}else if(i==8){
GPIO_SetBits(GPIOC, GPIO_Pin_12);
}else{
GPIO_ResetBits(GPIOC, GPIO_Pin_12);
}
delay_nms(1);
GPIO_SetBits(GPIOC, GPIO_Pin_10);
i--;
}
GPIO_SetBits(GPIOC, GPIO_Pin_12);//MD
delay_nms(2);
GPIO_SetBits(GPIOC, GPIO_Pin_7);//MS
}
时序波形如图10和11,t(MCY)=2ms; t(MCL)=1ms; t(MCH)=1ms; t(MHH)=无穷(单次配置); t(MLS)=4ms; t(MLH)=2ms; t(MDH)=1ms; t(MDS)=1ms;均满足PCM1770对写入时序的要求。
图10
图11
配置完成后,就可以发送数据给PCM1770了,首先要初始化I2S接口,STM32的结构总线中I2S与SPI共用GPIO,在这里主要采用了SPI2口,对其进行重定义和配置,我选用了标准Philips协议,16位数据发送,MLK输出使能,音频频率为16K,高位先行,STM32做主模式。之后调用SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);启动I2S2的中断,之后系统便会根据I2S协议进入I2S2的中断,在捕获函数SPI2_IRQHandler()中将指向wav文件的数据指针地址发送就行,wav是无压缩的音频格式,数据可以通过DAC直接转换为模拟音频输出,其文件前段是文件头,描述了wav文件的各种参数信息,本文不做阐述,以后会详细介绍,可以直接跳过文件头发送音频数据,要注意的是,I2S是左右声道数据分时发送,所以在中断里数据指针一次要移动两位。
void init_I2S(){
I2S_InitTypeDef I2S_InitStructure;
//SPI_I2S_DeInit(SPI3);
SPI_I2S_DeInit(SPI2);
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16bextended;
I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_16k;//16k
I2S_InitStructure.I2S_CPOL = I2S_CPOL_High;
I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
//I2S_Init(SPI3, &I2S_InitStructure);
//I2S_InitStructure.I2S_Mode = I2S_Mode_SlaveRx;
I2S_Init(SPI2, &I2S_InitStructure);
I2S_Cmd(SPI2, ENABLE);
//I2S_Cmd(SPI3, ENABLE);
}
void SPI2_IRQHandler(void)
{
if ((SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_TXE) == SET))
{
SPI_I2S_SendData(SPI2,*(__IO uint16_t *) (musicData + i));
i+=2;
}
}
最后,没后级的带上耳机,有后级的接上喇叭,就可以开始享受了,have fun!
顶1踩
|