目录标题写在这里
- 一、项目原理
-
- 1、什么是Flash
- 2、实例说明
- 二、FLASH使用代码读写程序
-
- 1、main.c函数
- 2、flash.c函数
- 3、flash.h函数
- 4、led和key函数
- 三、代码分析
一、项目原理
1、什么是Flash
Flash全名叫做Flash Memory,属于非易失性存储设备的数据存储设备(Non-volatile Memory Device),对应于易失性存储设备(Volatile Memory Device)非易失存储设备:断电后数据不丢失,即断电前保持状态。e.g. Flash,硬盘,ROM等。 易失存储设备:断电后数据丢失,即返回输入前状态。e.g.内存,SDRAM,DDR SDRAM,DDR2,DDR3等。
2、实例说明
未加flash程序的2个LED二进制加法项目上显示: 加入flash程序的2个LED二进制加法项目上显示:
二、FLASH使用代码读写程序
1、main.c函数
#include "stm32f10x.h" //STM32头文件#include "sys.h"#include "delay.h"#include "led.h"#include "key.h" #include "flash.h" #define FLASH_START_ADDR 0x0801f000 ///写入的起始地址int main (void){ //主程序 u16 a; //定义变量 //初始化程序 RCC_Configuration(); ///时钟设置 LED_Init();//LED初始化 KEY_Init();//按键初始化 a = FLASH_R(FLASH_START_ADDR);////阅读指定页面的地址FLASH GPIO_Write(LEDPORT,a); ///直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上) //主循环 while(1){ //示例4:有
锁 if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平 delay_ms(20); //延时20ms去抖动 if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平 //在2个LED上显示二进制加法 a++; //变量加1 if(a>3){ //当变量大于3时清0 a=0; } GPIO_Write(LEDPORT,a); //直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上) FLASH_W(FLASH_START_ADDR,a); //从指定页的地址写入FLASH while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按键松开 } } }}
2、flash.c函数
#include "flash.h"//FLASH写入数据void FLASH_W(u32 add,u16 dat){
//参数1:32位FLASH地址。参数2:16位数据// RCC_HSICmd(ENABLE); //打开HSI时钟 FLASH_Unlock(); //解锁FLASH编程擦除控制器 FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位 FLASH_ErasePage(add); //擦除指定地址页 FLASH_ProgramHalfWord(add,dat); //从指定页的addr地址开始写 FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位 FLASH_Lock(); //锁定FLASH编程擦除控制器}//FLASH读出数据u16 FLASH_R(u32 add){
//参数1:32位读出FLASH地址。返回值:16位数据 u16 a; a = *(u16*)(add);//从指定页的addr地址开始读return a;}
3、flash.h函数
#ifndef __FLASH_H#define __FLASH_H #include "sys.h" void FLASH_W(u32 add,u16 dat);u16 FLASH_R(u32 add);#endif
4、led和key函数
见链接中的led.c led.h key.c key.h 函数
链接: led和key函数
三、代码分析
#define FLASH_START_ADDR 0x0801f000
flash存储在主存储区中,存储地址如下,此处是为此处将要存储的变量设置地址(一般的设置较靠后的位置,为用户数据存储留下足够空间),本次程序存储的位置是0x0801f000位于124页
a = FLASH_R(FLASH_START_ADDR);//从指定页的地址读FLASHGPIO_Write(LEDPORT,a); //直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上)
此句的分析可以在看完下面的内容后最后查看 FLASH_R()函数源于flash.c函数,读取出存放在FLASH_START_ADDR处的led的状态值。
u16 FLASH_R(u32 add){ //参数1:32位读出FLASH地址。返回值:16位数据 u16 a; a = *(u16*)(add);//从指定页的addr地址开始读 return a;}
FLASH_W(FLASH_START_ADDR,a); //从指定页的地址写入FLASH
选择语句中按键控制LED灯变化的内容不再赘述,里面包含的FLASH_W()函数来源于flash.c函数 输入参数1:32位FLASH地址。即在程序起点定义的宏定义。 输入参数2:16位数据。按键控制LED灯变化函数中用了一个16为的变量a进行记录led灯的当前状态,此处及传达此状态到flash中去
void FLASH_W(u32 add,u16 dat){ //参数1:32位FLASH地址。参数2:16位数据// RCC_HSICmd(ENABLE); //打开HSI时钟(此处未用到) FLASH_Unlock(); //解锁FLASH编程擦除控制器 FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位 FLASH_ErasePage(add); //擦除指定地址页 FLASH_ProgramHalfWord(add,dat); //从指定页的addr地址开始写 FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位 FLASH_Lock(); //锁定FLASH编程擦除控制器}
1、为了防止程序出错对flash的数据造成影响,所以在不使用flash读写程序时会将其FLASH_Lock()锁定,因此在使用前需要利用FLASH_Unlock()函数解锁flash程序,才能够写入程序值。 2、FLASH_ClearFlag():为了写入新的flash程序,我们需要把flash地址上已经存在的值进行清除。 3、FLASH_ProgramHalfWord():写入led的状态值,存入FLASH_START_ADDR地址中。 4、FLASH_ClearFlag():清除flash待处理标志位函数,这是一条必要操作,加上即可,暂且不论。
FLASH_W()函数载入完后,led的状态值就被存储到flash函数中了,在程序开始的地方利用FLASH_R()读取出flash的值再显示在led上就能保证断电后led仍然保持短点前的状态了。