STM32实现简单的音乐播放器

以下是一个使用STM32实现简单的音乐播放器的案例代码:

案例代码中,我们使用了STM32F4 Discovery开发板和SD卡模块。音乐文件以WAV格式存储在SD卡中。主要的功能包括初始化SD卡、读取音乐文件、配置音频输出、播放音乐。

#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
#include <string.h>

/* SD Card Definitions */
#define SD_SPI                   SPI1
#define SD_SPI_CLK               RCC_APB2Periph_SPI1
#define SD_SPI_SCK_PIN           GPIO_Pin_5
#define SD_SPI_SCK_GPIO_PORT     GPIOA
#define SD_SPI_SCK_GPIO_CLK      RCC_AHB1Periph_GPIOA
#define SD_SPI_MISO_PIN          GPIO_Pin_6
#define SD_SPI_MISO_GPIO_PORT    GPIOA
#define SD_SPI_MISO_GPIO_CLK     RCC_AHB1Periph_GPIOA
#define SD_SPI_MOSI_PIN          GPIO_Pin_7
#define SD_SPI_MOSI_GPIO_PORT    GPIOA
#define SD_SPI_MOSI_GPIO_CLK     RCC_AHB1Periph_GPIOA
#define SD_CS_PIN                GPIO_Pin_3
#define SD_CS_GPIO_PORT          GPIOD
#define SD_CS_GPIO_CLK           RCC_AHB1Periph_GPIOD

/* Audio Definitions */
#define AUDIO_CODEC_I2C          I2C1
#define AUDIO_I2C_CLK            RCC_APB1Periph_I2C1
#define AUDIO_I2S                SPI2
#define AUDIO_I2S_CLK            RCC_APB1Periph_SPI2
#define AUDIO_I2S_WS_PIN         GPIO_Pin_4
#define AUDIO_I2S_WS_GPIO_PORT   GPIOB
#define AUDIO_I2S_WS_GPIO_CLK    RCC_AHB1Periph_GPIOB
#define AUDIO_I2S_SCK_PIN        GPIO_Pin_10
#define AUDIO_I2S_SCK_GPIO_PORT  GPIOB
#define AUDIO_I2S_SCK_GPIO_CLK   RCC_AHB1Periph_GPIOB
#define AUDIO_I2S_SD_PIN         GPIO_Pin_15
#define AUDIO_I2S_SD_GPIO_PORT   GPIOB
#define AUDIO_I2S_SD_GPIO_CLK    RCC_AHB1Periph_GPIOB
#define AUDIO_I2S_MCK_PIN        GPIO_Pin_6
#define AUDIO_I2S_MCK_GPIO_PORT  GPIOD
#define AUDIO_I2S_MCK_GPIO_CLK   RCC_AHB1Periph_GPIOD
#define AUDIO_I2S_DMA_STREAM     DMA1_Stream5
#define AUDIO_I2S_DMA_CHANNEL    DMA_Channel_0
#define AUDIO_I2S_DMA_IRQ        DMA1_Stream5_IRQn
#define AUDIO_I2S_DMA_FLAG       DMA_FLAG_TCIF5

/* WAV File Definitions */
#define CHUNK_ID        0x46464952 // "RIFF"
#define FORMAT          0x45564157 // "WAVE"
#define SUBCHUNK1_ID    0x20746D66 // "fmt "
#define SUBCHUNK2_ID    0x61746164 // "data"

/* Function Prototypes */
void SD_Init(void);
void SD_WriteByte(uint8_t byte);
uint8_t SD_ReadByte(void);
void SD_WriteCmd(uint8_t cmd, uint32_t arg);
uint8_t SD_ReadData(void);
void SD_ReadDataBlock(uint8_t* buffer, uint32_t size);
uint8_t SD_InitCard(void);
uint8_t SD_InitSDIO(void);
uint8_t SD_InitCardIdentify(void);
uint8_t SD_InitCardSetBusWidth(void);
uint8_t SD_ReadSingleBlock(uint32_t sector, uint8_t* buffer);
void SD_ReadWavHeader(uint8_t* buffer, uint32_t* dataStart, uint32_t* dataSize, uint32_t* sampleRate);
void SD_PlayMusic(void);
void SD_PlaySample(uint32_t sampleRate);

void Audio_Init(void);
void Audio_PlaySample(uint32_t sampleRate);

/* Global Variables */
volatile uint8_t SD_Initialized = 0;
volatile uint8_t SDIO_Initialized = 0;
volatile uint8_t SD_CardType = 0;
volatile uint32_t SD_CardCapacity = 0;

