| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4424 人关注过本帖
标题:麻烦大家帮我看看,c51读写spiflash 现在只能读,不能写,麻烦看看哪里问题 ...
取消只看楼主 加入收藏
zcl2013c
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2013-10-28
结帖率:60%
收藏
已结贴  问题点数:4 回复次数:4 
麻烦大家帮我看看,c51读写spiflash 现在只能读,不能写,麻烦看看哪里问题?
程序代码:
#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;   
    return (dat & 0x01);                        //状态值的Bit0即为忙标志
}

/************************************************
使能Flash写命令
入口参数: 无
出口参数: 无

************************************************/
void FlashWriteEnable()
{
   // while (FlashBusy());                      //Flash忙检测
    spi_cs = 0;
    spi_write(SF_WREN);                         //发送写使能命令
    spi_cs = 1;
}

/************************************************
擦除整片Flash
入口参数: 无
出口参数: 无

************************************************/
void FlashChipErase()
{
   
   
        FlashWriteEnable();                     //使能Flash写命令
        spi_cs = 0;
        spi_write(SF_CHIPER);                   //发送擦除命令
        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;
   
}

/************************************************
擦除BlockFlash(64KB)
入口参数: 无
出口参数: 无

************************************************/
void FlashBlockErase()
{
   
   
        FlashWriteEnable();                     //使能Flash写命令
        spi_cs = 0;
        spi_write(SF_BLOCKER2);                   //发送擦除命令
        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 & 0xff);           //设置起始地址
        spi_write(addr>>8 & 0xff);
        spi_write(addr & 0xff);
        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 & 0xff);           //设置起始地址
        spi_write(addr>>8 & 0xff);
        spi_write(addr & 0xff);
        //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;
    }
}


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);
        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]);
    */
    }

}
程序就是只能读,不能写
搜索更多相关主题的帖子: 灯笼 
2014-02-18 11:37
zcl2013c
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2013-10-28
收藏
得分:0 
不能沉啊自己顶下,
flash是winbond的w25q16
2014-02-18 15:01
zcl2013c
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2013-10-28
收藏
得分:0 
回复 3楼 beyondyf
谢谢分析,所缺代码如下,单片机是33v的,硬件部分没有问题
程序代码:
#include "REG51.h"
#include "intrins.h"
#include <stdio.h>
#include <string.h>    

#define uchar  unsigned char
/*************************
    模拟SPI接口I/O定义
*************************/
sbit    spi_cs=P0^6; 
sbit    spi_di=P0^4; 
sbit    spi_clk=P0^5;
sbit    spi_do=P0^7;
void SomeNOP()
{
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();

 }
/*******************************
    向SPI器件写入一个字节数据
*******************************/
void spi_write(unsigned char spi_dat) 
{ 
    unsigned  char  i; 
    spi_cs=0;
    //spi_clk=1; 
    for  (i=0;i<8;i++) 
    {  
        SomeNOP();
        spi_clk=1;
        if((spi_dat & 0x80)==0x80)
        {
            spi_di=1;  //写入最高位
        }
        else
            spi_di=0;
        SomeNOP();    
        spi_dat=(spi_dat<<1);  //左移一位,依次写入
        spi_clk=0;
    }
    //spi_clk=0; 
    //spi_cs=1;
} 


 void spi_write1(unsigned char spi_dat) 
{ 
    unsigned  char  i; 
    spi_cs=0;
    //spi_clk=1; 
    for  (i=0;i<8;i++) 
    {  
        SomeNOP();
        spi_clk=0;
        if((spi_dat & 0x80)==0x80)
        {
            spi_di=1;  //写入最高位
        }
        else
            spi_di=0;
        SomeNOP();    
        spi_dat=(spi_dat<<1);  //左移一位,依次写入
        spi_clk=1;
    }
    //spi_clk=0; 
    //spi_cs=1;
}
/********************************
  从SPI器件读出一个字节数据
********************************/
unsigned char spi_read() 
{ 
    unsigned char i;
    unsigned  tdata; 
    spi_cs=0;
    spi_clk=1; 
    for (i=0;i<8;i++)                     
    {   
        SomeNOP();                        
        spi_clk=0;                                   
        tdata = (tdata<<1);  //xxxxxxx0
        SomeNOP();
        spi_clk=1;
        SomeNOP();                                                                
        if(spi_do==1)
        {
            tdata |=0x01;  //xxxxxxx0|00000001        
        }
        else
        {
            tdata &=~0x01;  //xxxxxxx0&11111110                
        }
    spi_clk=1;                      //从高到低位依次移入
    //spi_cs=1;
    }
    return tdata; 
}

 
2014-02-19 10:37
zcl2013c
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2013-10-28
收藏
得分:0 
回复 5楼 beyondyf
程序代码:
#include "REG51.h"
#include "intrins.h"
#include <stdio.h>
#include <string.h>
#include "spi.c"    

