历史上的今天
今天是:2024年09月11日(星期三)
2018年09月11日 | STM32中flash的读写详解
2018-09-11 来源:eefocus
一:对STM32内部FLASH写进行编程操作,需要遵循以下流程:
1.FLASH解锁
2.清除相关标志位
3.擦除FLASH(先擦除后写入的原因是为了工业上制作方便,即物理实现方便)
4.写入FLASH
5.锁定FLASH
(1)获取状态:FLASH_Status FLASH_GetStatus(void);
返回值是通过枚举类型定义的。
typedef enum
{
FLASH_BUSY = 1, //忙
FLASH_ERROR_PG, //编程错误
FLASH_ERROR_WRP, //写保护错误
FLASH_COMPLETE, //操作完成
FLASH_TIMEOUT //操作超时
}FLASH_Status;
(2)FLASH_Unlock();//解锁函数(在对flash进行写操作前必须解锁)
(3)FLASH_ClearFlag();//清除所有已有标志
(4)擦除函数有3个:
FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
FLASH_Status FLASH_EraseAllPages(void);
FLASH_Status FLASH_EraseOptionBytes(void);
(5)写函数:
FLASHStatus FLASH_ProgramWord(uint32_t Address,uint32_t Data);//32位字写入函数
FLASHStatus FLASH_ProgramHalfWord(uint32_t Address,uint32_t Data);//16位半字写入
FLASHStatus FLASH_ProgramOptionByteData(uint32_t Address,uint32_t Data);//用户字节写入
int write_flash(u32 StartAddr,u16 *buf,u16 len)
{
volatile FLASH_Status FLASHStatus;
u32 FlashAddr;
len=(len+1)/2;
FLASH_Unlock();//1.解锁函数(在对flash进行写操作前必须解锁)
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);//2.清除所有已有标志
FlashAddr=StartAddr;
FLASH_ErasePage(StartAddr);//3.擦除一个flash页面
while(len--)
{
//FLASH_ProgramHalfWord为写入函数,返回值是flash的状态(5种)
FLASHStatus = FLASH_ProgramHalfWord(FlashAddr,*buf++);
if (FLASHStatus != FLASH_COMPLETE) //FLASH_COMPLETE表示闪存完成
{
//printf("FLSH :Error %08X\n\r",FLASHStatus);
return -1;
}
FlashAddr += 2;
}
FLASH_Lock();
return 0;
}
二:FLASH 读取方法
*(uint32_t *)0x8000000;//读一个字
*(uint8_t *)0x8000000;//读一个字节;
*(uint16_t *)0x8000000;//读半字;
举例:
uint8_t data;
data = *(uint8_t *)0x8000000;//就是读取FLASH中地址0x8000000处的数据
int read_flash(u32 StartAddr,u32 *buf,u16 len) //一次读一个字4字节
{
len=(len+3)/4;
while(len--)
{
*buf=*(__IO uint32_t *)StartAddr;
StartAddr=StartAddr+4;
buf++;
}
return 0;
}
三:几个有用的子函数
/*
功能:向指定地址写入数据
参数说明:addr: 写入的FLASH页的地址
p: 被写入变量的地址(数组中的必须是uint8_t类型,元素个数必须是偶数)
Byte_Num: 被写入变量的字节数(必须是偶数)
*/
void FLASH_WriteByte(uint32_t addr , uint8_t *p , uint16_t Byte_Num)
{
uint32_t HalfWord;
Byte_Num = Byte_Num/2;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_ErasePage(addr);
while(Byte_Num --)
{
HalfWord=*(p++);
HalfWord|=*(p++)<<8;
FLASH_ProgramHalfWord(addr, HalfWord);
addr += 2;
}
FLASH_Lock();
}
例:
uint8_t data[100];
FLASH_WriteByte(0x8000000 , data , 100);/*数组data的数据被写入FLASH中*/
/*
功能:从指定地址读取数据
参数说明:addr 从FLASH中读取的地址
p 读取后要存入变量的地址(数组中的必须是uint8_t类型)
Byte_Num 要读出的字节数
*/
void FLASH_ReadByte(uint32_t addr , uint8_t *p , uint16_t Byte_Num)
{
while(Byte_Num--)
{
*(p++)=*((uint8_t*)addr++);
}
}
例:
uint8_t data[101];
FLASH_ReadByte(0x8000001 , data , 101);/*FLASH中的数据被读入数组data中*/
hardware_conf.h中:
//64 flash
#define ADDRESS_START_ADDR ((u32)0x0800EC00)//59:存储域名和端口号
#define TIME_START_ADDR ((u32)0x0800F000)//60:存储时间
#define KEYS_START_ADDR ((u32)0x0800F400)//61:存储各种key
#define MACHINEID_START_ADDR ((u32)0x0800F800)//62:存储机器码
#define VERSION_START_ADDR ((u32)0x0800FC00)//63:存储版本号
main()中:
//获取flash内容
void getFlash()
{
/*读取机器码*/
u8 machineId[19]="";
read_flash(MACHINEID_START_ADDR, (u32 *) machineId, 19);
strncpy(MachineID_Default, machineId, 18);
/*读取时间*/
u8 times[20]="";
read_flash(TIME_START_ADDR, (u32 *) times, 20);
char timeKey[2]="";
strncpy(timeKey, times, 1);
/*读取keys*/
u8 out_data[220];
read_flash(KEYS_START_ADDR, (u32 *) out_data, 220);
}
//写各种key到flash
int getAllMessage()
{
char in_data[220];
//下面是falsh需要存储的变量
sprintf(in_data, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s",isFisrt,community_code,address,swipe,code_overtime,myKey1,Private_Key,check_pw);
if(strlen(in_data)==96&&in_data[0]=='N' &&in_data[1]=='\n'&&in_data[63]=='\n'&&in_data[65]=='\n'&&in_data[69]=='\n'&&in_data[75]=='\n'&&in_data[82]=='\n'&&in_data[89]=='\n')
{
write_flash(KEYS_START_ADDR, (u16 *) in_data, 220);
ACCLOG("write keys success\n");
return 1;
}else{
ACCLOG("write keys fail...\n");
return 0;
}
}
史海拾趣
|
液晶显示问题。我买了快开发板,本来是1024*768分辨率的,根据网上资料,修改成800*600,但是整个WINDOWS界面只显示了屏幕的左上角,其他WINDOWS CE程序一切正常,不知道如何是好,希望各位能给电帮助。… 查看全部问答> |
|
一 为什么说是伪动态 做网站的人知道动态网页常用的开发语是ASP.net、JSP、PHP。而这里我们是没法用上的,我们用的是cgi文件。 二 什么是CGI Common Gate Interface(通用网关 ...… 查看全部问答> |
|
大家好! 小弟现在遇到一个奇怪的问题。 硬件测试环境:板子是STM8S208,板子上有两个LIN接口,一个做主机,一个做从机,用一条串口线将两个口连接起来通信。   ...… 查看全部问答> |
|
近几天一直在TI网站上瞎转悠,深为它的器件性能所引,在我提交的电源方案中(还没有完善)决定使用它的Piccolo CPU : _TMS320f28035,它可以由一块CPU担任所设想的从PFC到输出部分的、全部分的功率控制。 然而,搞这个没有个仿真器 ...… 查看全部问答> |
|
如何使用 CCS 建一个 M3 的工程,一直在用 MDK,最近不得不熟悉 CCS ,不知道 CCS 要怎么建工程呢? 找到一个 PDF ,按照里边的步骤还是能编译,而且很慢,这样的工具怎么用呢? [ 本帖最后由 Study_Stellaris 于 2011-12-5 16:00 编辑 ]… 查看全部问答> |
|
在CCS3.3的开发环境下,拿TDS560仿真器连接omapl138的板子,在reset_TDS560USB_plus时出现如下错误:C:\\CCStudio_v3.3\\cc\\bin>dbgjtag -f brddat\\ccbrd0.dat -rv ------------------------------------------------------------------------ ...… 查看全部问答> |
|
BeagleBone试用第一周 底板PCB--今天终于决定把板子拿去制了。到底如何不管他。 今天终于决定把板子拿去制了。到底如何不管他。 时间要紧。有错就改嘛。反正还是好同志。 希望大家支持,阿莫那里要求插孔都加大0.15MM 所以我的孔画的比较大。 有关硬件的资料: [ 本帖最后由 damiaa 于 2012-9-28 16:27 编辑 ...… 查看全部问答> |




