0


基于 STM32 的 NAS私有云盘搭建:集成LwIP 协议、HTTP/HTTPS、WEB前端技术栈(代码示例)

项目概述

在本项目中,我们将搭建一个基于 STM32 的 NAS(网络附加存储)私盘,通过网络访问存储在外部 SATA 硬盘上的文件。该项目将使用 STM32 开发板、外接 SATA 硬盘、LwIP 协议栈以及 FATFS 文件系统来实现文件的上传、下载和管理,用户可以通过简单的 Web 界面进行操作。

系统设计

硬件设计

  1. STM32 开发板- 选择 STM32F407 或 STM32F746 开发板,具备足够的 RAM 和闪存以支持 NAS 功能。
  2. 存储介质- 使用外接 SATA 硬盘,通过 SATA 转 USB 适配器连接到 STM32。
  3. 网络接口- 选择以太网模块(如 W5500)或 Wi-Fi 模块(如 ESP8266)以实现网络连接。
  4. 电源管理- 确保使用的电源适配器能够满足 STM32 开发板和外接硬盘的功耗需求。

软件设计

  1. 开发环境- 使用 STM32CubeIDE 或 Keil MDK 作为开发工具。
  2. 固件库- 使用 STM32 HAL 库进行硬件抽象和操作。
  3. 文件系统- 使用 FATFS 库来管理存储设备上的文件系统,支持文件的读写、删除等操作。
  4. 网络协议- 使用 LwIP 协议栈处理 TCP/IP 网络通信。- 实现 HTTP/HTTPS 协议以支持 Web 服务器功能,支持文件的上传和下载。

配置环境

1. 安装 STM32CubeIDE

  • 下载并安装 STM32CubeIDE。
  • 按照安装向导完成安装过程。

2. 创建新项目

  1. 打开 STM32CubeIDE,选择 File -> New -> STM32 Project
  2. Board Selector 中选择您的 STM32 开发板(如 STM32F407 或 STM32F746)。
  3. 配置项目名称和存储路径,点击 Finish

3. 启用所需的中间件

  1. 在左侧的 Project Explorer 中,右键单击项目名称,选择 Properties
  2. 选择 C/C++ Build -> Settings -> Tool Settings,确保选择了适当的编译工具链。
  3. 右键单击项目,选择 Manage Embedded Software Packages,然后选择 FATFSLwIP 进行添加和配置。

4. 配置网络接口

  • 根据所选的网络模块(以太网或 Wi-Fi),在 Pinout & Configuration 视图中配置相应的引脚和设置。
  • 对于以太网模块,请确保启用以太网外设并配置 MAC 地址等参数。

5. 配置外部存储

  1. 将 SATA 硬盘连接到 STM32 开发板的 USB 接口。
  2. 在 FATFS 中配置相关参数,以确保可以识别和访问外部存储。

6. 添加库文件

  • 导入必要的库文件(如 LwIP 和 FATFS)到项目中,并确保在 main.c 或其他相应文件中包含头文件。

STM32代码实现

以下是项目的主要代码实现部分,包括网络初始化、文件操作和 HTTP 服务器的实现。

1. 初始化和网络配置

  1. #include "lwip/init.h"
  2. #include "lwip/netif.h"
  3. #include "lwip/tcpip.h"
  4. #include "ethernetif.h"
  5. void init_network(void) {
  6. lwip_init(); // 初始化 LwIP
  7. struct netif my_netif;
  8. ip_addr_t ipaddr, netmask, gw;
  9. // 设置网关和子网
  10. IP4_ADDR(&gw, 192, 168, 1, 1); // 网关
  11. IP4_ADDR(&ipaddr, 192, 168, 1, 100); // 设备 IP
  12. IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码
  13. netif_add(&my_netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input);
  14. netif_set_default(&my_netif); // 设置为默认网络接口
  15. netif_set_up(&my_netif); // 启动网络接口
  16. }

说明

  • lwip_init() 初始化 LwIP(轻量级 IP 协议栈)。
  • 使用 netif_add() 添加网络接口,并配置 IP、网关和子网掩码。
  • netif_set_up() 启动网络接口,使其可以进行通信。