#define uchar  unsigned char
#define SF_WREN        0x06 //Flash命令 
#define SF_WRDI        0x04
#define SF_RDSR      0x05
//#define SF_RDSR_B      0x35
#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 BUFFER_SIZE     256                    //缓冲区大小
#define TEST_ADDR       512                       //Flash测试地址

uchar idflag;
uchar g_Buffer[BUFFER_SIZE];





sbit    spi_cs=P0^6; 
sbit    spi_di=P0^4; 
sbit    spi_clk=P0^5;
sbit    spi_do=P0^7;

/*******************************
    向SPI器件写入一个字节数据
*******************************/
void spi_write(unsigned char spi_dat) 
{ 
    unsigned  char  i;

    for  (i=0;i<8;i++) 
    {   

        spi_clk=0;
        if((spi_dat & 0x80)==0x80)
        {
            spi_di=1;  //写入最高位
        }
        else
            spi_di=0;  
        spi_dat=(spi_dat<<1);  //左移一位,依次写入
        spi_clk=1;
    }
} 


/********************************
  从SPI器件读出一个字节数据
********************************/
unsigned char spi_read() 
{ 
    unsigned char i;
    unsigned  tdata;

    for (i=0;i<8;i++)                     
    {   
                       
        spi_clk=1;                                   
        tdata = (tdata<<1);  //xxxxxxx0 

        spi_clk=0;
                                                                
        if(spi_do==1)
        {
            tdata |=0x01;  //xxxxxxx0|00000001        
        }
        else
        {
            tdata &=~0x01;  //xxxxxxx0&11111110                
        }
    }
    return tdata; 
}

void SomeNOP()
{
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();


 } 


 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;
}

/************************************************
检测FlashID

 W25Q16:0XEF14

************************************************/
unsigned char FlashCheckID()
{
    uchar dat1,dat2;
    uchar flag=0;
    spi_clk=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_clk = 0;
    spi_cs = 1;
    flag = ((dat1==0xef)&&(dat2==0x14));                                              
    return flag;
}

/************************************************
检测Flash的忙状态读状态寄存器1
入口参数: 无
出口参数:
    0 : Flash处于空闲状态
    1 : Flash处于忙状态

************************************************/

 FlashBusy(void)
{
    uchar dat;
    spi_clk = 0;
    spi_cs = 0;
    spi_write(SF_RDSR);                         //发送读取状态命令
    dat = spi_read();                            //读取状态
    spi_clk = 0;
    spi_cs = 1; 
    return (dat & 0x01);                         //状态值的Bit0即为忙标志

}


/************************************************
使能Flash写命令
入口参数: 无
出口参数: 无

************************************************/
void FlashWriteEnable()
{
    spi_clk = 0;
    spi_cs = 0;
    spi_write(SF_WREN);                         //发送写使能命令
    spi_clk = 0;
    spi_cs = 1;
}

/************************************************
擦除整片Flash
入口参数: 无
出口参数: 无

************************************************/
void FlashChipErase()
{
   
   
        FlashWriteEnable();                     //使能Flash写命令
        spi_clk = 0;
        spi_cs = 0;
        spi_write(SF_CHIPER);                   //发送擦除命令
        spi_clk = 0;
        spi_cs = 1;
}


