STM32F103C8用内部Flash做一个优盘(USB+MSC+FATFS)

2023-11-03

STM32F103C8用内部Flash做一个优盘(USB+MSC+FATFS),轻松实现APP升级、数据存储。

基本工程生成

直接使用STM32CubeMX生成基本的工程,省得我们去调底层。

时钟配置为外部8MHz晶振,这个需要根据自己开发板的晶振选择。 

启用SWD下载和滴答定时器

 启用USB

 启用FATFS,MAX_SS和MIN_SS设置为1024。

 配置USB的功能,MSC_MEDIA_PACKET这里也要配置为1024,和FATFS一致。

配置时钟树

配置堆栈

至此可以生成工程了,生成工程我选择MDK。

USB MSC功能实现和FATFS加入

主要是实现U盘功能和将USB和FATFS连接起来。

USB MSC功能实现

这里用STM32F103C8后面的64K Flash来充当U盘的存储区。这里需要修改usbd_storage_if.c文件的3个地方。什么?你还不知道STM32F103C8T6有128K flash?

涉及的宏:

#define     FLASH_SIZE                  128
#define     FMC_SECTOR_SIZE             1024
#define     FLASH_PAGE_NBR              64
#define     FLASH_START_ADDR        	(0x08000000+((FLASH_SIZE-FLASH_PAGE_NBR)*1024))

修改1:修改STORAGE_GetCapacity_FS函数,获取容量函数。FLASH_PAGE_NBR是存储器的大小,这里我们设置64K,FLASH_PAGE_SIZE是页大小,需要设置0x400,也就是1024和MSC_MEDIA_PACKET设置一致。

int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
  /* USER CODE BEGIN 3 */
  *block_num  = FLASH_PAGE_NBR;
  *block_size = FLASH_PAGE_SIZE;
  return (USBD_OK);
  /* USER CODE END 3 */
}

修改2:修改STORAGE_Read_FS函数,实现U盘读取功能。

int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */
	if(lun == 0)
	{
        memcpy(buf,(uint8_t *)(FLASH_START_ADDR + blk_addr*FLASH_PAGE_SIZE),blk_len*FLASH_PAGE_SIZE);
        return USBD_OK;
    }
    return USBD_FAIL;
  /* USER CODE END 6 */
}

修改3:修改STORAGE_Write_FS函数,实现U盘写功能。

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */
    uint16_t i;
    uint32_t PageError = 0;
    FLASH_EraseInitTypeDef Flash;
    if(lun == 0)
    {
		HAL_FLASH_Unlock();
		Flash.TypeErase = FLASH_TYPEERASE_PAGES;
		Flash.PageAddress = FLASH_START_ADDR + blk_addr*FLASH_PAGE_SIZE ;
		Flash.NbPages = blk_len;
		HAL_FLASHEx_Erase(&Flash, &PageError);
		for(i=0;i<blk_len*FLASH_PAGE_SIZE;i+=4)
		{
            HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,FLASH_START_ADDR + blk_addr*FLASH_PAGE_SIZE + i , *(uint32_t *)(&buf[i]));
        }
		HAL_FLASH_Lock();
		return USBD_OK;
    }
    return USBD_FAIL;
  /* USER CODE END 7 */
}

加入FATFS

这里是实现FATFS读写存储区。主要修改user_diskio.c文件的4个地方。和main.c文件的1个地方。

修改1:修改USER_status函数。

DSTATUS USER_status (
	BYTE pdrv       /* Physical drive number to identify the drive */
)
{
  /* USER CODE BEGIN STATUS */
    Stat = STA_NOINIT;
    Stat &= ~STA_NOINIT;
    return Stat;
  /* USER CODE END STATUS */
}

修改2:修改USER_read函数,实现FATAFS读取功能。

DRESULT USER_read (
	BYTE pdrv,      /* Physical drive nmuber to identify the drive */
	BYTE *buff,     /* Data buffer to store read data */
	DWORD sector,   /* Sector address in LBA */
	UINT count      /* Number of sectors to read */
)
{
  /* USER CODE BEGIN READ */
	uint8_t *s = (uint8_t *)(FLASH_START_ADDR);  
	s+=(sector*FMC_SECTOR_SIZE);
	for(int i=0; i<count*FMC_SECTOR_SIZE ;i++)
	{
		*(buff++) = *(s++ );
	}
    return RES_OK;
  /* USER CODE END READ */
}

修改3:修改USER_write函数,实现FATAFS写功能。