2. 文件系统操作

  1. #include "ff.h" // FATFS 头文件
  2. void create_file(void) {
  3. FATFS fs; // 文件系统对象
  4. FIL fil; // 文件对象
  5. FRESULT res; // 文件操作结果
  6. char buffer[] = "Hello, STM32 NAS!";
  7. // 挂载文件系统
  8. res = f_mount(&fs, "", 1);
  9. if (res == FR_OK) {
  10. // 创建文件并写入数据
  11. res = f_open(&fil, "test.txt", FA_WRITE | FA_CREATE_ALWAYS);
  12. if (res == FR_OK) {
  13. f_write(&fil, buffer, sizeof(buffer), NULL); // 写入数据
  14. f_close(&fil); // 关闭文件
  15. }
  16. }
  17. }

说明

  • FATFS 是文件系统的结构体,FIL 是文件对象。
  • 首先调用 f_mount() 挂载文件系统,这样就可以对存储设备进行操作。
  • 使用 f_open() 创建或打开文件,并使用 f_write() 写入数据。
  • 操作完成后,调用 f_close() 关闭文件,以释放资源。

3. HTTP 服务器实现

  1. #include "httpd.h" // HTTP 服务器头文件
  2. void start_http_server(void) {
  3. httpd_init(); // 初始化 HTTP 服务器
  4. }
  5. // HTTP 请求处理示例
  6. static void handle_get_request(struct httpd_state *hs) {
  7. const char *response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello from STM32 NAS!";
  8. httpd_send(hs, response, strlen(response)); // 发送响应
  9. }

说明

  • httpd_init() 初始化 HTTP 服务器,准备接受请求。
  • 处理 GET 请求的示例函数 handle_get_request() 发送一个简单的文本响应。

4. 主函数

  1. int main(void) {
  2. // 初始化系统
  3. HAL_Init();
  4. SystemClock_Config(); // 配置系统时钟
  5. MX_GPIO_Init(); // 初始化 GPIO
  6. MX_SPI_Init(); // 初始化 SPI(用于以太网模块)
  7. MX_USB_OTG_FS_PCD_Init(); // 初始化 USB OTG(用于 SATA 硬盘)
  8. init_network(); // 初始化网络
  9. create_file(); // 创建文件
  10. start_http_server(); // 启动 HTTP 服务器
  11. while (1) {
  12. // 处理网络事件
  13. syscheck_timeouts();
  14. }
  15. }

说明

  • HAL_Init() 初始化硬件抽象层,设置基本的硬件配置。
  • SystemClock_Config() 配置系统时钟,以保证系统的正常运行。
  • 调用 init_network() 初始化网络,create_file() 创建文件,start_http_server() 启动 HTTP 服务器。
  • while (1) 循环中,不断处理网络事件,保持系统运行。

Web 前端界面交互搭建

1. 项目结构

首先,您需要创建一个简单的项目结构,用于存放前端文件。假设我们将所有的前端文件放在 STM32 的文件系统中的

  1. /www

目录下,项目结构如下:

  1. /www
  2. ├── index.html
  3. ├── style.css
  4. └── script.js

2. HTML 页面(index.html)

下面是一个简单的 HTML 页面,提供文件上传和下载的功能。

  1. <!DOCTYPE html>
  2. <html lang="zh">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>STM32 NAS 私盘</title>
  7. <link rel="stylesheet" href="style.css">
  8. </head>
  9. <body>
  10. <div class="container">
  11. <h1>STM32 NAS 私盘</h1>
  12. <div class="upload-section">
  13. <h2>上传文件</h2>
  14. <input type="file" id="fileInput">
  15. <button id="uploadButton">上传</button>
  16. </div>
  17. <div class="file-list">
  18. <h2>文件列表</h2>
  19. <ul id="fileList"></ul>
  20. </div>
  21. </div>
  22. <script src="script.js"></script>
  23. </body>
  24. </html>

3. CSS 样式(style.css)

