当前位置: 首页 > news >正文

【毕业设计】基于的单片机的移动硬盘设计与实现 - stm32 嵌入式 物联网

文章目录

  • 0 前言
  • 1 简介
  • 2 主要器件
  • 3 实现效果
  • 4 设计原理
    • **硬件部分**
      • 软件设计
  • 5 部分核心代码
  • 5 最后


0 前言

🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

🚩 基于的单片机的移动硬盘设计与实现

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:4分
  • 工作量:4分
  • 创新点:3分

🧿 选题指导, 项目分享:

https://gitee.com/dancheng-senior/project-sharing-1/blob/master/%E6%AF%95%E8%AE%BE%E6%8C%87%E5%AF%BC/README.md


1 简介

基于stm32的嵌入式移动网盘 设计思路:使用stm32+Wi-Fi模块+SD卡,搭建一个嵌入式的迷你网盘,支持云端操作(增删改查)端侧的文件。 主要解决的问题:需要解决终端挂载的SD卡如何能被云端(公网服务器)访问,并能够支持修改。 项目创新点:借助终端外挂的大容量SD卡,基于Wi-Fi网络传输,实现网盘的功能,有望解决云服务器低成本扩容的问题。

2 主要器件

  • stm32单片机
  • RT-Thread物联网操作系统
  • TG7100C Wi-Fi模组
  • 云端简单服务器程序,用于下发对SDCARD的查看和控制;
  • Wi-Fi热点的管理连接

3 实现效果

在这里插入图片描述
在这里插入图片描述

4 设计原理

硬件部分

主要使用了stm32和一个TG7100CWi-Fi模组。

stm32主控MCU

stm32是一颗基于RISC-V的MCU,性价比非常高,不管是开发板还是芯片,都比较便宜,具体参数如下:
在这里插入图片描述

利用RT-Thread Studio(https://www.rt-thread.org/page/studio.html)进行开发。此外,需要安装Bluetrum开发板支持以及RISC-V-GCC编译器,如图:

在这里插入图片描述

stm32:充当主控,使用其SDIO接口,用于读取SD的内容。还使用其串口,用于链接Wi-Fi模组。

TG7100CWi-Fi模组

Wi-Fi模组:充当网络通讯模块,解决网络连接的问题。主要使用了其Wi-Fi功能和串口连接。

TG-12F模块采用平头哥TG7100C芯片,TG7100C 是智能新一代高集成 Wi-Fi 和 BLE 组合芯片。无线子系统包含 2.4G 射频、Wi-Fi 802.11b/g/n 和 BLE 基带/MAC 设计。微控制器子系统包含一个低功耗 32 位 RISC CPU、高速缓存和存储器。电源管理单元提供灵活的设置实现低功耗模式,并支持多种安全功能。
在这里插入图片描述

模组接线

在这里插入图片描述

TG-12F接出两个串口:一个指令串口,用于指令交互和数据传输;一个日志串口,用于输出模组运行日志。电源供电3.3V。

日志串口(uart1):gpio12(RX) gpio21(TX) 波特率:921600

AT串口(uart0): gpio7(RX) gpio16(TX) 波特率:115200

软件设计

整个演示方案,软件部分分为三大块:

1 云端的一个简单的服务器程序,用于下发对SDCARD的查看和控制;

1)识别SDCARD的挂载

2)新增命令行功能,可以下发对SDCARD的控制

3)网络报文的控制传输,命令协议的处理

2 stm32的固件程序

1)串口协议的组包、解析

2)命令行返回数据的获取以及组包发送

3)对接Wi-Fi模组,对网络连接、发送、接收、关闭的协议处理

3 Wi-Fi模组的固件程序

1)串口协议的组包、解析

2)Wi-Fi热点的管理连接

3)stm32的网络连接请求管理(串口转网络TCP、TCP转串口)

5 部分核心代码

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-01-16     takeout       the first version
 */

#include <rtthread.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <rtthread.h>
#include <rthw.h>

extern int tcp_send(uint8_t *buf_out, uint16_t len);
extern int tcp_recv(uint8_t *buf_out, uint16_t len);

int report_sdcard_name(char *name)
{
    uint8_t buf[128];

    snprintf(buf, sizeof(buf), "sdcard-name:%s", name);

    return tcp_send(buf, strlen(buf));
}

static char g_rsp_data[4096];
static int g_rsp_offset;

