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 操作有了更深入的理解和掌握。在遇到问题和解决问题的过程中,锻炼了自己的调试能力和问题解决能力,学会了如何从硬件和软件两个层面去分析和解决问题。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值