下面是简单的 CSS 样式,用于美化前端界面。

  1. body {
  2. font-family: Arial, sans-serif;
  3. background-color: #f4f4f4;
  4. margin: 0;
  5. padding: 20px;
  6. }
  7. .container {
  8. max-width: 600px;
  9. margin: 0 auto;
  10. background: #fff;
  11. padding: 20px;
  12. border-radius: 5px;
  13. box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  14. }
  15. h1 {
  16. text-align: center;
  17. }
  18. .upload-section, .file-list {
  19. margin-bottom: 30px;
  20. }
  21. button {
  22. padding: 10px 15px;
  23. background-color: #28a745;
  24. color: white;
  25. border: none;
  26. border-radius: 5px;
  27. cursor: pointer;
  28. }
  29. button:hover {
  30. background-color: #218838;
  31. }

4. JavaScript 代码(script.js)

我们将使用 AJAX 来与 STM32 后端进行交互,实现文件上传和获取文件列表的功能。

  1. document.getElementById('uploadButton').onclick = function() {
  2. const fileInput = document.getElementById('fileInput');
  3. const file = fileInput.files[0];
  4. if (!file) {
  5. alert('请选择一个文件!');
  6. return;
  7. }
  8. const formData = new FormData();
  9. formData.append('file', file);
  10. fetch('/upload', { // 发送文件到后端
  11. method: 'POST',
  12. body: formData
  13. })
  14. .then(response => response.text())
  15. .then(data => {
  16. alert(data);
  17. loadFileList(); // 上传成功后更新文件列表
  18. })
  19. .catch(error => console.error('Error:', error));
  20. };
  21. function loadFileList() {
  22. fetch('/files') // 请求文件列表
  23. .then(response => response.json())
  24. .then(files => {
  25. const fileList = document.getElementById('fileList');
  26. fileList.innerHTML = ''; // 清空文件列表
  27. files.forEach(file => {
  28. const li = document.createElement('li');
  29. li.textContent = file;
  30. fileList.appendChild(li);
  31. });
  32. })
  33. .catch(error => console.error('Error:', error));
  34. }
  35. // 页面加载时获取文件列表
  36. window.onload = loadFileList;

5. 后端实现

为了使前端能够与后端进行交互,我们需要在 STM32 的 HTTP 服务器中处理文件上传和文件列表请求。

