帮忙写一个stm32 使用IIS接口DMA方式驱动VS1053的完整代码
时间: 2023-12-10 18:40:17 浏览: 525
好的,以下是一个使用STM32的IIS接口和DMA方式驱动VS1053的完整代码:
```
#include "stm32f10x.h"
// 定义VS1053的控制寄存器地址
#define SCI_MODE 0x0
#define SCI_STATUS 0x1
#define SCI_BASS 0x2
#define SCI_CLOCKF 0x3
#define SCI_DECODE_TIME 0x4
#define SCI_AUDATA 0x5
#define SCI_WRAM 0x6
#define SCI_WRAMADDR 0x7
#define SCI_HDAT0 0x8
#define SCI_HDAT1 0x9
#define SCI_AIADDR 0xa
#define SCI_VOL 0xb
#define SCI_AICTRL0 0xc
#define SCI_AICTRL1 0xd
#define SCI_AICTRL2 0xe
#define SCI_AICTRL3 0xf
// 定义VS1053的模式寄存器中的位掩码
#define SM_DIFF 0x01
#define SM_LAYER12 0x02
#define SM_RESET 0x04
#define SM_OUTOFWAV 0x08
#define SM_EARSPEAKER_LO 0x10
#define SM_TESTS 0x20
#define SM_STREAM 0x40
#define SM_EARSPEAKER_HI 0x80
#define SM_DACT 0x100
#define SM_SDIORD 0x200
#define SM_SDISHARE 0x400
#define SM_SDINEW 0x800
#define SM_ADPCM 0x1000
#define SM_LINE1 0x4000
#define SM_CLK_RANGE 0x8000
// 定义VS1053的状态寄存器中的位掩码
#define SS_VER 0xf000
#define SS_APDOWN 0x0800
#define SS_VCM_OVER 0x0400
#define SS_VER_MINOR 0x00f0
#define SS_VER_MAJOR 0x000f
// 定义VS1053的启动时序
const uint16_t vs1053_startup[] = {0x0000, 0x9800, 0x44, 0x8020, 0x1804, 0x0000, 0x0000};
// 定义音频数据缓冲区
#define AUDIO_BUFFER_SIZE 4096
volatile uint16_t audio_buffer[AUDIO_BUFFER_SIZE];
volatile uint16_t audio_buffer_read_index = 0;
volatile uint16_t audio_buffer_write_index = 0;
// 配置I2S接口
void config_i2s(void) {
// 配置GPIO口复用
GPIO_InitTypeDef gpio_init;
gpio_init.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &gpio_init);
// 配置SPI接口
SPI_InitTypeDef spi_init;
spi_init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
spi_init.SPI_Mode = SPI_Mode_Master;
spi_init.SPI_DataSize = SPI_DataSize_16b;
spi_init.SPI_CPOL = SPI_CPOL_Low;
spi_init.SPI_CPHA = SPI_CPHA_1Edge;
spi_init.SPI_NSS = SPI_NSS_Soft;
spi_init.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
spi_init.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI1, &spi_init);
// 启用SPI
SPI_Cmd(SPI1, ENABLE);
// 配置I2S接口
I2S_InitTypeDef i2s_init;
i2s_init.I2S_Mode = I2S_Mode_MasterTx;
i2s_init.I2S_Standard = I2S_Standard_Phillips;
i2s_init.I2S_DataFormat = I2S_DataFormat_16b;
i2s_init.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
i2s_init.I2S_AudioFreq = I2S_AudioFreq_44k;
i2s_init.I2S_CPOL = I2S_CPOL_Low;
I2S_Init(SPI1, &i2s_init);
// 启用I2S
I2S_Cmd(SPI1, ENABLE);
}
// 配置DMA通道
void config_dma(void) {
// 配置DMA通道
DMA_InitTypeDef dma_init;
dma_init.DMA_PeripheralBaseAddr = (uint32_t) & (SPI1->DR);
dma_init.DMA_MemoryBaseAddr = (uint32_t) &audio_buffer[0];
dma_init.DMA_DIR = DMA_DIR_PeripheralDST;
dma_init.DMA_BufferSize = AUDIO_BUFFER_SIZE;
dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dma_init.DMA_Mode = DMA_Mode_Circular;
dma_init.DMA_Priority = DMA_Priority_High;
dma_init.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &dma_init);
// 配置DMA中断
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = DMA1_Channel3_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 0;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
// 启用DMA通道和中断
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel3, ENABLE);
}
// 配置VS1053
void config_vs1053(void) {
// 等待VS1053启动完成
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2) == Bit_RESET);
// 发送启动时序
for (int i = 0; i < sizeof(vs1053_startup) / sizeof(vs1053_startup[0]); i++) {
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, vs1053_startup[i]);
}
// 等待启动时序发送完毕
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
// 将模式寄存器设置为默认值
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, SCI_MODE);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, SM_LINE1 | SM_SDINEW | SM_ADPCM | SM_TESTS);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
// 将音量设置为默认值
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, SCI_VOL);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, 100);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, 100);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
// 将数据寄存器设置为音频数据寄存器
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, SCI_WRAMADDR);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, 0xc017);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
}
// 向VS1053发送命令
void send_vs1053_command(uint8_t address, uint16_t data) {
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, address);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, data >> 8);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, data & 0xff);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
}
// DMA中断处理函数
void DMA1_Channel3_IRQHandler(void) {
if (DMA_GetITStatus(DMA1_IT_TC3) != RESET) {
// 读取音频数据缓冲区中的数据
uint16_t audio_data = audio_buffer[audio_buffer_read_index];
audio_buffer_read_index = (audio_buffer_read_index + 1) % AUDIO_BUFFER_SIZE;
// 将音频数据写入I2S接口
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, audio_data);
// 清除DMA传输完成中断标志
DMA_ClearITPendingBit(DMA1_IT_TC3);
}
}
int main(void) {
// 启用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 配置I2S接口和DMA通道
config_i2s();
config_dma();
// 配置VS1053
config_vs1053();
// 播放音频
while (1) {
// 从音频文件中读取音频数据
uint16_t audio_data = read_audio_data();
// 将音频数据存入缓冲区
audio_buffer[audio_buffer_write_index] = audio_data;
audio_buffer_write_index = (audio_buffer_write_index + 1) % AUDIO_BUFFER_SIZE;
}
}
```
请注意,这只是一个示例代码,你需要根据你的具体硬件和要求进行调整和修改。
阅读全文