你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32F769】读取音乐列表

[复制链接]
lugl 发布时间:2025-3-16 19:36

前面,我分享了有关GUI相关的LVGL文章:

【STM32F769I-DISC1】移植LVGL - ST中文论坛活动 ST意法半导体中文论坛

以及FatFs文件系统的文章:

【STM32F769I-DISC1】移植基于FreeRTOS的FATFS - ST中文论坛活动 ST意法半导体中文论坛

现在就结合LVGL+FatFs进行了SD卡中的音乐.wav的读取,并将文件列表存入双向链表中,同时也可以显示到界面中。

【工程结合】

我把两个帖子的代码进行了整合。

image.png

【界面设计】

image.png

【文件列表保存】

我使用双向链表来进行管理,这样就一次获取,之后就只需要对链表进行访问,通过文件名再对SD卡进行读取。

【主要代码】

节点设计:

typedef struct WavFileNode
{
    char filename[256];       // 存储文件名
    struct WavFileNode *prev; // 指向前一个节点
    struct WavFileNode *next; // 指向后一个节点
} WavFileNode;

创建节点:

WavFileNode *createNode(const char *filename)
{
    WavFileNode *newNode = (WavFileNode *)malloc(sizeof(WavFileNode));
    if (newNode == NULL)
    {
        printf("内存分配失败\n");
        return NULL;
    }
    sprintf(newNode->filename, "%s", filename); // 修正拼写错误
    newNode->prev = NULL;
    newNode->next = NULL;
    return newNode;
}

整体源代码我放到回复里。

接下来给lvgl的button编写click事件与文件读取:

image.png

【实现效】

我点击Getfile后即可把SD卡下面的文件读取到界面上:

image.png

【小结】

通过fatfs,可以实现对SD卡的文件读取,下一步将设计音频输出,最终实现一个音乐播放器。

收藏 评论3 发布时间:2025-3-16 19:36

举报

3个回答
lugl 回答时间:2025-3-16 19:37:27

代码read_wav_filename.c:

#include "ff.h"
#include <stdio.h>
#include <stdlib.h>
#include "read_wav_filename.h"
#include <stdbool.h>
WavFileNode *fileList = NULL;
// 创建新节点
WavFileNode *createNode(const char *filename)
{
    WavFileNode *newNode = (WavFileNode *)malloc(sizeof(WavFileNode));
    if (newNode == NULL)
    {
        printf("内存分配失败\n");
        return NULL;
    }
    sprintf(newNode->filename, "%s", filename); // 修正拼写错误
    newNode->prev = NULL;
    newNode->next = NULL;
    return newNode;
}

// 在链表末尾添加新节点
void appendNode(WavFileNode **head, const char *filename)
{
    WavFileNode *newNode = createNode(filename);
    if (*head == NULL)
    {
        *head = newNode;
    }
    else
    {
        WavFileNode *temp = *head;
        while (temp->next != NULL)
        {
            temp = temp->next;
        }
        temp->next = newNode;
        newNode->prev = temp;
    }
}

// 释放双向链表内存
void freeList(WavFileNode *head)
{
    WavFileNode *temp = head;
    while (temp != NULL)
    {
        WavFileNode *next = temp->next;
        free(temp);
        temp = next;
    }
}

// 获取双向链表的尾节点
WavFileNode *getTailNode(WavFileNode *head)
{
    WavFileNode *temp = head;
    while (temp != NULL && temp->next != NULL)
    {
        temp = temp->next;
    }
    return temp;
}

// 获取双向链表的头节点
WavFileNode *getHeadNode(WavFileNode *head)
{
    WavFileNode *temp = head;
    while (temp != NULL && temp->prev != NULL)
    {
        temp = temp->prev;
    }
    return temp;
}

// 读取文件夹中的.wav文件并存储到双向链表中

void readWavFiles(const char *folderPath, WavFileNode **head)
{
    DIR dir;
    FILINFO fileInfo;
    FRESULT res = f_opendir(&dir, folderPath);
    if (res != FR_OK)
    {
        printf("无法打开文件夹\n");
        return;
    }
    while (1)
    {
        res = f_readdir(&dir, &fileInfo);
        if (res != FR_OK || fileInfo.fname[0] == 0)
        {
            break;
        }
        if (fileInfo.fattrib & AM_DIR)
        {
            // 如果是文件夹,则递归读取子文件夹
            continue;
        }
        else
        {
            // 如果是文件,则判断是否为.wav文件
            if (strstr(fileInfo.fname, ".wav") != NULL  && fileInfo.fname[0] != 0)
            {
                // 如果是.wav文件,则将文件名存储到双向链表中
                appendNode(head, fileInfo.fname);
            }
        }
    }
    f_closedir(&dir);
}