/************************************************
擦除扇区Flash
入口参数: addr
出口参数: 无

************************************************/
void FlashSectorErase(unsigned long addr)
{
   
   
        FlashWriteEnable();                     //使能Flash写命令
        spi_clk = 0;
        spi_cs = 0;
        spi_write(SF_SECTORER);                   //发送擦除命令
        spi_write(addr>>16 & 0xff);           //设置起始地址
        spi_write(addr>>8 & 0xff);
        spi_write(addr & 0xff);
        spi_clk = 0;
        spi_cs = 1;
   
}

/************************************************
擦除BlockFlash(64KB)
入口参数: addr
出口参数: 无

************************************************/
void FlashBlockErase(unsigned long addr)
{
   
   
        FlashWriteEnable();                     //使能Flash写命令
        spi_clk = 0;
        spi_cs = 0;
        spi_write(SF_BLOCKER2);                   //发送擦除命令
        spi_write(addr>>16 & 0xff);           //设置起始地址
        spi_write(addr>>8 & 0xff);
        spi_write(addr & 0xff);
        spi_clk = 0;
        spi_cs = 1;
   
}


/************************************************
从Flash中读取数据fastread
入口参数:
    addr   : 地址参数
    size   : 数据块大小
    buffer : 缓冲从Flash中读取的数据
出口参数:
    无
   
************************************************/
void FlashRead(unsigned long addr,unsigned long size, unsigned char *buffer)
{       
        while (FlashBusy());                  //Flash忙检测
        spi_clk = 0;
        spi_cs = 0;
        spi_write(SF_FASTREAD);                 //使用快速读取命令
        spi_write(addr>>16 & 0xff);           //设置起始地址
        spi_write(addr>>8 & 0xff );
        spi_write(addr & 0xff );
        spi_write(0x00);                            //需要空读一个字节
        while (size)
        {
            *buffer = spi_read();              //自动连续读取并保存
            addr++;
            buffer++;
            size--;
        }
        spi_clk = 0;
        spi_cs = 1;
           
}

/************************************************
写数据到Flash中
入口参数:
    addr   : 地址参数
    size   : 数据块大小
    buffer : 缓冲需要写入Flash的数据
出口参数: 无
************************************************/
void FlashWrite(  unsigned long addr,unsigned long size, unsigned char *buffer)
{
        while (FlashBusy());
        FlashWriteEnable();                     //使能Flash写命令
        spi_clk = 0;
        spi_cs = 0;
        spi_write(SF_PAGEPROG);                 //发送页编程命令
        spi_write(addr>>16 );           //设置起始地址
        spi_write(addr>>8 );
        spi_write(addr );
       
        while (size)
        {
            spi_write(*buffer);                  //连续页内写
            buffer++;
            addr++;
            size--;
            if ((addr & 0xff) == 0) break;
        }
        spi_clk = 0;
        spi_cs = 1;
}


void main()
{
    int i;
    for (i=0; i<BUFFER_SIZE; i++)
    {
    g_Buffer[i]=i;
    }

   
    //初始化串口
    UART_Initial();
    delay1ms(2);
    while(1)
    {
        //检测Flash状态
        idflag = FlashCheckID();
        send_char(idflag),waitsend();
        delay1ms(100);
        //擦除扇区Flash
        //FlashSectorErase(TEST_ADDR);
        //将缓冲区的数据写到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();
        }
    }

}
读写时序改过来了,可是现在无法检测ID和读写数据了,还请再次求教


[ 本帖最后由 zcl2013c 于 2014-2-21 16:40 编辑 ]
2014-02-21 16:39
zcl2013c
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2013-10-28
收藏
得分:0 
回复 7楼 beyondyf
是在单片机上飞了四根线到flash,所以没用dual,
非常感谢你的指导,问题已经调通了。
2014-02-22 14:34
快速回复:麻烦大家帮我看看,c51读写spiflash 现在只能读,不能写,麻烦看看哪里 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.033943 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved