STM32 --- 使用内部FLASH存储数据

本文记录了对一些知识点的理解、操作方法,如有错误,请务必批评指正!!

最终的测试截图:

目录​ 

一、内部FLASH要点

关于地址:

关于解锁:

关于擦除:

关于写入:

二、读取数据

三、存储数据

四、应用示例


一、内部FLASH要点

关于地址:

  1. 内部FLASH地址开始地址:0x0800 0000;
  2. 结束地址:0x08000000+FLASH大小
  3. FLASH的大小,可根据芯片型号得知,如F103x8=64K,  F103xC=256K, F103xE=512K
  4. FLASH的大小,也可读*(uint16_t*)0x1FFFF7E0直接获得;

关于解锁:

  1. 对FLASH寄存器的操作, 需要在操作之前解锁;
  2. 如果解锁过程发生错误,FLASH寄存器操作将死锁至掉电;
  3. 解锁步骤(1): FLASH->KEYR= (uint32_t)0x45670123;
  4. 解锁步骤(2): FLASH->KEYR= (uint32_t)0xCDEF89AB;

关于擦除:

  1. 内部FLASH空间,按页划分成连续的数据块;
  2. 每次擦除的最小单位是:页;
  3. F103中,中小容量FLASH的页(扇区)大小为1K, 而大容量的页大小为2K
  4. 每页擦除时长:中小容量约30ms, 大容量约50ms
  5. 页寿命:中小容量约可擦: 1K次, 大容量约可擦: 10K次
  6. 擦除步骤(1):FLASH->CR|= 1<<1;             // 选择以页进行擦除
  7. 擦除步骤(2):FLASH->AR = 0x0800xxxx;  // 要擦除的页地址
  8. 擦除步骤(3):FLASH->CR|= 0x40;             // 开始擦除
  9. 擦除步骤(4):while((FLASH->SR & 0x01); // 等待空闲,即BSY=0

关于写入:

  1. 写入的地址,必须是偶数;
  2. 每一次写入,必须以半字进行(uint16_t)!单字节或全字将发生错误;
  3. 写入步骤(1):  FLASH->CR |= 0x01<<0;                // 使能可编程
  4. 写入步骤(2):  *(uint16_t*)addr = (uint16_t)value;  // 写入数据  
  5. 写入步骤(3):  while((FLASH->SR & 0x01);           // 等待空闲,即BSY=0
  6. 写入步骤(4):  FLASH->CR &= ((uint32_t)0x00001FFE);  // 关闭编程

二、读取数据

  • 可以按byte读取,也可以按半字、全字方式读取;
  • 读取的方式很简单,如:short value = *(uint16_t*)readAddr;

下面的读取函数,经多次完善,按字节读取,方便匹配奇数数量的数据读取;

/******************************************************************************
 * 函 数:  System_ReadInteriorFlash
 * 功  能: 在芯片的内部FLASH里,读取指定长度数据
 * 参  数: uint32_t  readAddr     数据地址
 *         uint8_t  *pBuffer      读出后存放位置
 *         uint16_t  numToRead    读取的字节数量
 * 返回值: 0_成功    1_失败,地址小于FLASH基址   2_失败,地址大于FLASH最大值
 ******************************************************************************/  
uint8_t  System_ReadInteriorFlash (uint32_t readAddr, uint8_t *pBuffer, uint16_t numToRead) 
{     
    // 获取芯片FLASH大小       
    uint16_t flashSize = *(uint16_t*)(0x1FFFF7E0);                        // 读取芯片FLASH大小;本寄存器值为芯片出厂前写入的FLASH大小,只读单位:KByte
                
    // 判断地址有效性                
    if(readAddr < STM32_FLASH_ADDR_BASE)    return 1;                     // 如果读的地址,小于FLASH的最小地址,则退出
    if(readAddr > (STM32_FLASH_ADDR_BASE+(flashSize*1024)))  return 2;    // 如果读的地址,超出FLASH的最大地址,则退出
              
    // 开始复制                
    while(numToRead--){
        *pBuffer = *(__IO uint8_t*)readAddr;
        pBuffer++;        // 指针后移一个数据长度
        readAddr++;       // 偏移一个数据位
    }      
    
    return 0;             // 成功,返回0;    
}

三、存储数据

1:在存储函数前,需要三个数据的定义:

// 下面这三个定义,用于存取内部FLASH数据,F103系列都不用修改
#ifdef   STM32F10X_HD
#define  STM32_FLASH_SECTOR_SIZE       2048                    // 内部FLASH页大小, 单位:bytes  (注:STM32F10xx系列下,小中容量存储器扇区为1K, 大容量存储器扇区为2K)
#else
#define  STM32_FLASH_SECTOR_SIZE       1024                 // 内部FLASH页大小, 单位:bytes  (注:STM32F10xx系列下,小中容量存储器扇区为1K, 大容量存储器扇区为2K)
#endif

#define  STM32_FLASH_ADDR_BASE   0x08000000                    // 芯片内部FLASH基址(这个基本不用修改)
static   uint8_t sectorbufferTemp[STM32_FLASH_SECTOR_SIZE];    // 开辟一段内存空间,作用:在内部FLASH写入时作数据缓冲

2:等待空闲的函数:

// 作用:内部FLASH写入时,等待空闲,BSY位标志:0闲1忙
static uint8_t waitForFlashBSY(uint32_t timeOut)
{                                                        
    while((FLASH->SR & 0x01) && (timeOut-- != 0x00)) ; // 等待BSY标志空闲
    if(timeOut ==0)   
        return 1;    // 失败,返回1, 等待超时; 
    
    return 0;        // 正常,返回0                
}

3:完整可用的存储函数:

/******************************************************************************
 * 函 数:  System_WriteInteriorFlash
 * 功  能: 在芯片的内部FLASH里,写入指定长度数据
 * 参  数: uint32_t  writeAddr        写入地址,重要:写入地址必须是偶数!!!
 *         uint8_t  *writeToBuffer
 *         uint16_t  numToWrite
 *
 * 返回值: 0_成功,
 *         1_失败,地址范围不正确
 *         2_失败,FLASH->SR:BSY忙超时
 *         3_失败,擦除超时
 ******************************************************************************/  
uint8_t System_WriteInteriorFlash(uint32_t writeAddr, uint8_t *writeToBuffer, uint16_t numToWrite)               
{
    uint16_t flashSize = *(uint16_t*)(0x1FFFF7E0);                // 读取芯片FLASH大小;本寄存器值为芯片出厂前写入的FLASH大小,只读,单位:KByte
                    
    uint32_t addrOff    = writeAddr - STM32_FLASH_ADDR_BASE;      // 去掉0x08000000后的实际偏移地址
    uint32_t secPos     = addrOff / STM32_FLASH_SECTOR_SIZE;;     // 扇区地址,即起始地址在第几个扇区
    uint16_t secOff     = addrOff%STM32_FLASH_SECTOR_SIZE ;       // 开始地始偏移字节数: 数据在扇区的第几字节存放
    uint16_t secRemain  = STM32_FLASH_SECTOR_SIZE - secOff;       // 本扇区需要写入的字节数 ,用于判断够不够存放余下的数据
    
    // 判断地址有效性   
    if(writeAddr < STM32_FLASH_ADDR_BASE)    return 1;                     // 如果读的地址,小于FLASH的最小地址,则退出,返回1_地址失败
    if(writeAddr > (STM32_FLASH_ADDR_BASE+(flashSize*1024)))    return 1;  // 如果读的地址,超出FLASH的最大地址,则退出, 返回1_地址失败
               
    // 0_解锁FLASH
    FLASH->KEYR = ((uint32_t)0x45670123);
    FLASH->KEYR = ((uint32_t)0xCDEF89AB);
    
    if(numToWrite <= secRemain)    secRemain=numToWrite;  
    while(1){    
        // 1_读取当前页的数据
        if(waitForFlashBSY(0x00888888))   return 2;                         // 失败,返回:2, 失败原因:FLASH->SR:BSY忙超时                    
        System_ReadInteriorFlash ( secPos*STM32_FLASH_SECTOR_SIZE+STM32_FLASH_ADDR_BASE , sectorbufferTemp, STM32_FLASH_SECTOR_SIZE );   // 读取扇区内容到缓存
                  
        // 2_擦险指定页(扇区)                           
        if(waitForFlashBSY(0x00888888))   return 2;                         // 失败,返回:2, 失败原因:FLASH->SR:BSY忙超时  
        FLASH->CR|= 1<<1;                                                   // PER:选择页擦除;位2MER为全擦除
        FLASH->AR = STM32_FLASH_ADDR_BASE + secPos*STM32_FLASH_SECTOR_SIZE; // 填写要擦除的页地址
        FLASH->CR|= 0x40;                                                   // STRT:写1时触发一次擦除运作 
        if(waitForFlashBSY(0x00888888))   return 2;                         // 失败,返回:3, 失败原因:擦除超时
        FLASH->CR &= ((uint32_t)0x00001FFD);                                // 关闭页擦除功能   
                                          
        for(uint16_t i=0; i<secRemain ; i++)                                // 原始数据写入缓存
            sectorbufferTemp[secOff+i] = writeToBuffer[i];
       
        for(uint16_t i=0; i<STM32_FLASH_SECTOR_SIZE/2 ; i++){               // 缓存数据写入芯片FLASH                      
            if(waitForFlashBSY(0x00888888))   return 2;                     // 失败,返回:2, 失败原因:FLASH->SR:BSY忙超时
            FLASH->CR |= 0x01<<0;                                           // PG: 编程                             
            *(uint16_t*)(STM32_FLASH_ADDR_BASE + secPos*STM32_FLASH_SECTOR_SIZE +i*2) = (sectorbufferTemp[i*2+1]<<8) | sectorbufferTemp[i*2] ; // 缓存数据写入设备
                                                        
            if(waitForFlashBSY(0x00888888))   return 2;                     // 失败,返回:2, 失败原因:FLASH->SR:BSY忙超时
            FLASH->CR &= ((uint32_t)0x00001FFE) ;                           // 关闭编程
        }
        
        if(secRemain == numToWrite){                          
            break;                                                          // 已全部写入
        }                        
        else{                                                               // 未写完                                                                          
            writeToBuffer += secRemain ;                                    // 原始数据指针偏移
            secPos ++;                                                      // 新扇区
            secOff =0;                                                      // 新偏移位,扇区内数据起始地址            
            numToWrite -= secRemain ;                                       // 剩余未写字节数            
            secRemain = (numToWrite>STM32_FLASH_SECTOR_SIZE)?(STM32_FLASH_SECTOR_SIZE):numToWrite;  // 计算新扇区写入字节数                  
        }              
    } 
    FLASH->CR |= 1<<7 ;                                                     // LOCK:重新上锁    
 
    return 0;                
}

四、应用示例

下面代码中,分别测试了四种数据类型的存储、读取、转换。

注意:string不是独立的数据类型;

    printf("\r\n>>>>开始测试内部FLASH读写,及数据转换:\r\n");         
    
    // 测试1:字符
    uint32_t addrChar   = 0x08000000+38*1024;                                          // 注意地址必须是偶数,且地址段尽量安排在FLASH尾部,避免覆盖了代码段数据
    char writeChar='F';            
    System_WriteInteriorFlash(addrChar, (uint8_t*)&writeChar, 1);                      // 存入数据,函数内自动解锁,擦除,写入
    char readChar=0;                                 
    System_ReadInteriorFlash(addrChar, (uint8_t*)&readChar, 1);                        // 读取数据,函数内自动按半字读取
    printf("测试char     地址:0x%X    写入:%c       读取:%c \r\n", addrChar, writeChar, readChar);
    
    // 测试2:带符号的16位   
    uint32_t addrShort  = 0x08000000+155*1024-2;                                       // 注意地址必须是偶数,且地址段尽量安排在FLASH尾部,避免覆盖了代码段数据
    short writeShort=-888;             
    System_WriteInteriorFlash(addrShort, (uint8_t*)&writeShort, sizeof(writeShort));   // 存入数据,函数内自动解锁,擦除,写入
    short readShort=0;       
    System_ReadInteriorFlash(addrShort, (uint8_t*)&readShort, sizeof(writeShort));     // 读取数据,函数内自动按半字读取
    printf("测试short    地址:0x%X    写入:%d    读取:%d \r\n", addrShort, writeShort, readShort);
  
    // 测试3:无符号的32位
    uint32_t addrUint   = 0x08000000+254*1024;                                         // 注意地址必须是偶数,且地址段尽量安排在FLASH尾部,避免覆盖了代码段数据
    uint32_t writeUint= 0x12345678;
    System_WriteInteriorFlash(addrUint, (uint8_t*)&writeUint, 4);                      // 存入数据,函数内自动解锁,擦除,写入
    uint32_t readUint = 0;
    System_ReadInteriorFlash(addrUint, (uint8_t*)&readUint, 4);                        // 读取数据,函数内自动按半字读取
    printf("测试uint     地址:0x%X    写入:0x%X     读取:0x%X \r\n", addrUint, writeUint, readUint);
  
    // 测试4:字符串
    uint32_t addrString   = 0x08000000+166*1024-6;                                     // 注意地址必须是偶数,且地址段尽量安排在FLASH尾部,避免覆盖了代码段数据
    char writeString[100]="早吖! 去哪呢?";     
    System_WriteInteriorFlash(addrString, (uint8_t*)writeString, sizeof(writeString)); // 存入数据,函数内自动解锁,擦除,写入
    char readString[100];
    System_ReadInteriorFlash(addrString, (uint8_t*)readString, sizeof(readString));    // 读取数据,函数内自动按半字读取
    printf("测试string   地址:0x%X   写入:%s  读取:%s \r\n", addrString, writeString, readString);
    

之前建了个Q群,玩STM32的朋友,可以一起吹吹水:262901124.

版权声明:本文为CSDN博主「广东老周」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhouml_msn/article/details/120178349

本文记录了对一些知识点的理解、操作方法,如有错误,请务必批评指正!!

最终的测试截图:

目录​ 

一、内部FLASH要点

关于地址:

关于解锁:

关于擦除:

关于写入:

二、读取数据

三、存储数据

四、应用示例


一、内部FLASH要点

关于地址:

  1. 内部FLASH地址开始地址:0x0800 0000;
  2. 结束地址:0x08000000+FLASH大小
  3. FLASH的大小,可根据芯片型号得知,如F103x8=64K,  F103xC=256K, F103xE=512K
  4. FLASH的大小,也可读*(uint16_t*)0x1FFFF7E0直接获得;

关于解锁:

  1. 对FLASH寄存器的操作, 需要在操作之前解锁;
  2. 如果解锁过程发生错误,FLASH寄存器操作将死锁至掉电;
  3. 解锁步骤(1): FLASH->KEYR= (uint32_t)0x45670123;
  4. 解锁步骤(2): FLASH->KEYR= (uint32_t)0xCDEF89AB;

关于擦除:

  1. 内部FLASH空间,按页划分成连续的数据块;
  2. 每次擦除的最小单位是:页;
  3. F103中,中小容量FLASH的页(扇区)大小为1K, 而大容量的页大小为2K
  4. 每页擦除时长:中小容量约30ms, 大容量约50ms
  5. 页寿命:中小容量约可擦: 1K次, 大容量约可擦: 10K次
  6. 擦除步骤(1):FLASH->CR|= 1<<1;             // 选择以页进行擦除
  7. 擦除步骤(2):FLASH->AR = 0x0800xxxx;  // 要擦除的页地址
  8. 擦除步骤(3):FLASH->CR|= 0x40;             // 开始擦除
  9. 擦除步骤(4):while((FLASH->SR & 0x01); // 等待空闲,即BSY=0

关于写入:

  1. 写入的地址,必须是偶数;
  2. 每一次写入,必须以半字进行(uint16_t)!单字节或全字将发生错误;
  3. 写入步骤(1):  FLASH->CR |= 0x01<<0;                // 使能可编程
  4. 写入步骤(2):  *(uint16_t*)addr = (uint16_t)value;  // 写入数据  
  5. 写入步骤(3):  while((FLASH->SR & 0x01);           // 等待空闲,即BSY=0
  6. 写入步骤(4):  FLASH->CR &= ((uint32_t)0x00001FFE);  // 关闭编程

二、读取数据

  • 可以按byte读取,也可以按半字、全字方式读取;
  • 读取的方式很简单,如:short value = *(uint16_t*)readAddr;

下面的读取函数,经多次完善,按字节读取,方便匹配奇数数量的数据读取;

/******************************************************************************
 * 函 数:  System_ReadInteriorFlash
 * 功  能: 在芯片的内部FLASH里,读取指定长度数据
 * 参  数: uint32_t  readAddr     数据地址
 *         uint8_t  *pBuffer      读出后存放位置
 *         uint16_t  numToRead    读取的字节数量
 * 返回值: 0_成功    1_失败,地址小于FLASH基址   2_失败,地址大于FLASH最大值
 ******************************************************************************/  
uint8_t  System_ReadInteriorFlash (uint32_t readAddr, uint8_t *pBuffer, uint16_t numToRead) 
{     
    // 获取芯片FLASH大小       
    uint16_t flashSize = *(uint16_t*)(0x1FFFF7E0);                        // 读取芯片FLASH大小;本寄存器值为芯片出厂前写入的FLASH大小,只读单位:KByte
                
    // 判断地址有效性                
    if(readAddr < STM32_FLASH_ADDR_BASE)    return 1;                     // 如果读的地址,小于FLASH的最小地址,则退出
    if(readAddr > (STM32_FLASH_ADDR_BASE+(flashSize*1024)))  return 2;    // 如果读的地址,超出FLASH的最大地址,则退出
              
    // 开始复制                
    while(numToRead--){
        *pBuffer = *(__IO uint8_t*)readAddr;
        pBuffer++;        // 指针后移一个数据长度
        readAddr++;       // 偏移一个数据位
    }      
    
    return 0;             // 成功,返回0;    
}

三、存储数据

1:在存储函数前,需要三个数据的定义:

// 下面这三个定义,用于存取内部FLASH数据,F103系列都不用修改
#ifdef   STM32F10X_HD
#define  STM32_FLASH_SECTOR_SIZE       2048                    // 内部FLASH页大小, 单位:bytes  (注:STM32F10xx系列下,小中容量存储器扇区为1K, 大容量存储器扇区为2K)
#else
#define  STM32_FLASH_SECTOR_SIZE       1024                 // 内部FLASH页大小, 单位:bytes  (注:STM32F10xx系列下,小中容量存储器扇区为1K, 大容量存储器扇区为2K)
#endif

#define  STM32_FLASH_ADDR_BASE   0x08000000                    // 芯片内部FLASH基址(这个基本不用修改)
static   uint8_t sectorbufferTemp[STM32_FLASH_SECTOR_SIZE];    // 开辟一段内存空间,作用:在内部FLASH写入时作数据缓冲

2:等待空闲的函数:

// 作用:内部FLASH写入时,等待空闲,BSY位标志:0闲1忙
static uint8_t waitForFlashBSY(uint32_t timeOut)
{                                                        
    while((FLASH->SR & 0x01) && (timeOut-- != 0x00)) ; // 等待BSY标志空闲
    if(timeOut ==0)   
        return 1;    // 失败,返回1, 等待超时; 
    
    return 0;        // 正常,返回0                
}

3:完整可用的存储函数:

/******************************************************************************
 * 函 数:  System_WriteInteriorFlash
 * 功  能: 在芯片的内部FLASH里,写入指定长度数据
 * 参  数: uint32_t  writeAddr        写入地址,重要:写入地址必须是偶数!!!
 *         uint8_t  *writeToBuffer
 *         uint16_t  numToWrite
 *
 * 返回值: 0_成功,
 *         1_失败,地址范围不正确
 *         2_失败,FLASH->SR:BSY忙超时
 *         3_失败,擦除超时
 ******************************************************************************/  
uint8_t System_WriteInteriorFlash(uint32_t writeAddr, uint8_t *writeToBuffer, uint16_t numToWrite)               
{
    uint16_t flashSize = *(uint16_t*)(0x1FFFF7E0);                // 读取芯片FLASH大小;本寄存器值为芯片出厂前写入的FLASH大小,只读,单位:KByte
                    
    uint32_t addrOff    = writeAddr - STM32_FLASH_ADDR_BASE;      // 去掉0x08000000后的实际偏移地址
    uint32_t secPos     = addrOff / STM32_FLASH_SECTOR_SIZE;;     // 扇区地址,即起始地址在第几个扇区
    uint16_t secOff     = addrOff%STM32_FLASH_SECTOR_SIZE ;       // 开始地始偏移字节数: 数据在扇区的第几字节存放
    uint16_t secRemain  = STM32_FLASH_SECTOR_SIZE - secOff;       // 本扇区需要写入的字节数 ,用于判断够不够存放余下的数据
    
    // 判断地址有效性   
    if(writeAddr < STM32_FLASH_ADDR_BASE)    return 1;                     // 如果读的地址,小于FLASH的最小地址,则退出,返回1_地址失败
    if(writeAddr > (STM32_FLASH_ADDR_BASE+(flashSize*1024)))    return 1;  // 如果读的地址,超出FLASH的最大地址,则退出, 返回1_地址失败
               
    // 0_解锁FLASH
    FLASH->KEYR = ((uint32_t)0x45670123);
    FLASH->KEYR = ((uint32_t)0xCDEF89AB);
    
    if(numToWrite <= secRemain)    secRemain=numToWrite;  
    while(1){    
        // 1_读取当前页的数据
        if(waitForFlashBSY(0x00888888))   return 2;                         // 失败,返回:2, 失败原因:FLASH->SR:BSY忙超时                    
        System_ReadInteriorFlash ( secPos*STM32_FLASH_SECTOR_SIZE+STM32_FLASH_ADDR_BASE , sectorbufferTemp, STM32_FLASH_SECTOR_SIZE );   // 读取扇区内容到缓存
                  
        // 2_擦险指定页(扇区)                           
        if(waitForFlashBSY(0x00888888))   return 2;                         // 失败,返回:2, 失败原因:FLASH->SR:BSY忙超时  
        FLASH->CR|= 1<<1;                                                   // PER:选择页擦除;位2MER为全擦除
        FLASH->AR = STM32_FLASH_ADDR_BASE + secPos*STM32_FLASH_SECTOR_SIZE; // 填写要擦除的页地址
        FLASH->CR|= 0x40;                                                   // STRT:写1时触发一次擦除运作 
        if(waitForFlashBSY(0x00888888))   return 2;                         // 失败,返回:3, 失败原因:擦除超时
        FLASH->CR &= ((uint32_t)0x00001FFD);                                // 关闭页擦除功能   
                                          
        for(uint16_t i=0; i<secRemain ; i++)                                // 原始数据写入缓存
            sectorbufferTemp[secOff+i] = writeToBuffer[i];
       
        for(uint16_t i=0; i<STM32_FLASH_SECTOR_SIZE/2 ; i++){               // 缓存数据写入芯片FLASH                      
            if(waitForFlashBSY(0x00888888))   return 2;                     // 失败,返回:2, 失败原因:FLASH->SR:BSY忙超时
            FLASH->CR |= 0x01<<0;                                           // PG: 编程                             
            *(uint16_t*)(STM32_FLASH_ADDR_BASE + secPos*STM32_FLASH_SECTOR_SIZE +i*2) = (sectorbufferTemp[i*2+1]<<8) | sectorbufferTemp[i*2] ; // 缓存数据写入设备
                                                        
            if(waitForFlashBSY(0x00888888))   return 2;                     // 失败,返回:2, 失败原因:FLASH->SR:BSY忙超时
            FLASH->CR &= ((uint32_t)0x00001FFE) ;                           // 关闭编程
        }
        
        if(secRemain == numToWrite){                          
            break;                                                          // 已全部写入
        }                        
        else{                                                               // 未写完                                                                          
            writeToBuffer += secRemain ;                                    // 原始数据指针偏移
            secPos ++;                                                      // 新扇区
            secOff =0;                                                      // 新偏移位,扇区内数据起始地址            
            numToWrite -= secRemain ;                                       // 剩余未写字节数            
            secRemain = (numToWrite>STM32_FLASH_SECTOR_SIZE)?(STM32_FLASH_SECTOR_SIZE):numToWrite;  // 计算新扇区写入字节数                  
        }              
    } 
    FLASH->CR |= 1<<7 ;                                                     // LOCK:重新上锁    
 
    return 0;                
}

四、应用示例

下面代码中,分别测试了四种数据类型的存储、读取、转换。

注意:string不是独立的数据类型;

    printf("\r\n>>>>开始测试内部FLASH读写,及数据转换:\r\n");         
    
    // 测试1:字符
    uint32_t addrChar   = 0x08000000+38*1024;                                          // 注意地址必须是偶数,且地址段尽量安排在FLASH尾部,避免覆盖了代码段数据
    char writeChar='F';            
    System_WriteInteriorFlash(addrChar, (uint8_t*)&writeChar, 1);                      // 存入数据,函数内自动解锁,擦除,写入
    char readChar=0;                                 
    System_ReadInteriorFlash(addrChar, (uint8_t*)&readChar, 1);                        // 读取数据,函数内自动按半字读取
    printf("测试char     地址:0x%X    写入:%c       读取:%c \r\n", addrChar, writeChar, readChar);
    
    // 测试2:带符号的16位   
    uint32_t addrShort  = 0x08000000+155*1024-2;                                       // 注意地址必须是偶数,且地址段尽量安排在FLASH尾部,避免覆盖了代码段数据
    short writeShort=-888;             
    System_WriteInteriorFlash(addrShort, (uint8_t*)&writeShort, sizeof(writeShort));   // 存入数据,函数内自动解锁,擦除,写入
    short readShort=0;       
    System_ReadInteriorFlash(addrShort, (uint8_t*)&readShort, sizeof(writeShort));     // 读取数据,函数内自动按半字读取
    printf("测试short    地址:0x%X    写入:%d    读取:%d \r\n", addrShort, writeShort, readShort);
  
    // 测试3:无符号的32位
    uint32_t addrUint   = 0x08000000+254*1024;                                         // 注意地址必须是偶数,且地址段尽量安排在FLASH尾部,避免覆盖了代码段数据
    uint32_t writeUint= 0x12345678;
    System_WriteInteriorFlash(addrUint, (uint8_t*)&writeUint, 4);                      // 存入数据,函数内自动解锁,擦除,写入
    uint32_t readUint = 0;
    System_ReadInteriorFlash(addrUint, (uint8_t*)&readUint, 4);                        // 读取数据,函数内自动按半字读取
    printf("测试uint     地址:0x%X    写入:0x%X     读取:0x%X \r\n", addrUint, writeUint, readUint);
  
    // 测试4:字符串
    uint32_t addrString   = 0x08000000+166*1024-6;                                     // 注意地址必须是偶数,且地址段尽量安排在FLASH尾部,避免覆盖了代码段数据
    char writeString[100]="早吖! 去哪呢?";     
    System_WriteInteriorFlash(addrString, (uint8_t*)writeString, sizeof(writeString)); // 存入数据,函数内自动解锁,擦除,写入
    char readString[100];
    System_ReadInteriorFlash(addrString, (uint8_t*)readString, sizeof(readString));    // 读取数据,函数内自动按半字读取
    printf("测试string   地址:0x%X   写入:%s  读取:%s \r\n", addrString, writeString, readString);
    

之前建了个Q群,玩STM32的朋友,可以一起吹吹水:262901124.

版权声明:本文为CSDN博主「广东老周」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhouml_msn/article/details/120178349

生成海报
点赞 0

广东老周

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32 --- 使用内部FLASH存储数据

本文记录了对一些知识点的理解、操作方法,如有错误,请务必批评指正!! 最终的测试截图: 目录​  一、内部FLASH要点 关于地址: 关于解锁&#xf

基于STM32的指纹密码锁

设计简介: 本设计是基于单片机的指纹密码锁,主要实现以下功能: 矩阵按键输入密码,并通过按键显示*号可通过按键或手机开门密码可通过按键进行开门可通过蓝牙模块连接手机进行开门可通过指纹进