FlashRom
任务要求:Flash地址空间的数据读取。stm32f103c8t6只有20KB 内存(RAM)供程序代码和数组变量存放,因此,针对内部Flash的总计64KB存储空间(地址从0x08000000开始),运行一次写入8KB数据,总计复位运行代码8次,将64KB数据写入Flash,并验证写入数据的正确性和读写速率。此外,继续往后续地址写入数据,检验stm32f103c8t6 实际FlashROM是否超过64KB。
一、建立CubeMX工程
新建工程,选择我们所需要的芯片

配置RCC

配置SYS

配置GPIO
我这里选择PC13作为LED灯的输出

配置NVIC

配置时钟

配置Project Manager


之后生成代码
二、代码编写
我们这里需要自行添加代码
1.添加flash.c和flash.h文件

flash.h文件同样的添加方法
2.添加flash.c和flash.h代码
flash.h代码
/*
* flash.h
*
* Created: 2016-04-22
* Author: zhanglifu
*/
#ifndef _flash_H_
#define _flash_H_
#include "stm32f1xx_hal.h"
/*********************************************************************/
// 变量定义
/*********************************************************************/
//-- 用途划分
// 0x0800FC00-0x0800FFFF -- 使用最后4k 个字节用来存放电机信息
#define FMC_FLASH_BASE 0x08000000 // FLASH的起始地址
#define APP_MAX_SIZE 0x00010000 //
#define FMC_FLASH_END 0x08010000 // FLASH的结束地址 256
#define DEVICE_INFO_ADDRESS 0x0800C000 //(STM32_FLASH_END - DEVICE_INFO_SIZE) // 设备信息起始地址
#define DEVICE_LOG_ADDRESS 0x0800E000 //(STM32_FLASH_END - 2*DEVICE_INFO_SIZE) // 设备日志起始地址
#define FMC_FLASH_SIZE 64 // 定义Flash大小,单位KB
#if FMC_FLASH_SIZE < 256
#define FMC_SECTOR_SIZE 1024 // 字节
#define MOD_SECTOR_SIZE 0X3FF
#define PAGE_COUNT_BY16 512
#else
#define FMC_SECTOR_SIZE 2048
#define MOD_SECTOR_SIZE 0X7FF
#define PAGE_COUNT_BY16 1024
#endif
/*********************************************************************/
// 函数声明
/*********************************************************************/
void FlashWriteBuff( const uint32_t destination_address, uint8_t *const buffer,uint32_t length );
void FlashReadBuff(const uint32_t source_address,uint8_t *const buffer,uint16_t length);
#endif
flash.c代码
/*
* flash.c
*
* Created: 2018-01-29
* Author: zhanglifu
*/
/*********************************************************************/
// 头文件
/*********************************************************************/
#include "flash.h"
// 不检查的写入
// WriteAddr:起始地址
// pBuffer: 数据指针
// NumToWrite:字节数数
void FlashWriteNoCheck( uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite )
{
uint16_t i;
for( i=0; i<NumToWrite; i+=4 )
{
while( HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, WriteAddr+i,*(uint32_t *)(pBuffer+i) ) );
}
}
extern void FLASH_PageErase(uint32_t PageAddress);
void FlashWriteBuff( const uint32_t destination_address, uint8_t *const buffer,uint32_t length )
{
uint16_t i;
uint8_t FlashBuff[FMC_SECTOR_SIZE];
uint32_t StartAddress = destination_address - destination_address%FMC_SECTOR_SIZE;
uint16_t Offset = destination_address - StartAddress;
uint8_t *pBuf = buffer;
uint32_t remaindNum = length;
HAL_StatusTypeDef status = HAL_ERROR;
// 地址检查
if( (destination_address < FMC_FLASH_BASE) || ( destination_address + length >= FMC_FLASH_END) || (length <= 0) )
return;
HAL_FLASH_Unlock(); // 解锁
do
{
// 读出一页数据
for(i=0; i < FMC_SECTOR_SIZE; i += 4 )
*(uint32_t *)(FlashBuff+i) = *(uint32_t *)(StartAddress+i);
// 修改要改入的数据
for ( i=0; (i+Offset)<FMC_SECTOR_SIZE && i< remaindNum; i++ )
*(FlashBuff+Offset+i) = *(pBuf+i);
// 擦除一ROW数据
FLASH_PageErase( StartAddress );
// HAL库 FLASH_PageErase有BUFF,要加上下面三行代码
while( status != HAL_OK )
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
// 写入数据
FlashWriteNoCheck( StartAddress,FlashBuff,FMC_SECTOR_SIZE );
// 为下一页做准备
StartAddress += FMC_SECTOR_SIZE;
remaindNum -= i;
pBuf += i;
Offset = 0;
} while( remaindNum > 0 );
HAL_FLASH_Lock(); // 上锁
}
// 从FLASH中读指定长度数据
void FlashReadBuff(const uint32_t source_address,uint8_t *const buffer,uint16_t length)
{
uint16_t i;
uint8_t Offset = 0;
uint32_t StartAddress = source_address;
uint16_t data;
// 地址检测
if( source_address + length > FMC_FLASH_END ) return;
// 如果没有对16齐
if( source_address & 1 )
{
Offset = 1;
StartAddress = source_address-1;
}
// flash的操作要求16对齐 最小读写操作16个比特
if ( Offset )
{
data = *(uint16_t *)(StartAddress);
buffer[0] = data >> 8;
StartAddress += 2;
}
for ( i = 0; i < (length-Offset); i += 2)
{
data = *(uint16_t *)(StartAddress+i);
buffer[i+Offset] = (data & 0xFF);
if ( (i+Offset) < (length - 1) )
buffer[i + Offset + 1] = (data >> 8);
}
}
3.添加flash文件路径
在刚刚CubeMX创建出的文件夹中的MDK-ARM文件夹中新建一个flash文件夹,将flash.h和flash.c复制到flash文件夹内

