STM32F103的FLASH代码

在这边就不仔细介绍FALSH这个东西了,简而言之就是个存储数据的地方,比如每次完成一个任务,或者计数,就存储一下。但是在突然断电的时候可能会存不了(个人感觉只要每隔多久存一下,突然掉电也问题不大)
话不多说,直接上代码

flash.h

#ifndef _FLASH_H_
#define _FLASH_H_

#define FLASH_KEY1               0X45670123 //在"stm32f10x_flash.c"中有定义
#define FLASH_KEY2               0XCDEF89AB	//在"stm32f10x_flash.c"中有定义

#include "sys.h"

#define STM32_FLASH_SIZE 512	//	所选STM32的FLASH容量大小(单位为K)	STM32的手册最后几页有一个:
								// Ordering information scheme,中可以看到芯片的FLSAH大小

#if STM32_FLASH_SIZE < 256
#define STM_SECTOR_SIZE 	1024                                       //字节
#else
#define STM_SECTOR_SIZE 	2048
#endif


//FLASH起始地址
#define STM32_FLASH_BASE 0x08000000 	//STM32 FLASH的起始地址
#define STM32_FLASH_ADDR 0X08070000		//STM32 要开始写的地址必须为2的倍数,并且在flash地址范围内。

u16 STMFLASH_ReadHalfWord(u32 faddr);	//读出半字
void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite);	//从指定地址开始写入指定长度的数据
void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead);	//从指定地址开始读取指定长度的数据

#endif

在这里插入图片描述

flash.c

#include "stm32f10x.h"
#include "delay.h"
#include "flash.h"

//读出指定地址的半字(16位数据)
//faddr:读地址(此地址必须为2的倍数!!)
//返回值:对应数据.
u16 STMFLASH_ReadHalfWord(u32 faddr)
{
    return *(vu16*)faddr;
}


//不检查的写入:		//WriteAddr:起始地址
					//pBuffer:数据指针
					//NumToWrite:半字(16位)数
void STMFLASH_Write_NoCheck (u32 WriteAddr, u16 *pBuffer, u16 NumToWrite)
{
    u16 i;
    for(i=0; i<NumToWrite; i++)
    {
        FLASH_ProgramHalfWord(WriteAddr, pBuffer[i]);//	写入半个字=2个字节
        WriteAddr += 2;//	地址增加2.
	}
}
//从指定地址开始写入指定长度的数据:		//WriteAddr:	起始地址(此地址必须为2的倍数!!)
										//pBuffer:		数据指针
										//NumToWrite:	半字(16位)数(就是要写入的16位数据的个数.)
u16 STMFLASH_BUF [STM_SECTOR_SIZE / 2];	//定义一个数组 最多是2K字节,如果是小容量的则最多是1K
void STMFLASH_Write(u32 WriteAddr, u16 *pBuffer, u16 NumToWrite) 
{
    u32 secpos;             //扇区地址
    u16 secoff;             //扇区内偏移地址(16位字计算)
    u16 secremain;          //扇区内剩余地址(16位字计算)
    u16 i;					//计数 i
    u32 offaddr;            //去掉0X08000000后的地址
    if((WriteAddr < STM32_FLASH_BASE) || (WriteAddr >= (STM32_FLASH_BASE + 1024 * STM32_FLASH_SIZE))) 
	//如果写的地址大于或小于这个flash地址,就直接跳出。
	{
			return;//非法地址
	}
    FLASH_Unlock();									//解锁
    offaddr	= WriteAddr - STM32_FLASH_BASE;			//实际偏移地址.
    secpos = offaddr / STM_SECTOR_SIZE;         	//扇区地址
    secoff= ( offaddr % STM_SECTOR_SIZE ) / 2;  	//在扇区内的偏移(2个字节为基本单位.)
    secremain = STM_SECTOR_SIZE / 2 - secoff;   	//扇区剩余空间大小
    if(NumToWrite <= secremain)						//如果要输入数据的个数小于剩余的空间容纳的个数	
	{
		secremain = NumToWrite;						//让扇区剩余空间大小等于输入数据的个数
	}
    while(1)
    {
        STMFLASH_Read(secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE, STMFLASH_BUF, STM_SECTOR_SIZE / 2);
        //读出整个扇区的内容		
		for(i=0; i < secremain; i++)	//校验数据  
        {
            if(STMFLASH_BUF[secoff + i] != 0XFFFF)					//如果数据不是0xFFFF,则需要擦除
			{
				break;
			}
        }
        if(i < secremain)                                           //需要擦除
        {
            FLASH_ErasePage(secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE);//擦除这个扇区
            for(i=0; i < secremain; i++)								
            {
                STMFLASH_BUF[i + secoff] = pBuffer[i];				//将要写入的数组复制到定义的数组中
            }
            STMFLASH_Write_NoCheck(secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE, STMFLASH_BUF, STM_SECTOR_SIZE / 2);//写入整个扇区
        } 
		else 
			STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain); 	//如果不需要擦除,直接写入扇区剩余区间.
        if(NumToWrite == secremain)
			break;                          						//写入结束
        else                                                      	//写入未结束
        {
            secpos++;                                              	//扇区地址增1
            secoff=0;                                             	//偏移位置置0
            pBuffer += secremain;                               	//指针偏移
            WriteAddr += secremain;                                 //写地址偏移
            NumToWrite -= secremain;                              	//字节(16位)数递减
            if(NumToWrite > (STM_SECTOR_SIZE / 2))					//下一个扇区还是写不完
			{	
				secremain = STM_SECTOR_SIZE / 2;					//进入下一个扇区
			}
            else 
				secremain=NumToWrite;                           	//下一个扇区可以写完了
        }
    };
    FLASH_Lock();                                                  	//上锁
}

//从指定地址开始读取指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数
void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)
{
    u16 i;
    for(i=0; i<NumToRead; i++)
    {
        pBuffer[i]=STMFLASH_ReadHalfWord(ReadAddr);               //读取2个字节.
        ReadAddr+=2;                                              //偏移2个字节
    }
}

实战也很简单,定义一个16位的数组,将想要的数据存在数组里。举个例子:

#define STM32_FLASH_ADDR 0x08060000	//定义写入地址
u16 temp[2] = {12,1234} //定义一个数组
STMFLASH_Write(STM32_FLASH_ADDR,temp,2); // 将temp的第0个和第1个的数据存到FLASH中
STMFLASH_Read(STM32_FLASH_ADDR,time,2);	// 将temp的第0个和第1个的数据从FLASH中读出来
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值