int hook_finsh_rsp_data(const char *fmt, ...)
{
    va_list args;
    rt_size_t length;

    va_start(args, fmt);
    length = rt_vsnprintf(&g_rsp_data[g_rsp_offset], sizeof(g_rsp_data) - 1, fmt, args);
    if (length > RT_CONSOLEBUF_SIZE - 1) {
        length = RT_CONSOLEBUF_SIZE - 1;
    }

    g_rsp_offset += length;

    va_end(args);

    return 0;
}

int excute_sdcard_opration(char *ip, char *port, char *sdcard_name)
{
    char buf[256];
    int len;
    int ret;

    tcp_sem_init();

    while (1) {

        tcp_connect(ip, port);

        report_sdcard_name(sdcard_name);

        while (1) {
            memset(buf, 0, sizeof(buf));
            ret = tcp_recv(buf, sizeof(buf));
            if (ret <= 0) {
                break;
            }
            rt_kprintf("recv %s\n", buf);

            if (!strncmp("cmd:ls", buf, 6)) {
                g_rsp_offset = 0;
                ls("/");
                //rt_kprintf("%s\n", g_rsp_data);
                tcp_send(g_rsp_data, g_rsp_offset);
            } else if (!strncmp("cmd:df", buf, 6)) {
                g_rsp_offset = 0;
                df("/");
                //rt_kprintf("%s\n", g_rsp_data);
                tcp_send(g_rsp_data, g_rsp_offset);
            }
        }

        tcp_close();
    }

    return ret;
}

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-01-15     takeout       the first version
 */

#include <rtthread.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>

// special for uart-wifi module
#define UART_WIFI_AP_CONN                   0xB0
#define UART_WIFI_AP_CONN_ACK               0xB1
#define UART_WIFI_TCP_CONN                  0xB2
#define UART_WIFI_TCP_CONN_ACK              0xB3
#define UART_WIFI_TCP_SEND                  0xB4
#define UART_WIFI_TCP_SEND_ACK              0xB5
#define UART_WIFI_TCP_RECV                  0xB6
#define UART_WIFI_TCP_RECV_ACK              0xB7
#define UART_WIFI_TCP_CLOSE                 0xB8
#define UART_WIFI_TCP_CLOSE_ACK             0xB9

extern int uart_tcp_ack_send(uint8_t cmd, uint8_t *data, uint16_t len);

static struct rt_semaphore tcp_sem;
static int g_tcp_fd;
static int g_tcp_ret;
static uint8_t *g_tcp_buf;
static int g_tcp_buf_len;

int tcp_sem_init(void)
{
    /* 初始化信号量 */
    rt_sem_init(&tcp_sem, "tcp_sem", 0, RT_IPC_FLAG_PRIO);/* 以中断接收及轮询发送模式打开串口设备 */
}

static int tcp_sem_take(uint32_t timeout_ms)
{
    int ret;
    uint32_t tick = timeout_ms / 1000 * RT_TICK_PER_SECOND; // 1tick = 1ms

    //rt_kprintf("before take\n");
    ret = rt_sem_take(&tcp_sem, tick);
    //rt_kprintf("after take\n");
    return ret;
}

static void tcp_sem_release(void)
{
    //rt_kprintf("before release\n");
    rt_sem_release(&tcp_sem);
    //rt_kprintf("after release\n");
}

int tcp_connect(const char *ip, char *port)
{
    uint8_t buf[128] = {0};
    char ip_str[16] = {0};
    char port_str[6] = {0};

    snprintf(ip_str, sizeof(ip_str), "%s", ip);
    snprintf(port_str, sizeof(port_str), "%s", port);
    memcpy(buf, ip_str, sizeof(ip_str));
    memcpy(buf + sizeof(ip_str), port_str, sizeof(port_str));
    uart_tcp_ack_send(UART_WIFI_TCP_CONN, buf, sizeof(ip_str) + sizeof(port_str));
    tcp_sem_take(60000); //10s

    rt_kprintf("%s: fd: %d\n", __func__, g_tcp_fd);

    return 0;
}

int tcp_connect_ack(uint8_t *buf, uint16_t len)
{
    if (buf[7] == 0xFF) {
        g_tcp_fd = -1;
    } else {
        g_tcp_fd = buf[7];
    }
    tcp_sem_release();
    return 0;
}

