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

单片机期末不挂科,看这一篇就够了

第一章 单片机概述 单选题知识点 1.MCU:单片机 EMPU:嵌入式微处理器 2.使用二进制的主要原因是 受器件的物理性能限制 3.手机中的双核是指: EMPU DSP 4.单片机与普通微型