int main(void)
{
    /* Initialize SD Card */
    SD_Init();

    /* Initialize Audio Codec */
    Audio_Init();

    /* Play Music */
    SD_PlayMusic();

    while (1) {
        /* Do Nothing */
    }
}

void SD_Init(void)
{
    /* Enable GPIO Clocks */
    RCC_AHB1PeriphClockCmd(SD_SPI_SCK_GPIO_CLK | SD_SPI_MISO_GPIO_CLK |
                           SD_SPI_MOSI_GPIO_CLK | SD_CS_GPIO_CLK, ENABLE);

    /* Enable SPI Clock */
    RCC_APB2PeriphClockCmd(SD_SPI_CLK, ENABLE);

    /* Configure SPI Pins */
    GPIO_PinAFConfig(SD_SPI_SCK_GPIO_PORT, SD_SPI_SCK_SOURCE, SD_SPI_SCK_AF);
    GPIO_PinAFConfig(SD_SPI_MISO_GPIO_PORT, SD_SPI_MISO_SOURCE, SD_SPI_MISO_AF);
    GPIO_PinAFConfig(SD_SPI_MOSI_GPIO_PORT, SD_SPI_MOSI_SOURCE, SD_SPI_MOSI_AF);

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = SD_SPI_SCK_PIN | SD_SPI_MISO_PIN | SD_SPI_SCK_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure CS Pin */
    GPIO_InitStructure.GPIO_Pin = SD_CS_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_Init(SD_CS_GPIO_PORT, &GPIO_InitStructure);
    SD_CS_HIGH();

    /* Configure SPI */
    SPI_InitTypeDef SPI_InitStructure;
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SD_SPI, &SPI_InitStructure);

    /* Enable SPI */
    SPI_Cmd(SD_SPI, ENABLE);

    /* Initialize SD Card */
    SD_Initialized = SD_InitCard();
}

void SD_WriteByte(uint8_t byte)
{
    /* Wait for SPI to be ready */
    while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_TXE) == RESET);

    /* Send Byte */
    SPI_I2S_SendData(SD_SPI, byte);

    /* Wait for SPI to finish operation */
    while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET);
}

uint8_t SD_ReadByte(void)
{
    /* Wait for SPI to be ready */
    while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_TXE) == RESET);

    /* Send Dummy Byte */
    SPI_I2S_SendData(SD_SPI, 0xFF);

    /* Wait for SPI to finish operation */
    while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET);

    /* Return Read Byte */
    return (uint8_t)SPI_I2S_ReceiveData(SD_SPI);
}

void SD_WriteCmd(uint8_t cmd, uint32_t arg)
{
    /* Send CMD Header */
    SD_WriteByte(0x40 | cmd);
    SD_WriteByte(arg >> 24);
    SD_WriteByte(arg >> 16);
    SD_WriteByte(arg >> 8);
    SD_WriteByte(arg);
    SD_WriteByte(0x95);
}

uint8_t SD_ReadData(void)
{
    /* Wait for correct start byte */
    while (SD_ReadByte() != 0xFE);

    /* Read Data Byte */
    return SD_ReadByte();
}

void SD_ReadDataBlock(uint8_t* buffer, uint32_t size)
{
    /* Read Data */
    for (uint32_t i = 0; i < size; i++) {
        buffer[i] = SD_ReadData();
    }
}

uint8_t SD_InitCard(void)
{
    /* Set SPI Speed to 400kHz */
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_Init(SD_SPI, &SPI_InitStructure);

    /* Set CS Low */
    SD_CS_LOW();

    /* Send CMD0 - Reset */
    SD_WriteCmd(0, 0);

    /* Wait for SD Card to initialize */
    uint32_t timeout = 0xFFFF;
    while ((SD_ReadByte() != 0x01) && timeout) {
        timeout--;
    }

    /* Set CS High */
    SD_CS_HIGH();

    /* Return Initialization Status */
    return (timeout) ? 1 : 0;
}

void SD_ReadWavHeader(uint8_t* buffer, uint32_t* dataStart, uint32_t* dataSize, uint32_t* sampleRate)
{
    /* Check RIFF and WAVE Tags */
    if ((*(uint32_t*)(buffer + 0) == CHUNK_ID) && (*(uint32_t*)(buffer + 8) == FORMAT)) {
        /* Check Format Tag */
        if (*(uint16_t*)(buffer + 20) == 1) {
            /* Get Sample Rate */

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值