微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > c51单片机与spiflash只能读不能写,求指教

c51单片机与spiflash只能读不能写,求指教

时间:10-02 整理:3721RD 点击:
#define SF_WREN        0x06 //Flash命令  
#define SF_WRDI        0x04
#define SF_RDSR        0x05
#define SF_WRSR        0x01
#define SF_READ        0x03
#define SF_FASTREAD    0x0B
#define SF_RDID        0x90
#define SF_PAGEPROG    0x02
//#define SF_RDCR        0xA1
//#define SF_WRCR        0xF1
#define SF_SECTORER    0x20
#define SF_BLOCKER1    0x52   //32KB
#define SF_BLOCKER2    0xD8   //64KB
#define SF_CHIPER      0xC7
//#define NULL            0
//#define FALSE           0
//#define TRUE            1
#define BUFFER_SIZE     256                    //缓冲区大小
#define TEST_ADDR       512                       //Flash测试地址
uchar idflag;
//uchar m=256;
uchar g_Buffer[BUFFER_SIZE];
/*
void waitsend();
void UART_Initial();
void send_char( uchar ch);
void spi_write(unsigned char spi_dat);
unsigned char spi_read();
//BYTE SpiShift(BYTE dat);
FlashCheckID();
void FlashBusy();
void FlashWriteEnable();
void FlashErase();
void FlashChipErase();
void FlashSectorErase();
void FlashBlockErase();
void FlashRead( addr,  size,unsigned char  *buffer);
void FlashWrite( addr,  size,unsigned char  *buffer);
*/

void waitsend()
{
     TI = 0;
  ES = 0;
     while(!TI)
     {
     };
     TI = 0;
  ES = 1;
}
void delay(long i)
{
   long  j;
   for(j=0;j<i;j++)
     {
    SomeNOP();
       SomeNOP();
   }
}
void delay1ms(long  i)
{
   long  j;
   for(j=0;j<i;j++)
     {
    delay(70);
   }
}
// UART  
void UART_Initial()
{
    SCON = 0x50; //串口方式1,允许接收
TMOD = 0x20; //定时计数器1方式2
TH1 = 0xFD; //9600 波特率 FD
TL1 = 0xFD;
EA=1;      
ES=1;      
TR1 = 1;
}

