65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 SPI 将 VS1053 音频编码器/解码器模块与 PIC 连接

2023年5月7日

CPOL

6分钟阅读

viewsIcon

3359

如何使用 SPI 将 VS1053 音频编码器/解码器模块与 PIC 连接

为了实现我用 16 位 PIC (PIC24FJ64GA002) 构建 MP3 播放器的愿望,我从 eBay 上购买了一个 VS1053 音频编码器/解码器模块。VS1053 由 VLSI 制造,能够解码 WAV/MP3/WMA/OGG/AAC/MIDI 文件,并通过软件插件支持 FLAC 格式。它还可以通过线路输入或随附的 breakout board 上的麦克风进行音频录制。

模块引脚定义

模块的正面和背面,带有 5x2 连接器:

为了能够在面包板上进行原型开发,我使用一小块万用板为连接器制作了一个小型 breakout board。连接器引脚定义如下:

MOSI - Master Out Slave In
MISO - Master In Slave Out
SCK  - SPI Clock Signal
XCS  - Send Command (Active Low)  
XDCS - Send Data (Active Low)
XRST - Reset (Active Low)
DREQ - Data Request

该模块使用 串行外设接口 (SPI) 与微控制器通信。我使用了 此处 的代码,并对其进行了修改,以适应我的 PIC24FJ64GA002 硬件 SPI 模块。修改后的完整代码可在此处下载:此处

音频播放

VS1053 有几个寄存器控制其操作。其中,最重要的寄存器是:

SCI_MODE   - Controls the operation of the module
SCI_STATUS - Controls information on the current status of the module
SCI_BASS   - Controls the bass boosting DSP algorithm used for playback
SCI_CLOCKF - Controls the chip clock frequency
SCI_VOL    - Controls playback volume

要使用 VS1053 模块播放和录制音频文件,我将 Adafruit 的 VS1053 的 Arduino 库 转换为可以在 Microchip C30 编译器下编译。要初始化模块,请将微控制器 SPI 速度设置为 1MHz,短暂拉低 XRST 引脚执行复位,然后读取 SCI_MODE 寄存器的值,该值应包含默认值 0x4800

// primary scaler 4:1, secondary scaler 4:1 @ 1MHz
spi2Init(0b00010010);     

//Deselect Control
MP3_XCS = 1;

//Deselect Data
MP3_XDCS = 1;

// hardware reset
MP3_RESET = 0;
delay_ms(10);
MP3_RESET = 1;
delay_ms(10);

//Set initial volume (20 = -10dB)
vs1053_SetVolume(volDefault, volDefault);

//Read the SCI_MODE register
vs1053_ReadRegister(SCI_MODE);

当准备好音频播放时,写入 SCI_CLOCKF 寄存器设置倍增器并提高 VS1053 的时钟速度,然后提高 PIC SPI 时钟速度。

//increase the VS1053 internal clock multiplier and up our SPI
vs1053_WriteRegister(SCI_CLOCKF, 0x60, 0x00); //Set multiplier to 3.0x

// Internal clock multiplier is now 3x.
// Therefore, max SPI speed is 5MHz. 4MHz will be safe.
// primary scaler 1:1, secondary scaler 4:1.
SPI2CON1 = SPI2CON1 | 0b00010011;

以上代码假设 PIC 以 32MHz 运行。设置完成后,只需通过 SPI 将数据发送到模块即可播放支持的文件。

void vs1053_play(unsigned char* data, unsigned int len)
{
    unsigned char *p;
    int i;

    p = &data[0]; // Point "p" to the beginning of array
    while(p <= &data[len - 1]) {
        while(!MP3_DREQ_IN) {
            //DREQ is low while the receive buffer is full
            //You can do something else here, the bus is free...
            //Maybe set the volume or whatever...
        }

        //Once DREQ is released (high) we can now send 32 bytes of data
        MP3_XDCS = 0;     //Select Data
        spi2Write(*p++);  // Send SPI byte
        MP3_XDCS = 1;     //Deselect Data
    }

    while(!MP3_DREQ_IN) ; //Wait for DREQ to go high indicating transfer is complete
    MP3_XDCS = 1;         //Deselect Data
}

除了 PIC24 SPI 设置的一些问题外,我的完整代码首次尝试就成功了。播放的音乐非常清晰,输出电流足够大,可以通过耳机听到。使用 Microchip MDD ,我能够将 PIC 与我的 128MB SD 卡连接,并从卡上流畅地播放 WAV/MP3/WMA/OGG/AAC 文件。对于 MIDI 文件,VS1053 只支持 MIDI 类型 0(单音轨)文件。如果你的 MIDI 文件是类型 1(多音轨),你需要先将它们转换为类型 0 才能播放。你可以在此处下载许多用于测试的 MIDI 类型 0 和类型 1 文件示例:此处

