[开发资料] 单片机内部FLASH的字节操作

[复制链接]
505|7
 楼主| uiint 发表于 2025-3-24 10:00 | 显示全部楼层 |阅读模式
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>//C语言标准库
  4. #include "flash.h"

  5. #define USER_FLASH_START_ADDR   0x01070000   //FLASH最后两个扇区  供用户使用


  6. u32tou8 u32data;//定义一个联合体

  7. //==================================================================================
  8. // 获取某个地址所在的页首地址
  9. // addr:FLASH地址
  10. // 返回:该地址所在的页 共128页(0~127)
  11. //==================================================================================
  12. unsigned int FLASH_GetFlashPage(unsigned int addr)
  13. {
  14.           if (IS_FLASH_ADDRESS(addr))
  15.                 {
  16.                    return  (addr&(~0xFFF));//清0低12位就是该页的起始地址
  17.           }
  18. }
  19. //==================================================================================
  20. // 从FLASH中读取 一个字(32位)
  21. // addr:读取地址
  22. // 返回: 读到的字数据
  23. //备注: 地址为4字节对齐
  24. //==================================================================================
  25. unsigned int FLSAH_ReadWord(unsigned int addr)
  26. {
  27.     return (*(unsigned int *)addr);
  28. }


  29. //==================================================================================
  30. //从FLASH指定地址 读取数据
  31. //备注: 读取数据类型为32位  读取地址为4字节对齐
  32. //==================================================================================
  33. void  FLASH_Read(unsigned int        ReadAddr,unsigned char *pBuffer,unsigned int NumToRead)
  34. {
  35.     unsigned int i;
  36.           u32tobyte cache;
  37.     for(i=0; i<NumToRead; i+=4)
  38.     {
  39.             cache.u32data=FLSAH_ReadWord(ReadAddr+i);
  40.                                     pBuffer[i]=cache.buf[0];
  41.                                            pBuffer[i+1]=cache.buf[1];
  42.                                           pBuffer[i+2]=cache.buf[2];
  43.                                           pBuffer[i+3]=cache.buf[3];
  44.     }
  45. }

  46. //==================================================================================
  47. // 向FLASH指定地址 写入大量数据
  48. // WriteAddr:写入首地址
  49. // pBuffer:数据首地址
  50. // NumToWrite:需要写入数据的大小
  51. // 返回: 4=成功  1,2,3,5=失败
  52. // 备注:
  53. //==================================================================================
  54. FLASH_Status  FLASH_Write(unsigned int        WriteAddr,unsigned char *pBuffer,unsigned int NumToWrite)
  55. {

  56.     FLASH_Status status = FLASH_COMPLETE;
  57.           u32tobyte cache;//联合体定义
  58.     unsigned int startaddr,endaddr,pageaddr=0;
  59.           unsigned char buffer[4096];//4K缓冲区 对应FALSH 1页
  60.           unsigned int i;
  61.           unsigned int index,remain;
  62.     startaddr = WriteAddr;
  63.     endaddr = startaddr+NumToWrite;//结束地址
  64.        
  65.     FLASH_Unlock();
  66.     FCU->RO = 0;//去掉所有扇区写保护
  67.     //==================================================================================
  68.     // 判断写入地址是否非法  起始地址或者结束地址不在FALSH范围内则退出
  69.     //==================================================================================
  70.     if(!(IS_FLASH_ADDRESS(startaddr)&& IS_FLASH_ADDRESS(endaddr))) return FLASH_ERROR_PG;
  71.    
  72.            while(startaddr < endaddr)
  73.                  {
  74.                          
  75.                 //==================================================================================
  76.     //1.计算起始地址在FALSH哪一页,并获取该页的首地址
  77.                 //2.计算起始地址在该页的偏移量
  78.     //3.计算该页还剩余多少字节没写入数据                         
  79.     //==================================================================================
  80.                           pageaddr = FLASH_GetFlashPage(startaddr);//获取起始地址所在页的页首地址
  81.                           index = startaddr-pageaddr;//4K缓冲区内偏移地址
  82.                           remain=4096-index;//缓存区剩余大小
  83.     //==================================================================================
  84.     // 将该页数据读入4K缓冲数组,后面读写都是对该缓冲数组操作
  85.     //==================================================================================                         
  86.                     for(i=0;i<4096;i+=4)//读取一页到缓冲buff
  87.                           {
  88.                                     cache.u32data=FLSAH_ReadWord(pageaddr+i);
  89.                                     buffer[i]=cache.buf[0];
  90.                                            buffer[i+1]=cache.buf[1];
  91.                                           buffer[i+2]=cache.buf[2];
  92.                                           buffer[i+3]=cache.buf[3];
  93.                                 }
  94.     //==================================================================================
  95.     // 擦除FALSH对应的页,FLASH只能按页擦除,
  96.                 // 这一页数据已经被读到缓冲数组中了 之前的数据也保留下来了                
  97.     //==================================================================================                               
  98.                                 status = FLASH_ErasePage(startaddr);
  99.         if(status != FLASH_COMPLETE) return status;//擦除1页 4K字节                                       
  100.     //==================================================================================
  101.     //1.判断要写入的数据是否大于该页剩余容量(即计算写入的数据长度是否跨多页)
  102.                 //2.将需要写入的数据转存到缓冲数据               
  103.     //==================================================================================                               
  104.                                 if(NumToWrite > remain)//需要写入的数据量大于缓冲buf剩余字节数
  105.                                 {
  106.                                         for(i=index;i<4096;i++)//将需要写入FALSH的数据写入缓冲buff
  107.                                         {
  108.                                                          buffer[i]=*(pBuffer++);                               
  109.                                         }
  110.                                         NumToWrite-=remain;//需要写入的数据长度-本次已经写入的数据长度       
  111.           startaddr+=remain;//地址向后偏移本次写入的字节数                                       
  112.                           }
  113.                                 else
  114.                                 {
  115.                                   for(i=index;i<NumToWrite+index;i++)//将需要写入FALSH的数据写入缓冲buff
  116.                                         {
  117.                                                          buffer[i]=*(pBuffer++);                               
  118.                                         }
  119.           startaddr+=NumToWrite;//地址向后偏移本次写入的字节数                                                               
  120.                                 }       
  121.     //==================================================================================
  122.     // 将缓冲数组(4K)写入FLASH 对应的页
  123.                 // 此处必须从页首写入,因为缓冲数组正好4K,对应FALSH 1页       
  124.     //==================================================================================                               
  125.                                 for(i=0;i<4096;i+=4)//将缓冲buffer写入 FALSH
  126.                           {
  127.                                     cache.buf[0]=buffer[i];
  128.                                            cache.buf[1]=buffer[i+1];
  129.                                           cache.buf[2]=buffer[i+2];
  130.                                           cache.buf[3]=buffer[i+3];
  131.                                        
  132.                                           if((status=FLASH_ProgramWord(pageaddr+i,cache.u32data))!= FLASH_COMPLETE)
  133.                                                 {
  134.                                                                 FLASH_Lock();
  135.                                                                 return status;//写入失败 FLASH上锁
  136.                                                 }                                                                    
  137.                                 }                       
  138.                  }
  139.     FLASH_Lock();
  140. }


