STM32_Flash模拟eeprom

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 );
    }
}

猜你喜欢

转载自blog.csdn.net/fukangwei_lite/article/details/121500285