根据数据手册,FLAC 文件通过加载软件插件来支持。我还没有尝试过。

意外问题:XTEST 引脚悬空!

实验过程中,我突然发现我的 VS1053 模块停止工作了。它再也无法播放任何音频文件,并且在上电时 SCI_MODE 总是读取 65424 (0xFF90),而不是默认的 0x4800。发生这种情况时,其他 SPI 读取/写入操作似乎仍然正常工作,例如写入的值仍然可以正确读回。尝试将 SCI_MODE 的默认值 0x4800 写入成功,但模块仍然无法播放任何音频数据。

我决定暂时放下开发板,断开电源,然后重试。令人惊讶的是,一切在第一次尝试时都正常工作,但仅此一次!第二次运行时,模块再次出现相同的行为(上电时 SCI_MODE0xFF90)。我用一个新的 VS1053 模块再次尝试,结果仍然只能工作一次。

究竟是什么问题?模块不可能是完全损坏的,因为 SPI 读写仍然正常工作。而且两个不同的模块以完全相同的方式损坏的可能性也很小。此时,我怀疑由于代码的某些部分不正确,可能会改变 VS1053 的非易失性存储器内容,导致永久性损坏。在网上搜索发现,其他人也有类似的间歇性行为,并怀疑 VS1053 的非易失性存储器损坏。然而,VSDSP 论坛上的帖子证实 VS1053 没有非易失性存储器,所以问题一定是电气方面的。

经过大量研究,真正的问题是 VS1053 上的 XTEST 引脚。此引脚必须连接到 VDD 才能始终正常工作。许多克隆板,包括 Sparkfun VS1053 板的早期版本以及 eBay 上销售的板子,都会将 XTEST 引脚悬空,导致行为不确定。我参考了数据手册中 XTEST 的位置,在 LQFP-48 封装中是引脚 32。

经过多次检查,我确认 XTEST 引脚确实悬空。请注意,由于 PCB 可能是多层的,你不能仅仅因为一个引脚看起来未连接就判断它悬空,因为它可能通过 PCB 的隐藏层连接。尽管引脚非常小,用普通烙铁焊接起来似乎非常困难,但我很幸运,我只需要将 XTEST 连接到 VDD,而 VDD 恰好是相邻的引脚 31 (CVDD3)。只需要在两个引脚之间滴一滴焊锡即可,修改后的板子如下(焊锡的引脚用红色标出)。

进行此修改后,板子工作良好,不再出现间歇性问题。如果你仍然遇到问题,请确保 GPIO0 和 GPIO1 引脚也连接到 GND。有些板子将 GPIO0 连接到 GND,而将 GPIO1 连接到 VDD,模块将以实时 MIDI 模式启动。

音频录制

该模块支持录制,可通过板载麦克风或线路输入。原生支持脉冲编码调制 (PCM) 编码,可以是 线性(无压缩)或 ADPCM(压缩)。通过软件插件支持 OGG 格式编码。PCM 以 16 位小端格式编码。

要进入录音模式,请设置 SCI_MODE 寄存器的 SM_ADPCMSM_RESET 位。如果通过线路输入录制,可以设置 SM_LINE1 位,否则清除它以通过麦克风录制。数据手册 第 53 页对此有详细说明。请注意,如果你通过麦克风录制,请将 SCI_AICTRL3 的位 0-1 设置为左声道模式,否则默认为立体声(两个声道),由于麦克风只提供单声道,输出音频会失真。

我尝试执行线性 PCM 录制并将数据写入 SD 卡。在 8kHz 和 16 位下,输出文件每秒消耗约 16KB。我使用 MDD 库的 FSfwrite 函数进行了基准测试,方法是打开一个文件并向其追加 0xFF。在 PIC 以 32MHz 运行时,速度约为 18KB/s。实际录制时的写入速度会更低,因为 PIC 还需要忙于与 VS1053 通信以检索音频数据。结果,录制的音频文件听起来断断续续,似乎需要进一步优化才能使录制正常工作。

由于这是一个业余项目,我决定不继续改进录制性能。在 PIC24 上使用此模块进行音频播放应该足够了。有兴趣的人可以在此处下载使用 VS1053 播放音频文件的 C30 代码:此处

另请参阅

© . All rights reserved.