// 返回下一个.wav文件名
const char *getNextWavFilename(WavFileNode **head)
{
    WavFileNode *temp = *head;
    if (temp == NULL)
    {
        return NULL;
    }
    const char *filename = temp->filename;
    *head = temp->next;
    free(temp);
    return filename;
}

// 判断WavFileNode链表是否为空
bool isWavFileListEmpty(WavFileNode *head)
{
    return head == NULL;
}

// 打印WavFileNode链表中的文件名
void printWavFileList(WavFileNode *head)
{
    uint8_t count = 0;
    WavFileNode *temp = head;
    while (temp!= NULL)
    {
        printf("count:%d: %s\n", count, temp->filename);
        temp = temp->next;
        count++;
    }
}
lugl 回答时间:2025-3-16 19:38:00

read_wav_filename.h:

#ifndef READ_WAV_FILENAME_H
#define READ_WAV_FILENAME_H

#include "ff.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 定义双向链表节点结构体
typedef struct WavFileNode
{
    char filename[256];       // 存储文件名
    struct WavFileNode *prev; // 指向前一个节点
    struct WavFileNode *next; // 指向后一个节点
} WavFileNode;

// 声明函数原型
WavFileNode *createNode(const char *filename);
void appendNode(WavFileNode **head, const char *filename);
void freeList(WavFileNode *head);
WavFileNode *getTailNode(WavFileNode *head);
WavFileNode *getHeadNode(WavFileNode *head);
void readWavFiles(const char *folderPath, WavFileNode **head);
const char *getNextWavFilename(WavFileNode **head);
bool isWavFileListEmpty(WavFileNode *head);
void printWavFileList(WavFileNode *head);
#endif // READ_WAV_FILENAME_H
lugl 回答时间:2025-3-16 19:38:33

lvgl代码:




/*********************
 *      INCLUDES
 *********************/
#include <stdio.h>
#include "lvgl.h"
#include "custom.h"
#include <string.h>
/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/

/**********************
 *  STATIC VARIABLES
 **********************/
#include <stdio.h>
#include "file_opera.h"
#include "fatfs.h"
#include <stdio.h>
#include "ff.h"
#include "stdlib.h"
#include "read_wav_filename.h"
/**
 * Create a demo application
 */
extern WavFileNode *fileList ;
void get_wave_file(lv_ui *ui)
{
    static get_state_flag = 0;
    if (get_state_flag == 0)
    {
        get_state_flag = 1;
        readWavFiles("/", &fileList);
    }

    printWavFileList(fileList);
    if (isWavFileListEmpty(fileList))
    {
        printf("No WAV files found.\n");
    }
    else
    {
        char buff[1024] = {0};
        //取取flist中的所有文件名
        WavFileNode *current = fileList;
        while (current != NULL)
        {
            // 使用 snprintf 来拼接文件名,确保不会超出缓冲区大小
            int remaining_space = sizeof(buff) - strlen(buff);
            if (remaining_space > 0)
            {
                snprintf(buff + strlen(buff), remaining_space, "%s\n", current->filename);
            }
            else
            {
                printf("Buffer is full, cannot add more filenames.\n");
                break;
            }
            current = current->next;
        }
        lv_span_set_text(ui->screen_spangroup_1_span, (const char *)buff);
    }

}
static void screen_btn_1_event_handler(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    //获取事件发生的ui对象
    lv_ui *ui = lv_event_get_user_data(e);
    switch (code)
    {
    case LV_EVENT_CLICKED:
    {
        printf("screen_btn_1 clicked\n");
        get_wave_file(ui);
        break;
    }
    default:
        break;
    }
}

void custom_init(lv_ui *ui)
{
    lv_obj_add_event_cb(ui->screen_btn_1, screen_btn_1_event_handler, LV_EVENT_ALL, ui);
    /* Add your codes here */
}

所属标签

ST中文论坛活动

即日起开启活动话题入口,之后的活动统一都放在此处,欢迎大家的加入!


最新内容

相似分享

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版