点击魔术棒,选择c/c++,添加刚刚新建的flash文件夹的地址

4.在main.c添加代码
#include "flash.h"

uint8_t FlashWBuff [255];
uint8_t FlashRBuff [255];

uint8_t i;
uint8_t FlashTest[] = "Hello This is ZhangMing hao Flash Test DEMO";

FlashWriteBuff( DEVICE_INFO_ADDRESS, FlashTest,sizeof(FlashTest) ); // 写入数据到Flash
for(i=0;i<255;i++)
FlashWBuff[i] = i;
FlashWriteBuff( DEVICE_INFO_ADDRESS + sizeof(FlashTest), FlashWBuff,255 ); // 写入数据到Flash
FlashReadBuff( DEVICE_INFO_ADDRESS + sizeof(FlashTest),FlashRBuff,255 ); // 从Flash中读取数

之后进行编译
编译过后测试


三、实验总结
实验结果
1.所有写入的数据均被正确读取,验证了Flash的可靠性。
2.通过记录时间,计算出平均写入和读取速率。
3.在写入64KB数据后,继续写入数据,如果微控制器出现错误或无法启动,说明Flash容量未超过64KB。
心得体会
通过实际操作,我对Flash的物理特性和操作有了更深入的理解。并且实际操作STM32F103C8T6,加深了对微控制器硬件特性的认识。我也在实验过程中遇到了很多问题,如写入失败、数据校验错误等,这些都锻炼了解决问题的能力。通过这次实际操作,将理论知识与实践紧密结合,对 stm32f103c8t6 的 Flash 操作有了更深入的理解和掌握。在遇到问题和解决问题的过程中,锻炼了自己的调试能力和问题解决能力,学会了如何从硬件和软件两个层面去分析和解决问题。
1326

被折叠的 条评论
为什么被折叠?