//向串口发送一个字符  
void send_char( uchar ch)
{
    SBUF=ch;
    //delay1ms(1);
    //while (TI==0);
    //TI=0;
}
/************************************************
使用SPI方式与Flash进行数据交换
入口参数:
    dat : 准备写入的数据
出口参数:
    从Flash中读出的数据
************************************************
BYTE SpiShift(BYTE dat)
{
    SPDAT = dat;                                //触发SPI发送
    while (!(SPSTAT & SPIF));                   //等待SPI数据传输完成
    SPSTAT = SPIF | WCOL;                       //清除SPI状态
   
    return SPDAT;
}
*/
/************************************************
检测FlashID
W25Q16:0XEF14
************************************************/
unsigned char FlashCheckID()
{
    uchar dat1,dat2;
    uchar flag=0;
   
    spi_cs = 0;
    spi_write(SF_RDID);                         //发送读取ID命令
    spi_write(0x00);                             //空读3个字节
    spi_write(0x00);
    spi_write(0x00);
    dat1 = spi_read();                      //读取制造商ID1
    dat2 = spi_read();                      //读取制造商ID2
    spi_cs = 1;
    flag = ((dat1==0xef)&&(dat2==0x14));                                               
    return flag;
}
/************************************************
检测Flash的忙状态读状态寄存器1
入口参数: 无
出口参数:
    0 : Flash处于空闲状态
    1 : Flash处于忙状态
************************************************/
FlashBusy(void)
{
    uchar dat;
   
    spi_cs = 0;
    spi_write(SF_RDSR);                         //发送读取状态命令
    dat = spi_read();                          //读取状态
    spi_cs = 1;
    //if(dat&0x03)
    //dat = 0x01;
    //else
    //dat = 0x00;
    //return (dat);   
    return (dat & 0x01);                        //状态值的Bit0即为忙标志
}
/************************************************
使能Flash写命令
入口参数: 无
出口参数: 无
************************************************/
void FlashWriteEnable()
{
   // while (FlashBusy());                      //Flash忙检测
    spi_cs = 0;
    spi_write(0x06);                         //发送写使能命令
    spi_cs = 1;
    //delay1ms(10);
}
/************************************************
擦除整片Flash
入口参数: addr
出口参数: 无
************************************************/
void FlashChipErase(unsigned long addr)
{
   
   
        FlashWriteEnable();                     //使能Flash写命令
        spi_cs = 0;
        spi_write(SF_CHIPER);                   //发送擦除命令
        spi_write(addr>>16 & 0xff);           //设置起始地址
        spi_write(addr>>8 & 0xff);
        spi_write(addr & 0xff);
        spi_cs = 1;
   
}
/************************************************
擦除扇区Flash
入口参数: addr
出口参数: 无
************************************************/
void FlashSectorErase(unsigned long addr)
{
   
   
        FlashWriteEnable();                     //使能Flash写命令
        spi_cs = 0;
        spi_write(SF_SECTORER);                   //发送擦除命令
        spi_write(addr>>16 & 0xff);           //设置起始地址
        spi_write(addr>>8 & 0xff);
        spi_write(addr & 0xff);
        spi_cs = 1;
        while (FlashBusy());
   
}
/************************************************
擦除BlockFlash(64KB)
入口参数: addr
出口参数: 无
************************************************/
void FlashBlockErase(unsigned long addr)
{
   
   
        FlashWriteEnable();                     //使能Flash写命令
        spi_cs = 0;
        spi_write(SF_BLOCKER2);                   //发送擦除命令
        spi_write(addr>>16 & 0xff);           //设置起始地址
        spi_write(addr>>8 & 0xff);
        spi_write(addr & 0xff);
        spi_cs = 1;
   
}
/************************************************
从Flash中读取数据fastread
入口参数:
    addr   : 地址参数
    size   : 数据块大小
    buffer : 缓冲从Flash中读取的数据
出口参数:
    无
   
************************************************/
void FlashRead(unsigned long addr,unsigned long size, unsigned char *buffer)
{        
        while (FlashBusy());                  //Flash忙检测
        spi_cs = 0;
        spi_write(SF_FASTREAD);                 //使用快速读取命令
        spi_write(addr>>16);           //设置起始地址
        spi_write(addr>>8 );
        spi_write(addr );
        spi_write(0x00);                            //需要空读一个字节
        while (size)
        {
            *buffer = spi_read();              //自动连续读取并保存
            addr++;
            buffer++;
            size--;
        }
        spi_cs = 1;   
}
/************************************************
写数据到Flash中
入口参数:
    addr   : 地址参数
    size   : 数据块大小
    buffer : 缓冲需要写入Flash的数据
出口参数: 无
************************************************/
void FlashWrite(  unsigned long addr,unsigned long size, unsigned char *buffer)
{
    //while (FlashBusy());
    //while (size)
    //{
        //uchar i;
        FlashWriteEnable();                     //使能Flash写命令
        spi_cs = 0;
        spi_write(SF_PAGEPROG);                 //发送页编程命令
        spi_write(addr>>16 );           //设置起始地址
        spi_write(addr>>8 );
        spi_write(addr );
        //for (i=0; i<0x100; i++)
        //{
            //spi_write(*buffer);
            //size--;
            //buffer++;
        //}
        
        while (size)
        {
            spi_write(*buffer);                  //连续页内写
            buffer++;
            addr++;
            //buffer++;
            size--;
            //if ((addr & 0xff) == 0) break;
        }
        spi_cs = 1;
        //while (FlashBusy());
   // }
}
void main()
{
    int i;
    for (i=0; i<BUFFER_SIZE; i++)
    {
    g_Buffer[i]=i;
    }
   
    //初始化Flash状态
    //g_fFlashOK = FALSE;
   
    //初始化串口
    UART_Initial();
    delay1ms(2);
    FlashSectorErase(TEST_ADDR);
    delay1ms(200);
    while(1)
    {
        //for (i=0; i<BUFFER_SIZE; i++)
        //{
            //send_char(g_Buffer[i]),waitsend();
            //delay1ms(100);
        //}
        //i=0;
        //检测Flash状态
        idflag = FlashCheckID();
        send_char(idflag),waitsend();
        delay1ms(1000);
        //send_char(0x01), waitsend();
   
        //将缓冲区的数据写到Flash中
        FlashWrite(TEST_ADDR, BUFFER_SIZE, g_Buffer);
        //send_char(addr);
        delay1ms(100);
        //读取测试地址的数据
        FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
        delay1ms(100);
        //发送到串口
        for (i=0; i<BUFFER_SIZE; i++)
        {   
            send_char(g_Buffer[i]),waitsend();
            delay1ms(100);
        }
    /*
    //擦除Flash
    FlashErase();
    //读取测试地址的数据
    FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
    //发送到串口
    for (i=0; i<BUFFER_SIZE; i++) SendUart(g_Buffer[i]);
   
    //修改置缓冲区
    for (i=0; i<BUFFER_SIZE; i++) g_Buffer[i] = i>>2;
    //将缓冲区的数据写到Flash中
    FlashWrite(TEST_ADDR, BUFFER_SIZE, g_Buffer);
   
    //读取测试地址的数据
    FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
    //发送到串口
    for (i=0; i<BUFFER_SIZE; i++) SendUart(g_Buffer[i]);
   
    FlashErase();
    //读取测试地址的数据
    FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
    //发送到串口
    for (i=0; i<BUFFER_SIZE; i++) SendUart(g_Buffer[i]);
   
    //修改置缓冲区
    for (i=0; i<BUFFER_SIZE; i++) g_Buffer[i]= 255-(i>>2);
    //将缓冲区的数据写到Flash中
    FlashWrite(TEST_ADDR, BUFFER_SIZE, g_Buffer);
   
    //读取测试地址的数据
    FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
    //发送到串口
    for (i=0; i<BUFFER_SIZE; i++) SendUart(g_Buffer[i]);
    */
    }
}
程序如上

求高手看看啊,

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

网站地图

Top