/****************************************************************************** * @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 #include /* ============================================================================ * 私有宏定义 * ============================================================================ */ #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) * 对于STM32F103V,Flash地址范围: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; }