找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3675|回复: 0
打印 上一主题 下一主题
收起左侧

单片机W25X16读写程序

[复制链接]
跳转到指定楼层
楼主
ID:148457 发表于 2016-11-17 14:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
51单片机读写25X16程序,简单昨懂
全部源码下载:
51读写W25X16程序.rar (45.03 KB, 下载次数: 54)

预览:

  1. #include <intrins.h>  //包含位移和_nop_();
  2. #include "STC12C5A60S2.H"

  3. //***************************************************************

  4. void WriteDisable (void); //写禁止
  5. void WriteEnable  (void); //写允许
  6. unsigned char W25X_BUSY_OrNot (void); //判忙碌
  7. void W25X_ChipErase(void);  //片擦除
  8. void W25X_BlockErase(unsigned long Addre24);
  9. void W25X_SectorErase(unsigned long Addre24);        //擦除资料图示的4KB空间
  10.                                                                                                                                                  //读数据可以无限次,这里是由缓冲决定的大小
  11. void W25X_Flash_Byte_Read (unsigned long Addre24,unsigned char Quantity);//多字节读FLASH(1~256)  -W25X32-000000-3FFF00(4M)-
  12. void W25X_Flash_Byte_Write(unsigned long Addre24,unsigned char Quantity); //往FLASH里写一个或多个字节(小于256字节)

  13. unsigned char Read_OneByte(void);          //从SPI收8位数
  14. void Send_OneByte(unsigned char DATA8);
  15. void InitSerial(void);  //串行口初始化.通信速率9600bps 在22.1184MHz晶振频率        
  16. void Delay100ms(unsigned int _100ms); //100ms级延时

  17. //进度: 发一个指令OK 写允许OK 读状态OK 读写一个字节OK        

  18. unsigned char xdata Send_DATA[256];         //要发送的数据
  19. unsigned char xdata Recv_DATA[256];         //已接收的数据, 如2个数,则为Recv_DATA[0] Recv_DATA[1]
  20. unsigned char * Send_Pionter;
  21. unsigned char * Recv_Pionter;

  22. void main()         
  23.   {
  24.   unsigned char    BUSY;           //判忙碌
  25.   unsigned long Addre24;           //24位的Flash地址
  26.   unsigned char  x=0;
  27.   unsigned char  A;
  28.   unsigned char  B;
  29.   unsigned char  C;
  30.   unsigned long  D;

  31. //************************
  32.   A=0; B=0; C=0; D=0;
  33.   Delay100ms(2);
  34.   if(x)
  35.          {               
  36.          WriteDisable ();            //写禁止

  37.      W25X_ChipErase();                  //片擦除
  38.      W25X_SectorErase(Addre24);  //4K擦除                                                         
  39.      W25X_BlockErase (Addre24);  //64K块擦除

  40.      BUSY=W25X_BUSY_OrNot();        //判忙碌
  41.      W25X_Flash_Byte_Read (Addre24,21); //读FLASH
  42.      W25X_Flash_Byte_Write(Addre24,21);  //写入
  43.      }
  44. //*************************
  45.   P1M0=0xB0;
  46.   InitSerial();  //串行口初始化.通信速率9600bps 在22.1184MHz晶振频率

  47.   Send_Pionter = &Send_DATA[0];  //发送指针取地址
  48.   Recv_Pionter = &Recv_DATA[0];  //接收指针取地址

  49.   for (D=0;D<256;D++)
  50.      {
  51.         Send_DATA[D]=D;
  52.         Recv_DATA[D]=0;
  53.          }

  54.   W25X_SectorErase(Addre24); Delay100ms (4); //4K擦除  
  55.                   
  56. //**************************

  57.   W25X_Flash_Byte_Write(0x000000,255);  //写N个数
  58.   W25X_Flash_Byte_Read (0x000000,255);  //读X个数
  59.   

  60.   while(1)
  61.     {

  62.    SBUF  =A;
  63.    while(TI==0);
  64.    TI=0;
  65.    SBUF  =Recv_DATA[A] ;
  66.    while(TI==0);
  67.    TI=0;
  68.    Delay100ms(1);
  69.    A++;

  70.         }                           
  71.   }        // End of Main

  72. //*******************END of Main****************************



  73. //   ----W25X系统Flash读写---SUNYA注----
  74. //sbit CS          = P1^4;        //选通  
  75. //sbit DIO         = P1^5;  //单片机输出
  76. //sbit DO          = P1^6;        //FLASH输出
  77. //sbit SCLK        = P1^7;        //时钟
  78. //读写SPI口模拟模式3,时钟平时为高电平

  79. //#define W25X_ReadStatus       0x05                //读状态寄存器
  80. //#define W25X_WriteStatus      0x01                //写状态寄存器
  81. //#define W25X_ReadDATA8        0x03                //普读_数据
  82. //#define W25X_FastRead         0x0B                //快读_数据
  83. //#define W25X_DualOutput       0x3B                //快读_双输出
  84. //#define W25X_Write            0x02                //写_数据_0~255个字节
  85. //#define W25X_S_Erase          0x20                //扇区擦除4KB
  86. //#define W25X_B_Erase          0xD8                //块区擦除64KB
  87. //#define W25X_C_Erase          0xC7                //整片格式化
  88. //#define W25X_PowerDown        0xB9                //待机
  89. //#define W25X_PowerON_ID       0xAB                //开机或是读ID
  90. //#define W25X_JEDEC_ID         0x9F                //十六位的JEDEC_ID
  91. //#define W25X_WriteEnable      0x06                //写充许
  92. //#define W25X_WriteDisable     0x04                //写禁止

  93. //#define W25X_BUSY             0x01                //FLASH忙
  94. //#define W25X_NotBUSY          0x00                //FLASH闲        这是自定义的

  95. //***************判BUSY********************************
  96. unsigned char W25X_BUSY_OrNot (void) //在读和写之前得先判断FLASH是否BUSY
  97.    {                                         //BUSY的原因是擦除,或是连续读写
  98.    unsigned char k;          //如果没有以上方式,不必判定可以写读  

  99.    SCLK=1;
  100.    _nop_();
  101.    CS=0;
  102.    Send_OneByte(W25X_ReadStatus);  //读状态寄存器
  103.    k=Read_OneByte();  //读一个字节
  104.    k=k&0x01;
  105.    CS=1;_nop_();
  106.    SCLK=1;
  107.    if(k)return (W25X_BUSY);
  108.    else return (W25X_NotBUSY);
  109.    }        //end of check BUSY
  110. //***********************************************
  111. void W25X_Flash_Byte_Write(unsigned long Addre24,unsigned char Quantity)    //往FLASH里写一个或多个字节(小于255)
  112.    {                                                 //连续写的时候,地址最后八位必须从00开始写                 *如果256个字节都读满或写满,三字节地址最后一个字节必须为0*
  113.    unsigned char Addre3;         //否则当地址越过分面时,会从本页的00从新开始,造成错写
  114.    unsigned char Addre2;         //^^现在本函数没启用连写连读
  115.    unsigned char Addre1;
  116.    unsigned char J;   //计字节数
  117.    unsigned char x;

  118.    while(W25X_BUSY_OrNot ());  //判BUSY        等到Flash闲才能操作

  119.    WriteEnable();   //写允许
  120.    SCLK=1;
  121.    Addre1=Addre24;
  122.    Addre24=Addre24>>8;
  123.    Addre2=Addre24;
  124.    Addre24=Addre24>>8;
  125.    Addre3=Addre24;                    //把地址拆开来
  126.    
  127.    CS=0;
  128.    Send_OneByte(W25X_Write);  //命令
  129.    Send_OneByte(Addre3);
  130.    Send_OneByte(Addre2);
  131.    Send_OneByte(Addre1);

  132.    for (J=0;J<Quantity;J++)
  133.      {
  134.      Send_OneByte(Send_DATA[J]); //写字节
  135.            }

  136.    CS=1;
  137.    _nop_();_nop_();
  138.    SCLK=1;
  139.    for(x=0;x<200;x++) //延时一点点
  140.      {
  141.      _nop_();_nop_();
  142.      }
  143.    Addre24=0;  //地址清0

  144.    }         //写FLASH结束

  145. //***********************************************

  146. void W25X_Flash_Byte_Read (unsigned long Addre24,unsigned char Quantity)  //从Flash里读出小于256字节数
  147.    {
  148.    unsigned char xdata DATA8[256];  //要返回的字节
  149.    unsigned char * DATA;  //定义一个指针

  150.    unsigned char J;         //计字节数
  151.    unsigned char Addre3;
  152.    unsigned char Addre2;
  153.    unsigned char Addre1;
  154.    
  155.    while(W25X_BUSY_OrNot ());  //判BUSY

  156.    DATA=&DATA8[0]; //指针指向DATA8[256]

  157.    Addre1=Addre24;
  158.    Addre24=Addre24>>8;
  159.    Addre2=Addre24;
  160.    Addre24=Addre24>>8;
  161.    Addre3=Addre24;                 //把地址拆开来
  162.    
  163.    CS=0;
  164.    Send_OneByte(W25X_ReadDATA8);//命令读
  165.    Send_OneByte(Addre3);
  166.    Send_OneByte(Addre2);
  167.    Send_OneByte(Addre1);

  168.    for (J=0;J<Quantity;J++)
  169.      {
  170.      Recv_DATA[J]=Read_OneByte();         //读一个字节
  171.          }

  172.    CS=1;
  173.    _nop_();_nop_();
  174.    SCLK=1;
  175.    _nop_();_nop_();
  176.    Addre24=0;  //地址清0
  177.    }          //读FLASH结束

  178. //*********************************************** OK

  179. void Send_OneByte(unsigned char DATA8) //从SPI发8位数
  180.    {                                                                  //上升沿写入
  181.    unsigned char x;
  182.      
  183.    for (x=0;x<8;x++)
  184.      {
  185.          SCLK=0;
  186.          if(DATA8&0x80)DIO=1;
  187.          else DIO=0;
  188.          SCLK=1;
  189.          DATA8=DATA8<<1;
  190.          }
  191.        //发完后SCLK为1
  192.    }  //end of Send_OneByte

  193. //***********************************************  OK
  194. unsigned char Read_OneByte(void)     //从SPI收8位数
  195.    {                                                         //下降沿输出
  196.    unsigned char DATA8;
  197.    unsigned char x;

  198.    SCLK=1;
  199.    DATA8=0x00;
  200.    for (x=0;x<8;x++)
  201.      {
  202.          _nop_();
  203.          SCLK=0;
  204.          DATA8=DATA8<<1;
  205.          if(DO)DATA8=DATA8|0x01;
  206.          SCLK=1;         
  207.          }
  208.    return (DATA8);
  209.     //完成后SCLK=1
  210.    }//end of Read_OneByte

  211. //**************片擦除 (MAX_80S)****************** OK
  212. void W25X_ChipErase(void)
  213.   {
  214.   //BUSY ?
  215.   WriteEnable();   //写允许
  216.   SCLK=1;
  217.   CS=0;
  218.   Send_OneByte(W25X_C_Erase);//整片擦除命令
  219.   CS=1;          //从CS=1时开始执行擦除
  220.   SCLK=1;  
  221.   }

  222. //*************** 4K扇擦除************************ OK
  223. void W25X_SectorErase(unsigned long Addre24)        //擦除资料图示的4KB空间
  224.   {
  225.    //判BUSY或许放这里
  226.    unsigned char Addre3;
  227.    unsigned char Addre2;
  228.    unsigned char Addre1;

  229.    WriteEnable();   //写允许
  230.    Addre1=Addre24;
  231.    Addre24=Addre24>>8;
  232.    Addre2=Addre24;
  233.    Addre24=Addre24>>8;
  234.    Addre3=Addre24;                 //把地址拆开来

  235.    SCLK=1;
  236.    CS=0;
  237.    Send_OneByte(W25X_S_Erase);//整扇擦除命令
  238.    Send_OneByte(Addre3);
  239.    Send_OneByte(Addre2);
  240.    Send_OneByte(Addre1);
  241.    CS=1;
  242.    _nop_();
  243.    SCLK=1;
  244.    _nop_();_nop_();
  245.    Addre24=0;  //地址清0
  246.   }
  247. //*************** 64K页/块擦除************************* OK
  248. void W25X_BlockErase(unsigned long Addre24)        //擦除资料图示的64KB空间
  249.   {
  250.    //判BUSY或许放这里
  251.    unsigned char Addre3;
  252.    unsigned char Addre2;
  253.    unsigned char Addre1;

  254.    WriteEnable();   //写允许
  255.    Addre1=Addre24;
  256.    Addre24=Addre24>>8;
  257.    Addre2=Addre24;
  258.    Addre24=Addre24>>8;
  259.    Addre3=Addre24;                 //把地址拆开来

  260.    SCLK=1;
  261.    CS=0;
  262.    Send_OneByte(W25X_B_Erase);//整扇擦除命令
  263.    Send_OneByte(Addre3);
  264.    Send_OneByte(Addre2);
  265.    Send_OneByte(Addre1);
  266.    CS=1;
  267.    _nop_();_nop_();
  268.    SCLK=1;
  269.    _nop_();_nop_();
  270.    Addre24=0;  //地址清0
  271.   }
  272. //*************** 写允许 ****************************  OK
  273. void WriteEnable  (void)
  274.    {
  275.    SCLK=1;
  276.    CS=0;
  277.    Send_OneByte(W25X_WriteEnable);  
  278.    CS=1;
  279.    SCLK=1;
  280.    }
  281. //*************** 写禁止 ****************************        OK
  282. void WriteDisable (void)
  283.    {
  284.    SCLK=1;
  285.    CS=0;
  286.    Send_OneByte(W25X_WriteDisable);  
  287.    CS=1;
  288.    SCLK=1;
  289.    }

  290. //******************************************************** OK
  291. void Delay100ms(unsigned int _100ms) //100ms级延时
  292. {
  293.    unsigned char n,i,ms,loop;
  294.    for(loop=12;loop>0;loop--)  //STC12C5412AD为快速单片机,此100ms延时要快6倍
  295.      {  ms=_100ms;            //晶体为11.0592MHz
  296.         for(;ms>0;ms--)
  297.           for(n=145;n>0;n--)
  298.             for(i=251;i>0;i--)_nop_();
  299.      }
  300. }


  301. //***************************************//串行口初始化                OK
  302. void InitSerial(void)  //串行口初始化.通信速率9600bps 在22.1184MHz晶振频率
  303. {
  304.         SCON = 0x50;
  305.         BRT  = 250;
  306.         AUXR = 0x11;                        //使用独立波特率发生器
  307.         AUXR1= 0x80;
  308.         ES=1;
  309.         EA=1;
  310. /*   
  311.                 TR1=0;
  312.     ET1=0;            //定时器1禁止中断
  313.     TMOD=TMOD&0xCF;
  314.     TMOD=TMOD|0x20;   //通信方式2
  315.     TH1=0xFF;         //波特率:bps
  316.     TL1=0xFF;         //1位起始位,8位数据位,2位停止位,无校验
  317.     SCON=0xD8;
  318.     PCON=0x80;
  319.     TR1=1;                   //开启定时
  320.     ES=1;
  321. */
  322.     //IE=IE|0x90;    //开中断,允许串口中断
  323. }
  324. //***************************************************************
复制代码

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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