tpgf 发表于 2025-4-8 16:25 | 显示全部楼层
单片机内部FLASH的字节操作包括读、写和擦除三种基本操作。在进行这些操作时,需要特别注意地址对齐、锁定位的处理以及写入和擦除的最小单位等问题
xiaoqizi 发表于 2025-4-11 19:11 | 显示全部楼层
可以直接从任意地址开始读取一个字节的数据
木木guainv 发表于 2025-4-11 21:01 | 显示全部楼层
并非所有单片机都支持单字节写入。对于支持单字节写入的单片机,需要按照特定的步骤进行,如选择适当的时钟源和分频因子、清除LOCK位、判断BUSY位等
Jiangxiaopi 发表于 2025-4-11 22:49 | 显示全部楼层
字写入是一种常见的写入方式,通常用于写入较大的数据块。同样需要遵循特定的写入步骤

荣陶陶 发表于 2025-4-12 19:41 | 显示全部楼层
FLASH存储器的擦除操作通常是以段为单位进行的。不同型号的单片机其段的大小可能不同
Zhiniaocun 发表于 2025-4-12 21:31 | 显示全部楼层
某些单片机支持多段模块擦除功能,可以同时擦除多个段
LOVEEVER 发表于 2025-4-20 16:03 | 显示全部楼层
片机内部FLASH的字节操作包括读、写和擦除三种基本操作。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

59

主题

4538

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部