Files
DTU-LCD/Users/File_Handle.c
2026-01-24 20:03:14 +08:00

125 lines
5.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/******************************************************************************
* @file File_Handle.c
* @brief BMP图片文件处理和Flash存储管理文件
* @details 本文件实现了BMP图片文件的处理功能包括BMP文件头结构定义、
* Flash存储读写操作、LOGO图片的保存和显示等功能。
* 支持将BMP格式的LOGO图片数据保存到Flash中并在需要时读取显示。
* @author 阜阳师范大学物电学院
* @version V0.1
* @date 2026.1.23
* @note Flash存储地址0x0803F000扇区126
* Flash扇区大小2KB
* BMP数据长度3208字节
******************************************************************************/
/* ============================================================================
* 头文件包含
* ============================================================================ */
#include "filehandle.h"
#include <string.h>
#include <stdio.h>
/* ============================================================================
* 私有宏定义
* ============================================================================ */
#define Flash_EndAddr (0x08040000) /**< Flash存储结束地址 */
#define SECTOR_SIZE (2048) /**< Flash扇区大小单位字节2KB */
/* ============================================================================
* Flash存储操作函数
* ============================================================================ */
/**
* @brief 向Flash写入多个16位数据
* @param startAddress 起始写入地址必须是Flash地址范围内的有效地址
* @param writeData 要写入的数据指针16位数据数组
* @param countToWrite 要写入的数据个数16位数据个数
* @note 本函数实现了Flash的批量写入功能支持跨扇区写入
* 1. 自动计算需要擦除的扇区数量和位置
* 2. 在写入前自动擦除相关扇区
* 3. 按半字16位方式写入数据
* 4. 自动处理Flash的解锁和上锁
* 5. 进行地址合法性检查
* 注意Flash写入前必须先擦除擦除以扇区为单位2KB
* 对于STM32F103VFlash地址范围0x08000000~0x0803FFFF
* @retval HAL_StatusTypeDef 操作状态HAL_OK=成功HAL_ERROR=失败
*/
HAL_StatusTypeDef FLASH_WriteMoreData(uint32_t startAddress, uint16_t *writeData, uint16_t countToWrite)
{
/* 计算去掉Flash基地址0x08000000后的实际偏移地址 */
uint32_t offsetAddress = startAddress - FLASH_BASE;
/* 计算扇区位置,对于 STM32F103V 为0~127 */
uint32_t sectorPosition = offsetAddress / SECTOR_SIZE;
/* 计算对应扇区的首地址 */
uint32_t sectorStartAddress = sectorPosition * SECTOR_SIZE + FLASH_BASE;
uint16_t Index;
/* 计算起始地址在扇区内的偏移量 */
uint32_t startAddressOffset = startAddress - sectorStartAddress;
/* 计算总写入长度(字节数) */
uint32_t Total_len = countToWrite * 2;
uint32_t writeAddr = startAddress;
/* 计算待擦除的扇区个数(考虑起始地址偏移) */
uint32_t EraseSectorNum = (Total_len + startAddressOffset) / SECTOR_SIZE;
HAL_StatusTypeDef status = HAL_OK;
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t SectorError = 0;
/* 如果有余数,需要多擦除一个扇区 */
if((Total_len + startAddressOffset) % SECTOR_SIZE)
EraseSectorNum += 1;
/* 地址合法性检查起始地址必须在Flash范围内 */
if(startAddress < FLASH_BASE || ((startAddress + Total_len) >= Flash_EndAddr))
{
return HAL_ERROR; /* 非法地址 */
}
/* 扇区地址合法性检查 */
if(sectorStartAddress < FLASH_BASE || (sectorStartAddress >= Flash_EndAddr))
{
return HAL_ERROR; /* 非法地址 */
}
/* 解锁Flash写保护 */
HAL_FLASH_Unlock();
/* 检查是否需要跨扇区写入 */
if((writeAddr + Total_len) >= (sectorStartAddress + SECTOR_SIZE))
{
/* 循环擦除需要写入的所有扇区 */
for(Index = 0; Index < EraseSectorNum; Index++)
{
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; /* 设置擦除类型为页擦除 */
EraseInitStruct.PageAddress = sectorStartAddress; /* 设置要擦除的扇区地址 */
EraseInitStruct.NbPages = 1; /* 每次擦除1个扇区 */
/* 执行扇区擦除操作 */
status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
if(status != HAL_OK)
{
HAL_FLASH_Lock(); /* 擦除失败上锁Flash */
return status;
}
/* 移动到下一个扇区 */
sectorStartAddress += SECTOR_SIZE;
}
/* 循环写入所有数据(按半字方式写入) */
for(Index = 0; Index < countToWrite; Index++)
{
/* 按半字16位方式编程Flash */
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, startAddress + Index * 2, writeData[Index]);
if(status != HAL_OK)
{
break; /* 写入失败,退出循环 */
}
}
}
/* 上锁Flash写保护 */
HAL_FLASH_Lock();
return status;
}