微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > STC15F2K16S2单片机利用SPI功能与片外Flash读写程序就能读写255字节(第一页)

STC15F2K16S2单片机利用SPI功能与片外Flash读写程序就能读写255字节(第一页)

时间:10-02 整理:3721RD 点击:
大神们,帮忙看看不知道问题出在哪了,就能读写第一页 一共255 字节 当读写第二页时候,发现回来的都是0XFF,第一页数据读写正常

//用SPI查询方式将音频文件通过SPI存入到flash芯片里,写一整页(256bytes)
#include "STC15F2K60S2.h"
typedef bit BOOL;
#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long
#define FALSE           0
#define TRUE            1
uchar flag=0;
uchar ii=0;
uchar   g_Buffer[255];                                //Flash读写缓冲区
uchar   g_Buffer1[255];                                //Flash读写缓冲区
sbit CS=P1^1;                                         //Mx25L片选信号
BOOL g_fFlashOK;                                      //Flash状态
//====================STC15F2K16S2的SPI寄存器====================
#define SPI_S0          0x04
#define SPI_S1          0x08
#define SPIF            0x80                          //SPSTAT.7
#define WCOL            0x40                          //SPSTAT.6
#define SSIG            0x80                          //SPCTL.7
#define SPEN            0x40                          //SPCTL.6
#define DORD            0x20                          //SPCTL.5
#define MSTR            0x10                          //SPCTL.4
#define CPOL            0x08                          //SPCTL.3
#define CPHA            0x04                          //SPCTL.2
#define SPDHH           0x00                          //CPU_CLK/4
#define SPDH            0x01                          //CPU_CLK/16
#define SPDL            0x02                          //CPU_CLK/64
#define SPDLL           0x03                          //CPU_CLK/128
#define ESPI            0x02                          //IE2.1
//================Mx25l8005的flash存储器指令码===================
#define SFC_WREN        0x06                          //Write Enable
#define SFC_WRDI        0x04                                              //Write Disable
#define SFC_RDSR        0x05                                              //Read  status register
#define SFC_WRSR        0x01                                              //Write status register
#define SFC_READ        0x03                                              //Read  data
#define SFC_FASTREAD    0x0b                                              //Fast  read         data
#define SFC_PAGEPROG    0x02                                              //Page  Program
#define SFC_SECTORER    0x20                                              //Sector Erase
#define SFC_BLOCKER     0xd8                                              //Block  Erase
#define SFC_CHIPER      0xc7                                              //Chip   Erase
#define SFC_RDID                0x9f                          //Read idenification
//=================页面地址======================================
#define Mx25L8005_BLOCK0    0x000000
#define Mx25L8005_BLOCK1    0x010000
#define Mx25L8005_BLOCK2    0x020000
#define Mx25L8005_BLOCK3    0x030000
#define Mx25L8005_BLOCK4    0x040000
#define Mx25L8005_BLOCK5    0x050000
#define Mx25L8005_BLOCK6    0x060000
#define Mx25L8005_BLOCK7    0x070000
#define Mx25L8005_BLOCK8    0x080000
#define Mx25L8005_BLOCK9    0x090000
#define Mx25L8005_BLOCKA    0x0a0000
#define Mx25L8005_BLOCKB    0x0b0000
#define Mx25L8005_BLOCKC    0x0c0000
#define Mx25L8005_BLOCKD    0x0d0000
#define Mx25L8005_BLOCKE    0x0e0000
#define Mx25L8005_BLOCKF    0x0f0000
//======================串口初始化===============================
void uart_init()
{
          AUXR=0x40;                                          //定时器1速度是传统8051的12倍
          TMOD&=0x0f;                                         //设置T1定时器为工作模式0 16位自动装载  
          TL1=0xe0;                                           //设置波特率为9600
          TH1=0xfe;
          SM0=0;                                              //设置SCON 串口模式1 8位UART
          SM1=1;            
          TR1=1;                                                      //开启T1定时器
          REN=1;                                                      //允许串行接收
          ET1=0;                                                                       //关闭T1定时器
          EA=1;                                                                              //打开总中断
          ES=1;                                               //打开串口中断
}
//======================Spi初始化================================
void InitSpi()
{
      ACC = P_SW1;                                        //切换到第一组SPI
      ACC &= ~(SPI_S0 | SPI_S1);                          //SPI_S0=0 SPI_S1=0
      P_SW1 = ACC;                                        //(P1.2/SS, P1.3/MOSI, P1.4/MISO, P1.5/SCLK)
          SPSTAT = SPIF | WCOL;                               //清除SPI状态
      SPCTL = SSIG | SPEN | MSTR |CPHA |CPOL|SPDHH;       //设置SPI为主模式,CPHA=1,CPOL=1,CPU_CLK/4
}
//================写一个字节数据(对单片机操作)===================
void SpiWrite(uchar byte)
{
      SPSTAT =SPIF | WCOL;                                //清除SPI状态
      SPDAT=byte;                                                                                  //写一字节数据
      while (!(SPSTAT & SPIF ));                          //等待SPI数据传输完成
}
//================读一个字节数据(对单片机操作)===================
uchar SpiRead()
{
      SPSTAT=SPIF | WCOL;                                 //传输初始化
      SPDAT=0xff;                                                                          //随意发送一字节数据
      while (!(SPSTAT & SPIF));                           //等待SPI数据传输完成
      return SPDAT;
}
//================检查Flash是否为忙(等于1即为忙)=================
BOOL IsFlashBusy()
{
             uchar dat=0;  
      CS = 0;
      SpiWrite(SFC_RDSR);                                 //发送读取状态命令
      dat = SpiRead();                                    //读取状态
      CS = 1;
      return (dat & 0x01);                                //状态值的Bit0即为忙标志
}
//===============检测Flash是否准备就绪(等于1准备就绪)============
BOOL FlashCheckID()
{
      uchar dat1, dat2,dat3;
      while (IsFlashBusy());                                     //Flash忙检测
      CS = 0;
      SpiWrite(SFC_RDID);                                 //发送读取ID命令;
      dat1 = SpiRead();                                   //读取制造商ID
      dat2 = SpiRead();                                   //读取设备ID1
      dat3 = SpiRead();                                   //读取设备ID2
      CS = 1;
      while (IsFlashBusy());                                     //Flash忙检测
                                                          //检测是否为PM25LVxx系列的Flash
      g_fFlashOK = ((dat1 == 0xc2) && (dat2 == 0x20)&& (dat3 == 0x14));
      return g_fFlashOK;
}
//======================Flash使能信号============================
void FlashWriteEnable()
{
      CS = 0;
      SpiWrite(SFC_WREN);                                 //发送写使能命令
      CS = 1;          
}
//======================擦除整片指令=============================
void FlashErase()
{
            if (g_fFlashOK)
      {
         FlashWriteEnable();                              //使能Flash写命令
                 while (IsFlashBusy());                                 //Flash忙检测
         CS = 0;
         SpiWrite(SFC_CHIPER);                            //发送片擦除命令
         CS = 1;
                 while (IsFlashBusy());                                 //Flash忙检测
     }
}
//===================页面编程指令(0~4095)==========================
void FlashWrite(uint page,uchar *p,uint size)
{
   ulong addr;
   addr=(((ulong)page)<<8);                                    //取page地址
   if (g_fFlashOK)
   {
                FlashWriteEnable();                                    //使能Flash写命令
                while (IsFlashBusy());                                      //Flash忙检测
                CS=0;
                SpiWrite(SFC_PAGEPROG);                                //发送页编程命令
                SpiWrite((uchar)((addr&0x00ff0000)>>16));              //设置起始地址
        SpiWrite((uchar)((addr&0x00ff0000)>>8));
        SpiWrite((uchar)(addr&0x000000ff));
        while(size)
                {
                  SpiWrite(*p);
                  p++;
                  size--;
                }
                CS=1;
   }
}
//========================读指令===================================
void FlashRead(uint page,uchar *p,uint size)
{
        ulong addr2;
    addr2=(((ulong)page)<<8);                                    //取page地址
    if (g_fFlashOK)
    {
                while (IsFlashBusy());                                       //Flash忙检测
                CS=0;
        SpiWrite(SFC_FASTREAD);                                 //使用读取命令
        SpiWrite((uchar)((addr2&0x00ff0000)>>16));              //设置起始地址
        SpiWrite((uchar)((addr2&0x0000ff00)>>8));
        SpiWrite((uchar)(addr2&0x000000ff));
             SpiWrite(0xff);
        while(size)
                {
                   *p=SpiRead();
                   p++;
                   size--;
                }                       
                CS=1;
                while (IsFlashBusy());
    }
}
//======================主函数===================================
void main()
{
          InitSpi();                                                                                    //Spi初始化
          uart_init();                                                                                  //串口初始化
           //初始化Flash状态
      g_fFlashOK = FALSE;
     //检测Flash状态
      FlashCheckID();
      while(1);                                                                                                          
}                                                                                                                  
//=======================串口中断函数============================
void ser() interrupt 4
{
  uchar a;
  uint jj;
  RI=0;
  a=SBUF;
  if(flag)
  {   
      g_Buffer[ii++]=a;              //串口发来的数据写入到Flash缓冲区中
          if(ii==255)
          {
             ii=0;
                 FlashWrite(0x0000,g_Buffer,255);
                 FlashRead(0x0000,g_Buffer1,255);
             ES=0;
                 for(jj=0;jj<255;jj++)
                 {
            SBUF=g_Buffer1[jj];
                    while(!TI);
                    TI=0;
                 }
             ES=1;
          }
  }
  else
  {
         if(a==0x88)
         {
                flag=1;
                FlashErase();                                       //擦除整个芯片数据
         }
  }
}


小编,你的问题解决了吗,我也出现这种问题,帮忙顶上去。

没有,前段时间我把程序改了,数据写进去了。今天一试又不好使了,还是0x00

我的可以了,我的应该是写入数据出现了问题

能贴出来看下吗

顶起来,,,,,,,,,,

小编有这个芯片的资料吗?麻烦发下给我!谢谢811043655@qq.com

小编,解决了吗?我现在也在做这个,求指导一下!

很实用的,谢谢分享

请问小编这个程序有没有出现数据丢包的现象?

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top