文章目录
stmflash.h
stmflash.h
如下:
#ifndef __STMFLASH_H__
#define __STMFLASH_H__
#include "sys.h"
#define STM32_FLASH_SIZE 512 /* 所选STM32的FLASH容量大小(单位为K) */
#define STM32_FLASH_WREN 1 /* 使能FLASH写入(0为不使能,1为使能) */
#define STM32_FLASH_BASE 0x08000000 /* STM32的FLASH起始地址 */
u16 STMFLASH_ReadHalfWord ( u32 faddr ); /* 读出半字 */
void STMFLASH_WriteLenByte ( u32 WriteAddr, u32 DataToWrite, u16 Len ); /* 指定地址开始写入指定长度的数据 */
u32 STMFLASH_ReadLenByte ( u32 ReadAddr, u16 Len ); /* 指定地址开始读取指定长度数据 */
void STMFLASH_Write ( u32 WriteAddr, u16 *pBuffer, u16 NumToWrite ); /* 从指定地址开始写入指定长度的数据 */
void STMFLASH_Read ( u32 ReadAddr, u16 *pBuffer, u16 NumToRead ); /* 从指定地址开始读出指定长度的数据 */
void Test_Write ( u32 WriteAddr, u16 WriteData ); /* 测试写入 */
#endif
stmflash.c
stmflash.c
如下:
#include "stmflash.h"
#include "delay.h"
#include "usart.h"
u16 STMFLASH_ReadHalfWord ( u32 faddr ) {
/* 读取指定地址的半字(16位数据),参数faddr是读地址(此地址必须为2的倍数) */
return * ( vu16 * ) faddr;
}
#if STM32_FLASH_WREN /* 如果使能了写 */
/* 不检查的写入。参数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] );
WriteAddr += 2; /* 地址增加2 */
}
}
#if STM32_FLASH_SIZE < 256
#define STM_SECTOR_SIZE 1024 /* 字节 */
#else
#define STM_SECTOR_SIZE 2048
#endif
u16 STMFLASH_BUF[STM_SECTOR_SIZE / 2]; /* 最多是2K字节 */
void STMFLASH_Write ( u32 WriteAddr, u16 *pBuffer, u16 NumToWrite ) {
/* 从指定地址开始写入指定长度的数据 */
u32 secpos; /* 扇区地址 */
u16 secoff; /* 扇区内偏移地址(16位字计算) */
u16 secremain; /* 扇区内剩余地址(16位字计算) */
u16 i;
u32 offaddr; /* 去掉0X08000000后的地址 */
if ( WriteAddr < STM32_FLASH_BASE || ( WriteAddr >= ( STM32_FLASH_BASE + 1024 * STM32_FLASH_SIZE ) ) ) {
/* 非法地址 */
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 ) {
/* 检验需要擦除 */
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(); /* 上锁 */
}
#endif
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个字节 */
}
}
void Test_Write ( u32 WriteAddr, u16 WriteData ) {
STMFLASH_Write ( WriteAddr, &WriteData, 1 );
}
main.c
main.c
如下:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "stmflash.h"
const u8 TEXT_Buffer[] = {
"STM32 FLASH TEST"}; /* 要写入到STM32中FLASH的字符串数组 */
#define SIZE sizeof(TEXT_Buffer) /* 数组长度 */
#define FLASH_SAVE_ADDR 0X08020000 /* 设置FLASH的保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小 + 0X08000000) */
int main ( void ) {
SystemInit();
delay_init ( 72 );
NVIC_Configuration();
uart_init ( 9600 );
LED_Init();
STMFLASH_Write ( FLASH_SAVE_ADDR, ( u16 * ) TEXT_Buffer, SIZE );
printf ( "I write %s\r\n", TEXT_Buffer ) ;
delay_ms ( 500 );
while ( 1 ) {
u8 datatemp[SIZE] = {
0};
STMFLASH_Read ( FLASH_SAVE_ADDR, ( u16 * ) datatemp, SIZE );
printf ( "I read %s\r\n", datatemp ) ;
LED0 = !LED0;
delay_ms ( 500 );
}
}