1. 处理文件上传的代码

  1. #include "httpd.h" // HTTP 服务器头文件
  2. #include "ff.h" // FATFS 头文件
  3. // 处理文件上传请求
  4. static void handle_file_upload(struct httpd_state *hs) {
  5. char buf[512];
  6. FIL fil;
  7. FRESULT res;
  8. char *filename = "uploaded_file.txt"; // 上传的文件名
  9. // 读取 HTTP 请求体
  10. int bytes_read = httpd_read_request_body(hs, buf, sizeof(buf));
  11. if (bytes_read > 0) {
  12. // 创建文件并写入数据
  13. res = f_open(&fil, filename, FA_WRITE | FA_CREATE_ALWAYS);
  14. if (res == FR_OK) {
  15. f_write(&fil, buf, bytes_read, NULL); // 写入文件
  16. f_close(&fil); // 关闭文件
  17. httpd_send_response(hs, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nFile uploaded successfully!"); // 响应成功
  18. } else {
  19. httpd_send_response(hs, "HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\nFailed to open file!"); // 响应失败
  20. }
  21. } else {
  22. httpd_send_response(hs, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nInvalid request body!"); // 响应无效请求
  23. }
  24. }

说明

  • 使用 httpd_read_request_body(hs, buf, sizeof(buf)) 读取 HTTP 请求体中的文件数据。
  • 使用 FATFS API f_open() 创建或打开文件,然后使用 f_write() 写入数据。
  • 根据操作结果,发送不同的 HTTP 响应。

2. 获取文件列表的代码

接下来,我们需要实现一个功能来获取当前存储设备中的所有文件。

  1. #include "ff.h" // FATFS 头文件
  2. // 处理文件列表请求
  3. static void handle_file_list(struct httpd_state *hs) {
  4. DIR dir;
  5. FILINFO fno;
  6. FRESULT res;
  7. char response[1024];
  8. int response_length = 0;
  9. // 打开目录
  10. res = f_opendir(&dir, "/"); // 假设所有文件都在根目录
  11. if (res == FR_OK) {
  12. response_length += snprintf(response + response_length, sizeof(response) - response_length, "[");
  13. while ((res = f_readdir(&dir, &fno)) == FR_OK && fno.fname[0] != 0) {
  14. if (response_length > 1) {
  15. response_length += snprintf(response + response_length, sizeof(response) - response_length, ",");
  16. }
  17. response_length += snprintf(response + response_length, sizeof(response) - response_length, "\"%s\"", fno.fname);
  18. }
  19. response_length += snprintf(response + response_length, sizeof(response) - response_length, "]");
  20. f_closedir(&dir);
  21. httpd_send_response(hs, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n");
  22. httpd_send_response(hs, response); // 发送文件列表
  23. } else {
  24. httpd_send_response(hs, "HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\nFailed to open directory!"); // 响应失败
  25. }
  26. }

说明

  • 使用 f_opendir() 打开根目录,使用 f_readdir() 读取目录中的文件。
  • 将文件名格式化为 JSON 格式的字符串,返回给前端。
  • 发送 HTTP 响应,内容类型为 application/json

3. 绑定 HTTP 请求处理

在 HTTP 服务器初始化时,我们需要将上传和文件列表请求的处理函数绑定到相应的 URL。

  1. void start_http_server(void) {
  2. httpd_init(); // 初始化 HTTP 服务器
  3. // 绑定请求处理函数
  4. httpd_register_uri("/upload", handle_file_upload, HTTP_POST); // 处理文件上传
  5. httpd_register_uri("/files", handle_file_list, HTTP_GET); // 获取文件列表
  6. }

说明

  • httpd_register_uri() 函数用于将请求 URL 与处理函数进行绑定。
  • /upload URL 用于处理文件上传请求,/files URL 用于获取文件列表。

项目总结

在本项目中,我们成功地搭建了一个基于 STM32 的 NAS(网络附加存储)私盘,利用 STM32 开发板的强大功能和灵活性,结合 LwIP 协议栈和 FATFS 文件系统,实现了文件的上传、下载和管理。以下是本项目的关键要点和收获:

1. 硬件与软件的结合

通过选择适合的 STM32 开发板(如 STM32F407 或 STM32F746),并配合外部 SATA 硬盘和网络模块(如以太网或 Wi-Fi),我们有效地创建了一个功能强大的 NAS 解决方案。硬件部分的选择对于系统的稳定性和性能至关重要,而软件部分则利用了 STM32 HAL 库、FATFS 文件系统和 LwIP 协议栈,使得硬件功能得以充分发挥。

2. 文件管理功能

我们成功实现了基本的文件管理功能,包括文件的上传、下载和列表展示。通过使用 FATFS 库,我们能够方便地对外接存储进行文件操作,这为用户在 NAS 上进行文件管理提供了便利。

3. Web 前端交互

通过搭建简单的 Web 前端界面,用户能够直观地与 NAS 进行交互。使用 HTML、CSS 和 JavaScript,我们实现了文件上传和文件列表展示功能,使得用户在浏览器中就可以方便地操作存储在 STM32 上的文件。此外,利用 AJAX 技术,我们实现了无刷新数据交互,提升了用户体验。

4. 网络通信实现

使用 LwIP 协议栈,我们为 STM32 开发板实现了网络通信功能。通过 HTTP 协议,前端与后端的交互得以顺利进行。我们实现了对文件上传和文件列表请求的处理,使得用户能够通过网络访问 NAS 中的文件。


本文转载自: https://blog.csdn.net/qq_40431685/article/details/140827140
版权归原作者 极客小张 所有, 如有侵权,请联系我们删除。

“基于 STM32 的 NAS私有云盘搭建:集成LwIP 协议、HTTP/HTTPS、WEB前端技术栈(代码示例)”的评论:

还没有评论