int tcp_send(uint8_t *buf_in, uint16_t len)
{
    uint8_t *buf = (uint8_t *)rt_malloc(len + 3);
    //uint8_t buf[256];

    if (g_tcp_fd < 0) {
        return -1;
    }

    buf[0] = g_tcp_fd & 0xFF;
    buf[1] = len >> 8;
    buf[2] = len & 0xFF;
    memcpy(&buf[3], buf_in, len);
    uart_tcp_ack_send(UART_WIFI_TCP_SEND, buf, len + 3);
    tcp_sem_take(30000); //10s
    rt_kprintf("%s: ret: %d\n", __func__, g_tcp_ret);
    rt_free(buf);

    return len;
}

int tcp_send_ack(uint8_t *buf, uint16_t len)
{
    g_tcp_ret = buf[7] << 8 | buf[8];
    tcp_sem_release();
    return 0;
}

int tcp_recv(uint8_t *buf_out, uint16_t len)
{
    uint8_t buf[16] = {0};

    if (g_tcp_fd < 0) {
        return -1;
    }

    buf[0] = g_tcp_fd & 0xFF; //fd
    buf[1] = len >> 8;
    buf[2] = len & 0xFF;
    g_tcp_buf = buf_out;
    uart_tcp_ack_send(UART_WIFI_TCP_RECV, buf, 3);
    tcp_sem_take(60000); //10s
    rt_kprintf("%s: ret: %d\n", __func__, g_tcp_ret);

    return g_tcp_ret;
}

int tcp_recv_ack(uint8_t *buf, uint16_t len)
{
    //rt_kprintf("len: %d\n", len);
    //hexdump("org_recv_data", buf, len);
    g_tcp_ret = buf[7] << 8 | buf[8];
    g_tcp_buf_len = len - 8 - 2;
    memcpy(g_tcp_buf, &buf[9], g_tcp_buf_len);
    hexdump("recv_data", g_tcp_buf, g_tcp_buf_len);
    tcp_sem_release();
    return 0;
}

int tcp_close(void)
{
    uint8_t buf[128] = {0};

    if (g_tcp_fd < 0) {
        return -1;
    }

    buf[0] = g_tcp_fd & 0xFF;
    uart_tcp_ack_send(UART_WIFI_TCP_CLOSE, buf, 1);
    tcp_sem_take(10000); //10s

    rt_kprintf("%s: fd: %d\n", __func__, g_tcp_fd);
    g_tcp_fd = -1;
    return 0;
}

int tcp_close_ack(uint8_t *buf, uint16_t len)
{
    g_tcp_ret = buf[7];
    tcp_sem_release();
    return 0;
}




5 最后

相关文章:

  • 使用Python的requests库发送SOAP请求,错误码415
  • Python爬虫技术系列-02HTML解析-lxml+BS4
  • 今日头条——机器学习算法岗1234面
  • 【笔记】快速理解傅里叶级数
  • 宣布发布 .NET 7 Release Candidate 1
  • 8万Star,这个开源项目有点强
  • 数据批处理速度慢?不妨试试这个
  • 透过安全事件剖析黑客组织攻击技术(2FA/MA的攻击手法)
  • java毕业设计——基于Java+AI的五子棋游戏设计与实现(毕业论文+程序源码)——五子棋游戏
  • 29、Java 中的接口详解
  • mysql中怎么防止数据丢失
  • 软件开发中会使用到的图
  • 汇编语言入门(二)
  • java中的IO流
  • 【每日一练】图解: 数组中的逆序对
  • 03Go 类型总结
  • Android单元测试 - 几个重要问题
  • Effective Java 笔记(一)
  • Gradle 5.0 正式版发布
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • java8-模拟hadoop
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • nginx 配置多 域名 + 多 https
  • Puppeteer:浏览器控制器
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 大快搜索数据爬虫技术实例安装教学篇
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 深入浅出Node.js
  • 什么是Javascript函数节流?
  • 我感觉这是史上最牛的防sql注入方法类
  • 优秀架构师必须掌握的架构思维
  • 大数据全解:定义、价值及挑战
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​香农与信息论三大定律
  • ​业务双活的数据切换思路设计(下)
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #include<初见C语言之指针(5)>
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • %check_box% in rails :coditions={:has_many , :through}
  • (2.2w字)前端单元测试之Jest详解篇
  • (8)STL算法之替换
  • (LeetCode C++)盛最多水的容器
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (转)scrum常见工具列表
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .net framework4与其client profile版本的区别
  • .net 微服务 服务保护 自动重试 Polly
  • .net/c# memcached 获取所有缓存键(keys)
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • .NET运行机制