找回密码
 立即注册
查看: 666|回复: 0

基于STC32G12K128实验箱V9.62_实验之片外部Flash存储器读写

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:493
  • 最近打卡:2025-05-01 08:31:58

30

主题

347

回帖

3476

积分

荣誉版主

积分
3476
发表于 2024-6-30 21:52:18 | 显示全部楼层 |阅读模式
本帖最后由 浦江一水 于 2024-6-30 21:57 编辑

基于STC32G12K128实验箱V9.62_实验之片外部Flash存储器读写

W25Qxx芯片Flash存储器,存储容量大,接口简单,在单片机项目中被广泛使用。
STC32G12K128实验箱V9.62,搭载了一片W25Q40的外部Flash存储器芯片,容量为512K字节,扇区大小为256字节。
学习和掌握此芯片的读写,无疑是必备的基本功了。
然而此类存储器与STC内部EEPROM的读写有一个共同特点,那就是可以将1写成0,而不能将0写成1,也就是只能通过擦除,将0变成1,且擦除必须是按整扇区进行。
因此,读写时要倍加小心注意了,要避免后写入数据时,将前写入的同扇区数据清除掉。
本实验尝试优化算法,以实现在芯片地址范围内,任意地址和长度的写入和读出,自动判空和识别是否需要擦除扇区,以确保写入数据不被无意擦除。
本实验依然采用官方例程的对话方式, 用实验箱串口2与上位机通讯(不使用实验箱的显示设备),实际对话操作如截图所示:
读写W25Q40实验.jpg

主程序如下:
//********************************************************************************
// 名称: Main.C  通过串口2 STC32G12K128 读写外部Flash存储器
// 基于: STC32G12K128 V9.62 实验箱
// 实验: .../STC-USB-Link1D仿真器调试...
// 编程: 浦晓明(浦江一水) 2023-12-14
//********************************************************************************
#include "STC32G_SYS.H"
#include "STC32G_UART.H"
#include "W25Q40.H"


/** 全局变量说明 设为全局,便于调试观察... **************/
u16 W25Q40_ID;        //设备ID
u32 T_Addr;           //目标地址
u8  R_Buf[256];       //读取数据缓存
extern u8 F_Buf[256]; //扇区缓存
//========================================================================
// 函数: void  delay_ms(unsigned int ms)
// 描述: 毫秒级延时函数。 @22.1184MHz
// 参数: ms,要延时的ms数,自动适应主时钟.
//=====================================================================
void  delay_ms(unsigned int ms)
{ unsigned int i;
  do{ i = MAIN_Fosc / 6000;
      while(--i);
    } while(--ms);
}
/**** 主函数入口 ************************/
void main(void)
{ u8 ch,n,ts=1;
  u16 i,len;
  SYS_Init();              //系统初始化
  UART2_Init(1,1,115200);  //IO切换1,模式1,波特率115200
  W25Q40_Init();
  W25Q40_ID=W25Q40_ReadID(); //读取ID(验证设备是否存在)
  //  printf("STC32G UART2 Test Printf(x)...\r\n");        //测试 printf 发送一个字符串
  //  UART2_SendStr("UART2_SendStr(x)...OK!\r\n");   //测试字符串发送函数:UART2_SendStr()...
  //主循环...
  while(1)
  { if(ts)
    { //实验操作提示...
      printf("\r\n** STC32G单片机对外部Flash_W25Q40读写实验 **\r\n");
      printf("- 实验箱_USART2(RS232)串口连接PC机串口.波特率115200,8,1,N\r\n");
      printf("- PC机使用串口助手,串口命令例\xfd举如下:(无需回车换行)\r\n");   
      printf("E 0x000020            --> 删除\xfd字节地址0x000020所在扇区.\r\n");
      printf("W 0x000020 ABCDE12345 --> 写入地址0x000020字符串ABCDE12345\r\n");
      printf("R 0x000020 10       --> 读出地址0x000020指定长度字节.\r\n");   
      printf("读写地址范围: 0x000000 -- 0x07FFFF (512K)\r\n\r\n");
      ts=0;
    }
    delay_ms(10);
    if(RX2_Cnt>=10)          //串口2收到指令信息...
    { for(i=0;i<8;i++)
      { if((RX2_Buf >= 'a') && (RX2_Buf <= 'z'))RX2_Buf -= 0x20; } //小写转大写
      if(((RX2_Buf[0]=='E')||(RX2_Buf[0]=='W')||(RX2_Buf[0]=='R'))&&(RX2_Buf[1]==' '))
      { //解析地址...
        ch=RX2_Buf[4]-0x30; if(ch>9)ch=ch-0x07; T_Addr=(u32)ch;
        ch=RX2_Buf[5]-0x30; if(ch>9)ch=ch-0x07; T_Addr=16*T_Addr+(u32)ch;
        ch=RX2_Buf[6]-0x30; if(ch>9)ch=ch-0x07; T_Addr=16*T_Addr+(u32)ch;
        ch=RX2_Buf[7]-0x30; if(ch>9)ch=ch-0x07; T_Addr=16*T_Addr+(u32)ch;
        ch=RX2_Buf[8]-0x30; if(ch>9)ch=ch-0x07; T_Addr=16*T_Addr+(u32)ch;
        ch=RX2_Buf[9]-0x30; if(ch>9)ch=ch-0x07; T_Addr=16*T_Addr+(u32)ch;
        //解析指令
        switch(RX2_Buf[0])
        { case 'E': W25Q40_SectorErase(T_Addr);
                       printf("OK! Sector Erase.\r\n");
                       break;
          case 'W': n=RX2_Cnt-11;   //取指令数据长度
                       W25Q40_Write(T_Addr,RX2_Buf+11,n);
                       printf("OK! Write %2d Byte.\r\n",n);
                       break;
          case 'R': n=RX2_Cnt-11; len=0;  //取指令数据长度
                      for(i=0;i<n;i++)      //取需要读取的数据长度  
                      { ch=RX2_Buf[11+i];
                        if((ch>='0')&&(ch<='9'))len=10*len+RX2_Buf[11+i]-'0';
                        else break;
                      }
                      if(len>256)len=256;
                      W25Q40_Read(T_Addr,R_Buf,len);
                      printf("OK! Read out %3d Bytes:\r\n",len);
                      for(i=0;i<len;i++)UART2_SendChar(R_Buf);
                      UART2_SendChar(0x0D); UART2_SendChar(0x0A);
                      break;
        }

      } else { printf("指令错误!!\r\n"); ts=1; }
      RX2_Cnt=0;RX2_Buf[0]=0;     //计数清零
    }  
  }
}

相关存储器读写算法的W25Q40.C/H文件, 包含于工程包中,供有兴趣的爱好者参考。
07-TestW25Q40.rar (45.76 KB, 下载次数: 99)




回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:19 , Processed in 0.130963 second(s), 48 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表