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

这篇具有很好参考价值的文章主要介绍了STM32F103C8用内部Flash做一个优盘(USB+MSC+FATFS)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

基本工程生成

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

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

msc_media_packet,嵌入式,单片机,stm32,嵌入式硬件

启用SWD下载和滴答定时器

msc_media_packet,嵌入式,单片机,stm32,嵌入式硬件

 启用USB

msc_media_packet,嵌入式,单片机,stm32,嵌入式硬件

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

msc_media_packet,嵌入式,单片机,stm32,嵌入式硬件

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

msc_media_packet,嵌入式,单片机,stm32,嵌入式硬件

配置时钟树

msc_media_packet,嵌入式,单片机,stm32,嵌入式硬件

配置堆栈

msc_media_packet,嵌入式,单片机,stm32,嵌入式硬件

至此可以生成工程了,生成工程我选择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盘。也可以在代码检测存储区是否格式化然后调用格式化。我这里就不写了。

msc_media_packet,嵌入式,单片机,stm32,嵌入式硬件

 新建文件夹成功:

msc_media_packet,嵌入式,单片机,stm32,嵌入式硬件

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

其他型号的STM32可以可以参考。文章来源地址https://www.toymoban.com/news/detail-627088.html

到了这里,关于STM32F103C8用内部Flash做一个优盘(USB+MSC+FATFS)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 功耗测评 | STM32F103C8T6

    STM32F103C8T6 MCU越来越广泛的应用在生产生活的各个领域,外接丰富的传感器、功能模块、通信模块、显示存储等可以形成各种可样的产品项目应用。对于功耗要求比较高的产品,一般会选择STM32L系列的MCU,但是从功耗的评测角度,逻辑上是基本相似的。 在很多应用场合中都对

    2024年02月07日
    浏览(35)
  • STM32F103C8T6系统板

    1.电源部分 2.复位 3.晶振 4. 电源电路——防反接 有关二极管 漫谈二极管防电源反接电路 本次采用上图右下角的NMOS防反接电路。 电源电路——电源芯片 AMS1117是AMS公司的 ,LM1117是NS(美国国家半导体)的,LM1117要贵很多,所以一般的用AMS1117就可以了。 (以下分析参考STM32F10

    2024年02月02日
    浏览(60)
  • STM32F103C8T6串口通信

      首先来看一下需要操作的函数,以及配置的步骤: 图1                                                  图2   Code: usart.c #include \\\"usart.h\\\" void ustart_Init(void ) { GPIO_InitTypeDef GPIO_Init_Ustar ; // 定义输出端口TX的结构体对象 USART_InitTypeDef USTART_Init; // 定义串口初始化结构体对象

    2024年02月16日
    浏览(42)
  • STM32F103C8T6串口调试篇

    项目开发中,当出现bug时,由于不知道某个变量的值,所以很难定位问题,针对此问题,串口调试脱颖而出。通过串口printf()实时将需要显示的信息打印出来,这样就很方便的定位问题。 串口设置方法 1.购买调试器pwlink2。参考STM32F103C8T6程序烧录方法_stm32f103c8t6如何烧录_流

    2024年02月12日
    浏览(54)
  • [STM32F103C8T6]ADC转换

    什么是ADC转换? ADC转换的全称是: Analog-to-Digital Converter ,指模拟 / 数字转换器 ADC的性能指标: ADC分辨率: SSA与VREF-一起接到地,DDA与VREF+接到3.3v,所以ADC转换的范围是0---3.3v 所以最后的ADC转换值应该是我们的测量值*分辨率    分辨率 = 3.3v/2^12 = (3.3/4096)   12位的转换器所

    2024年02月06日
    浏览(40)
  • STM32F103C8T6 按键扫描输入

    第一章 STM32F103C8T6 点亮LED灯 系列文章目录 前言 一、原理  1.按键类型  2.按键消抖 3.IO口输入配置 1)模拟输出 2)浮空输入模式 3)下拉输入模式(PULL DOWN) 4)上拉输入模式(PULL UP) 二、代码部分 main.c key.c key.h 总结         上一章我们成功入门了STM32F103C8T6,今天我们来

    2023年04月23日
    浏览(69)
  • STM32F103C8T6移植FreeRTOS

    根据自己开发板型号下载地址:STM32相关内容下载地址 SDK直接下载地址:STM32直接下载地址 下载参考博客 FreeROTS下载地址 选用V9.0.0 版本 个人创建目录如下,可做参考 keil目录 链接头文件 • 修改堆栈大小 • 修改中断函数名 去掉stm32f10x_it.c终端函数 增加FreeRTOS中断 特别解释

    2024年02月12日
    浏览(46)
  • stm32f103c8t6的外部中断

    在单片机中存在着中断系统,这个系统的逻辑和功能在51单片机中已经有所了解。 1.在32单片机中的内核有一个nvic 里面存放许多优先级的设定,外接许多中断源,比如“exti、tim、adc、usart等”接入之后,nvic再通过中断优先级进行排队,再内接入cpu中进行处理,这样子大大减少

    2024年02月09日
    浏览(43)
  • STM32F103C8T6制作USB键盘

            1、原因:电脑每次开机都需要输入登录密码,感觉很麻烦,就想着能不能用单片机做一个USB键盘,按一下自动给电脑发一串密码实现开机。后来又想,其实不用按键也行,用延时,延时到电脑开机再发送密码就好了,于是便有了这个制作。         2、 功能:将做好

    2024年01月22日
    浏览(39)
  • 自制STM32F103C8T6最小系统板

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 记录自己绘制第一块STM32F103C8T6最小系统板,包括原理图的绘制,pcb图的绘制和布局,以及器材的选购。 提示:有任何问题和交流可以加q:2874160799, 我基本上不看评论和私信。 根据ST官方手册,查看引脚

    2024年02月07日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包