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仓库下载:传送门。文章来源:https://www.toymoban.com/news/detail-627088.html
其他型号的STM32可以可以参考。文章来源地址https://www.toymoban.com/news/detail-627088.html
到了这里,关于STM32F103C8用内部Flash做一个优盘(USB+MSC+FATFS)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!