DRESULT USER_write (
	BYTE pdrv,          /* Physical drive nmuber to identify the drive */
	const BYTE *buff,   /* Data to be written */
	DWORD sector,       /* Sector address in LBA */
	UINT count          /* Number of sectors to write */
)
{
  /* USER CODE BEGIN WRITE */
  /* USER CODE HERE */
    uint16_t i;	
    HAL_FLASH_Unlock();
	 
    FLASH_EraseInitTypeDef f;
    f.TypeErase = FLASH_TYPEERASE_PAGES;
    f.PageAddress = FLASH_START_ADDR + sector*FLASH_PAGE_SIZE ;
    f.NbPages = count;
    uint32_t PageError = 0;
    HAL_FLASHEx_Erase(&f, &PageError);
 
    for(i=0;i<count*FLASH_PAGE_SIZE;i+=4)
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,FLASH_START_ADDR + sector*FLASH_PAGE_SIZE + i , *(uint32_t *)(&buff[i]));
 
    HAL_FLASH_Lock();
    return RES_OK;
  /* USER CODE END WRITE */
}

修改4:修改USER_ioctl函数,实现FATAFS I/O控制操作。

DRESULT USER_ioctl (
	BYTE pdrv,      /* Physical drive nmuber (0..) */
	BYTE cmd,       /* Control code */
	void *buff      /* Buffer to send/receive control data */
)
{
  /* USER CODE BEGIN IOCTL */
    DRESULT res = RES_ERROR;
  switch(cmd)
  {
    case CTRL_SYNC :
			res = RES_OK;
        break;	
 
    case CTRL_TRIM:
			res = RES_OK;
        break;
		
    case GET_BLOCK_SIZE:
	*(DWORD*)buff = 1; 
	break;
		
    case GET_SECTOR_SIZE:
	*(DWORD*)buff = FMC_SECTOR_SIZE;
        break;
		
    case GET_SECTOR_COUNT:
	*(DWORD*)buff =  FLASH_PAGE_NBR;
	break;
			
    default:
	res = RES_PARERR;
	break;
    }
    return res;
  /* USER CODE END IOCTL */
}

修改5:调用/使用FATFS。

