133|2

7211

帖子

11

TA的资源

版主

楼主
 

《Hello算法》双向链表在LVGL的应用 [复制链接]

 

【前言】

经过链表的学习,有了一些了解。因此我准备在我的STM32F769上使用双向链表的实际工程应用。

【设计】

此次使用的环境为获取SD卡中的.wav文件列表。

为什么要用链表,因为我准备把SD卡的目录下的.wav文件读出来,好象在以后的播放中来进行播放当前文件,然后有后一首,前一首,到头到尾等多个操作。所以使用链表相比申请数组比较方便,当然也节约内存。

【节点的设计】

  • // 定义双向链表节点结构体
  • typedef struct WavFileNode
  • {
  • char filename[256]; // 存储文件名
  • struct WavFileNode *prev; // 指向前一个节点
  • struct WavFileNode *next; // 指向后一个节点
  • } WavFileNode;

其实这个节点还需要包文件的大小的。这次使用先从简单的做起。

然后就设计新建、追加、插入等函数,代码放在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++;
  • }
  • }

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

【应用】

我把这两个文件添加进工程中,在lvgl的工程中进行调用:

  • 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);
  • }
  • }

经过这样的设计,实现了fatfs的读取,与lvgl的代码进行解耦。

实现效果:

在打印日志中可以看到获取的文件列表:

 

在LVGL界面中也可以看到:

 

【总结】

通过对《Hell算法》的学习,我把学到的知识实现应用到了自己的MCU工程,成功的落地。

查看本帖全部内容,请登录或者注册

最新回复

学的算法拿来实用,好!   详情 回复 发表于 2 小时前
点赞 关注(1)
 
 

回复
举报

7016

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

用链表相比申请数组确实比较方便,同时也能节约内存,好

 
 
 

回复

51

帖子

3

TA的资源

一粒金砂(中级)

板凳
 

学的算法拿来实用,好!

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

猜你喜欢
随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
报名最后一周!2025 英飞凌消费、计算与通讯创新大会-北京站
会议时间:3月18日(周二)09:30签到
参会奖励:电动螺丝刀套装、户外登山包、京东卡

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表