int main(void)
{
  /* USER CODE BEGIN 1 */

    char path[4]= {"0:"};
    FRESULT FATFS_Status;	
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_FATFS_Init();
  MX_USB_DEVICE_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

    FATFS_Status = f_mount(&USERFatFS, path, 1);
    f_mkdir("0:/FW");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

烧录固件,连接数据线。在电脑手动格式化U盘。也可以在代码检测存储区是否格式化然后调用格式化。我这里就不写了。

 新建文件夹成功:

代码可以按上面的步骤实现。也可以从Gitee仓库下载:传送门

其他型号的STM32可以可以参考。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F103C8用内部Flash做一个优盘(USB+MSC+FATFS) 的相关文章

  • 今日分享积累的5个AI绘画网站,好用且免费

    AI绘画即基于人工智能的绘画技术 让设计师能够以全新的方式创作出惊人的艺术作品 而随着AI绘画技术的发展 市面上也多了很多能免费使用的AI绘画网站 可以为我们提供更多的绘画灵感和创作可能性 接下来我将为大家推荐5个能免费使用的AI绘画网站
  • ngrok搭建服务器(超级详细)

    前言 我一直都在usr local文件下操作 有不懂的同学给我留言 我没有修改源码 只是测试能否生成服务端文件 有需要的同学可以修改源码 使用 ip 做域名时 随机生成的子域名导致地址错误解决办法就是改源码 去掉随机生成 在ngrok目录下
  • WAIC2023:图像内容安全黑科技助力可信AI发展

    目录 0 写在前面 1 AI图像篡改检测 2 生成式图像鉴别 2 1 主干特征提取通道 2 2 注意力模块 2 3 纹理增强模块 3 OCR对抗攻击 4 助力可信AI向善发展 总结 0 写在前面 2023世界人工智能大会 WAIC 已圆满结

随机推荐

  • python insert插入新一列

    mydata insert 1 date data 日期 mydata 原有数据 1 插入第几列 data 插入列名 data 日期 插入列内容 原有数据插入一列 mydata insert 1 date data 日期 mydata 原有
  • 快速构建Kubesphere 3.0并设置Kubesphere 多集群联邦

    这里我们Host选择使用单节点All in One安装模式 可以零配置快速部署 KubeSphere和Kubernetes 我们安装联邦集群需要有一台节点进行管理 Member需要在Kubernetes中安装Kubesphere当作Memb
  • 目标检测pytorch版yolov3五——解码过程和可视化以及predict预测过程

    本篇博客是我学习某位up在b站讲的pytorch版的yolov3后写的 那位up主的b站的传送门 https www bilibili com video BV1A7411976Z 他的博客的传送门 https blog csdn net
  • c/c++linux后台服务器开发如何提升?(路线图已备好)

    随着业务市场的不断壮大 更便捷的开发语言也越来越受到市场的欢迎 Java python还有新贵golang 那c c 语言的开发者市场在哪里 虽然说没有活干说的可能过于夸张 但是面临的事实就是比不了 可能初学一点Java python等等就
  • 将NFA变成最小化DFA的方法

    学习的时候总感觉这个遇到新的题目不会做 这里总结一下 整个流程是这样的 我们直接来看一个例子 使用上面的算法来实现我们最后的目标 a b ba ab 我们先来画NFA 明确 开始状态和接受状态 终结状态要画两个圈 值得注意的是 由于 也可以
  • netron可视化

    1 netron简介 在很多项目中 经常会遇到各种网络模型 在学习的过程中 我们需要快速去了解这些结构 若只是单纯的看模型文件 很难了解其结构 netron可视化工具 可以清晰的看看见每一层的输入输出 网络总体的架构 而且还能支持各种网络框
  • API接口安全加密,防止接口被黑客攻击

    API接口安全加密的主要目的是为了防止黑客攻击 保护敏感数据不被泄露 以下是一些常用的API接口安全加密方式 HTTPS协议 使用HTTPS协议可以对数据进行传输加密 防止数据在传输过程中被窃听或篡改 API密钥认证 API密钥认证是指在每
  • 关键字constexpr(C++)

    关键字constexpr是在C 11中引入的 并且在C 14中得到了改进 像const一样 它可以应用于变量 当任何代码试图去修改该值时 都会引发编译器错误 与const不同 constexpr也可以应用于函数和类构造函数 constexp
  • 第13届CCF-CSP题解

    文章目录 Less 1 出现最多的数 Less 2 ISBN号码 Less 3 最大矩形 Less 4 有趣的数 Less 5 dfs Less 1 出现最多的数 直接根据题意模拟 include
  • 【yolov6系列一】深度解析网络架构

    在yolov5霸屏计算机视觉领域很久时 六月处美团开源了yolov6 并号称在精度和速度上均超越其他同量级的计算机视觉模型 刚刚瞅了一眼 star已经超过2 8k 脑子里莫名冒出一个词 国货之光 网上基于yolov6的解读有很多 文末会附上
  • Kmeans简单实现

    一 KMeans算法实现代码 class KMeans def init self data k clustres self data data self k clustres k clustres def train self max i
  • 基于 python 的数据库简单开发实验

    基于 python 的简单数据库应用程序开发总结 前言 在大三上数据库课时需要做基于数据库的 C S 和 B S 的简单应用 对之前一直接触命令行黑框框的笔者来说 需要临时学习不少新的技术 实际最后的开发非常简单 只是在前期选定技术和查找文
  • (1)密码学之RSA算法

    开始前先讲一下对称加密算法和公钥加密算法 我不喜欢叫非对称加密算法 这使我想起那个被问MD5算法属于对称还是非对称的恐惧 对称加密算法 1 甲方选择某一种加密规则 对信息进行加密 2 乙方使用同一种规则 对信息进行解密 公钥加密算法 1 乙
  • oracle 整理表 碎片,Oracle数据库表空间碎片的查询和整理方法

    一 查看表空间碎片的方法 1 查看fsfi值 select a tablespace name trunc sqrt max blocks sum blocks 100 sqrt sqrt count blocks 2 fsfi from
  • php+redis实现消息队列

    个人理解在项目中使用消息队列一般是有如下几个原因 把瞬间服务器的请求处理换成异步处理 缓解服务器的压力 实现数据顺序排列获取 redis实现消息队列步骤如下 1 redis函数rpush lpop 2 建议定时任务入队列 3 创建定时任务出
  • 目标检测mAP计算详解

    首先说明计算mAP有多个版本 每个数据集和比赛用的版本和方式也不同 下以VOC与COCO举例说明 精确度 precision 召回率 recall 分别为 常规的mAP计算为 这是一个N类检测任务 1 计算单张图片中class1的精度P V
  • Mac启动磁盘已满怎么办?Mac启动磁盘已满怎么清理?

    如果你的Mac电脑经常弹出窗口 您的启动盘几乎已经满了 这说明你的Mac硬盘空间严重不足了 清理各种不必要的垃圾可以释放一些空间 那么Mac启动磁盘已满怎么清理 下面为大家带来几点非常实用的Mac启动磁盘清理技巧 学会这些对你使用Mac电脑
  • 若依(ruoyi)代码生成树表结构的那些坑

    相信许多做后端开发的同学 一定用过若依这款框架 这款框架易上手 适合用来做后台管理系统 但是其中也存在一些坑 稍不注意就会中招 大佬可以忽略 今天 我们说的是若依的代码生成 树结构表 话不多说 直接看图说话 1 项目正常运行 成功登录之后
  • JS 对象和函数

    目录 一 对象 创建对象的四种方式 构造函数原型对象prototype和对象原型 proto 二 函数 创建函数的3种方式 一 对象 创建对象的四种方式 第一种方式 字面量 var o1 name o1 var o2 new Object
  • STM32F103C8用内部Flash做一个优盘(USB+MSC+FATFS)

    STM32F103C8用内部Flash做一个优盘 USB MSC FATFS 轻松实现APP升级 数据存储 基本工程生成 直接使用STM32CubeMX生成基本的工程 省得我们去调底层 时钟配置为外部8MHz晶振 这个需要根据自己开发板的晶