hpdell 发表于 2010-10-15 09:45:56

w25x40读写求助??????

我现在在调试一个w25x40的这个芯片,但是现在读单字节,读出来的数据时0xff,连续读是0x00,不知道什么原因,程序如下:
请大侠们帮我看看,问题出在哪里了?????????

单片机:stc12le5a60s2   (1t ,3.3v)
晶振:33MHz


#include<stc12c5a60s2.h>
#include<intrins.h>
#include<string.h>   //strlen


typedef    unsigned char   uchar;
typedef    unsigned int   uint;


unsigned char mama320240=
{
0xfa,0xfe,0xb5 ...........
};

unsigned char spi_nByte;



sbit SPI_CS = P2^3;
sbit SPI_CK = P2^1;
sbit SPI_DI = P2^0;
sbit SPI_DO = P3^4;
sbit SPI_WP = P3^5;
sbit SPI_HOLD = P2^2;


#define SPI_WP_H SPI_WP=1               //写保护关闭
#define SPI_WP_L SPI_WP=0               //写保护开启

#define SPI_CS_H SPI_CS=1
#define SPI_CS_L SPI_CS=0

#define SPI_CK_H SPI_CK=1
#define SPI_CK_L SPI_CK=0

#define SPI_DI_H SPI_DI=1
#define SPI_DI_L SPI_DI=0

#define SPI_DO_H SPI_DO=1
#define SPI_DO_L SPI_DO=0

#define SPI_WP_H SPI_WP=1
#define SPI_WP_L SPI_WP=0

#define SPI_HOLD_H SPI_HOLD=1
#define SPI_HOLD_L SPI_HOLD=0

#define WriteEnable               0x06       //写使能,设置状态寄存器
#define WriteDisable            0x04       //写禁止
#define ReadStatusRegister      0x05       //读状态寄存器
#define WriteStatusRegister       0x01       //写状态寄存器
#define Read_Data               0x03       //读取存储器数据
#define FastReadData            0x0B       //快速读取存储器数据
#define FastReadDualOutput      0x3B       //快速双端口输出方式读取存储器数据
#define Page_Program            0x02       //页面编程--写数据

#define BlockErace                0xD8       //块擦除,64kb
#define SectorErace               0x20       //扇区擦除        ,4kb
#define ChipErace               0xC7       //片擦除
#define Power_Down                0xB9       //掉电模式

#define ReleacePowerDown          0xAB       //退出掉电模式
#define ReadDeviceID            0xAB       //获取设备ID信息

#define ReadDeviceID            0xAB       //退出掉电模式、设备ID信息
#define ReadManuIDDeviceID      0x90       //读取制造厂商ID信息和设备ID信息
#define ReadJedec_ID            0x9F       //JEDEC的ID信息

#defineFLASH_WriteAddress       0x700700
#defineFLASH_ReadAddress      FLASH_WriteAddress
#defineFLASH_SectorToErase      FLASH_WriteAddress
#defineM25P64_FLASH_ID          0xEF0000
#defineBufferSize               (countof(Tx_Buffer)-1)
#define countof(a)                (sizeof(a) / sizeof(*(a)))
#define Dummy_Byte                0xA5
#define SPI_FLASH_PageSize      256





void Spi_init();
void Spi_send_byte(unsigned char byte);
unsigned char Spi_get_byte();
unsigned char Spi_read_StatusRegister();
void Spi_wait_busy();
void Spi_write_StatusRegister(unsigned char byte);
void Spi_Write_Enable();
void Spi_Write_Disable();


unsigned char Spi_Read_Byte(unsigned long addr);
void Spi_Read_nByte(unsigned long addr,unsigned int nByte,unsigned char *p);
unsigned char Spi_FasttRead_Byte(unsigned long addr);
void spi_FasttRead_nByte(unsigned long addr,unsigned int nByte,unsigned char *p);


void Spi_Write_Byte(unsigned long addr,unsigned char dat);
void Spi_Write_PageByte(unsigned long addr,unsigned char *dat,unsigned int nByte);
void Spi_Write_Buffrer(unsigned long addr,unsigned char *dat,unsigned int nByte);
void Spi_Erase_Chip();
void Spi_Erase_Sector(unsigned long addr);
void Spi_Erase_Block(unsigned long addr);


void Spi_init()
{
        SPI_CK_L;               /* set clock to low initial state for SPI operation mode 0 */
//        SPI_CK_H;       /* set clock to low initial state for SPI operation mode 3 */
//        SPI_HOLD_H;
        SPI_WP_H;
        SPI_CS_H;
        Spi_Write_Disable();       
}


void Spi_send_byte(unsigned char byte)
{
        uchar i=0;
        SPI_CS_L;
        for(i=0;i<8;i++)
        {
                if(byte & 0x80)                /* check if MSB is high */
                        SPI_DI_H;
                else
                        SPI_DI_L;

                SPI_CK_H;
                byte <<= 1;
                delay_us(10);
                SPI_CK_L;
               
        }
}

unsigned char Spi_get_byte()
{
        uchar i=0,dat=0,temp=0;
        SPI_CS_L;
        for(i=0;i<8;i++)
        {
                dat <<= 1;
                temp = SPI_DO;
                SPI_CK_H;
                if(temp)
                        dat |= 0x01;
                SPI_CK_L;
        }
        return dat;
}

unsigned char Spi_read_StatusRegister()
{
        uchar StatusRegister=0;       
        SPI_CS_L;
        Spi_send_byte(ReadStatusRegister);       
        StatusRegister =         Spi_get_byte();               
        SPI_CS_H;
        return StatusRegister;       
}


void Spi_wait_busy()
{
        /*waste time until not busy WEL & Busy bit all be 1 (0x03). */
        while(Spi_read_StatusRegister() == 0x03)
                Spi_read_StatusRegister();
}



void Spi_write_StatusRegister(unsigned char byte)
{
        Spi_Write_Enable();
        SPI_CS_L;
        Spi_send_byte(WriteStatusRegister);       /* select write to status register */
        Spi_send_byte(byte);       /* data that will change the status(only bits 2,3,7 can be written) */
        SPI_CS_H;       
        Spi_Write_Disable();
}


void Spi_Write_Enable()
{
        SPI_CS_L;
        Spi_send_byte(WriteEnable);       /* select write to status register */
        SPI_CS_H;               
}


void Spi_Write_Disable()
{
        SPI_CS_L;
        Spi_send_byte(WriteDisable);       // select write to status register
        SPI_CS_H;               
}

/*------------------------------------------------------
从芯片内读出一个字节的数据
addr是读取数据的地址
------------------------------------------------------*/
unsigned char Spi_Read_Byte(unsigned long addr)
{
        unsigned char temp=0;
        SPI_CS_L;
        Spi_send_byte(Read_Data);
        Spi_send_byte((addr & 0xff0000) >> 16);
        Spi_send_byte((addr & 0xff00) >> 8);
        Spi_send_byte(addr & 0xff);

        temp = Spi_get_byte();
        SPI_CS_H;
        return temp;
}


void Spi_Read_nByte(unsigned long addr,unsigned int nByte,unsigned char *p)
{
        unsigned char temp=0;
        SPI_CS_L;
        Spi_send_byte(Read_Data);
        Spi_send_byte((addr & 0xff0000) >> 16);
        Spi_send_byte((addr & 0xff00) >> 8);
        Spi_send_byte(addr & 0xff);

        for(temp=0;temp<nByte;temp++,*p++)
                *p = Spi_get_byte();
        SPI_CS_H;
}


unsigned char Spi_FasttRead_Byte(unsigned long addr)
{
        unsigned char temp=0;
        SPI_CS_L;
        Spi_send_byte(FastReadData);
        Spi_send_byte((addr & 0xff0000) >> 16);
        Spi_send_byte((addr & 0xff00) >> 8);
        Spi_send_byte(addr & 0xff);
        Spi_send_byte(0xff);               //dummy byte
        temp = Spi_get_byte();
        SPI_CS_H;
        return temp;
}

/*----------------------------------
void spi_FasttRead_nByte(unsigned long addr,unsigned int nByte,unsigned char *p)
{
        unsigned char temp=0;

        SPI_CS_L;
        Spi_send_byte(FastReadData);
        Spi_send_byte((addr & 0xff0000) >> 16);
        Spi_send_byte((addr & 0xff00) >> 8);
        Spi_send_byte(addr & 0xff);
        Spi_send_byte(0xff);               //dummy byte
        for(temp=0;temp<nByte;temp++,*p++)
                *p = Spi_get_byte();
        SPI_CS_H;
}
-----------------------------------------*/












/*------------------------------------------------------
写一个字节的数据
addr是写入数据的地址
dat 是写入的数据
------------------------------------------------------*/
void Spi_Write_Byte(unsigned long addr,unsigned char dat)
{
        Spi_Write_Enable();
//        Spi_wait_busy();

//        SPI_CS_L;
        Spi_send_byte(Page_Program);
        Spi_send_byte((addr & 0xff0000) >> 16);
        Spi_send_byte((addr & 0xff00) >> 8);
        Spi_send_byte(addr & 0xff);

        Spi_send_byte(dat);
        SPI_CS_H;
        Spi_Write_Disable();
}


/*------------------------------------------------------
写多字节的数据
addr是写入数据的地址
dat 是写入的数据

特别注意,此函数无法写超出地址之外的page页,如果超出则地址指针将在此page中将翻转
到0,最多写入256个byte,预先确认此page已经全部擦除为0xff
------------------------------------------------------*/
void Spi_Write_PageByte(unsigned long addr,unsigned char *dat,unsigned int nByte)
{
        unsigned int i;
       
        Spi_Write_Enable();
        Spi_wait_busy();
        Spi_send_byte(Page_Program);
        Spi_send_byte((addr & 0xff0000) >> 16);
        Spi_send_byte((addr & 0xff00) >> 8);
        Spi_send_byte(addr & 0xff);

        for(i=0;i<nByte;i++,*dat++)
                Spi_send_byte(*dat);
        SPI_CS_H;

        Spi_Write_Disable();
}



void Spi_Write_Buffrer(unsigned long addr,unsigned char *dat,unsigned int nByte)
{
        unsigned char Num0fPage=0,Num0fSingle=0,Addr=0,count=0,temp=0;

        Addr = addr % SPI_FLASH_PageSize;
        count = SPI_FLASH_PageSize - Addr;
        Num0fPage   = nByte / SPI_FLASH_PageSize;
        Num0fSingle = nByte % SPI_FLASH_PageSize;

        Spi_Write_Enable();
       
        if(Addr == 0)                       /* WriteAddr is SPI_FLASH_PageSize aligned*/
        {
                if(Num0fPage == 0)       /* nByte < SPI_FLASH_PageSize */
                {
                        Spi_Write_PageByte(addr,dat,nByte);       
                }
                else                                                               /* nByte > SPI_FLASH_PageSize */
                {
                        while(Num0fPage--)
                        {
                               Spi_Write_PageByte(addr,dat,SPI_FLASH_PageSize);       
                               addr += SPI_FLASH_PageSize;
                               dat+= SPI_FLASH_PageSize;
                        }
                        Spi_Write_PageByte(addr,dat,Num0fSingle);       
                }
        }
        else        /* addr is not SPI_FLASH_PageSize aligned*/
        {
                if(Num0fPage == 0)       /* nByte < SPI_FLASH_PageSize */
                {
                        if(Num0fSingle > count)       /* (nByte + addr) > SPI_FLASH_PageSize */
                        {
                                temp = Num0fSingle - count;

                                Spi_Write_PageByte(addr,dat,count);       
                                addr += count;
                                dat+= count;

                                Spi_Write_PageByte(addr,dat,temp);       
                        }
                        else
                        {
                                Spi_Write_PageByte(addr,dat,nByte);
                        }               
                }
               
                else               /* nByte > SPI_FLASH_PageSize */
                {
                        nByte -= count;
                        Num0fPage = nByte / SPI_FLASH_PageSize;
                        Num0fSingle = nByte % SPI_FLASH_PageSize;

                        Spi_Write_PageByte(addr,dat,count);
                        addr += count;
                        dat+= count;

                        while(Num0fPage--)
                        {
                               Spi_Write_PageByte(addr,dat,SPI_FLASH_PageSize);
                               addr += SPI_FLASH_PageSize;
                               dat+= SPI_FLASH_PageSize;;
                        }
                        if(Num0fSingle != 0)
                        {
                                Spi_Write_PageByte(addr,dat,Num0fSingle);
                        }
                }       
        }

        SPI_CS_H;
        Spi_Write_Disable();
}












void Spi_Erase_Chip()
{
        Spi_Write_Enable();
//        Spi_wait_busy();
//        SPI_CS_L;
        Spi_send_byte(ChipErace);
        SPI_CS_H;
        Spi_Write_Disable();
}



/*******************************************************************************
* Function Name: Spi_Erase_Sector
* Description    : Erases the specified FLASH sector.
* Input          : addr: address of the sector to erase.(24位的bit地址)
* Output         : None
* Return         : None
*******************************************************************************/
void Spi_Erase_Sector(unsigned long addr)
{
        Spi_Write_Enable();

        Spi_send_byte(SectorErace);
        Spi_send_byte((addr & 0xff0000) >> 16);
        Spi_send_byte((addr & 0xff00) >> 8);
        Spi_send_byte(addr & 0xff);
        SPI_CS_H;
        Spi_Write_Disable();
}

/*******************************************************************************
* Function Name: Spi_Erase_Block
* Description    : Erases the entire FLASH.
* Input          : addr:Bulk的地址(24位的bit地址)
* Output         : None
* Return         : None
*******************************************************************************/
void Spi_Erase_Block(unsigned long addr)
{
        Spi_Write_Enable();
        Spi_wait_busy();
        SPI_CS_L;
        Spi_send_byte(BlockErace);

        Spi_send_byte((addr & 0xff0000) >> 16);
        Spi_send_byte((addr & 0xff00) >> 8);
        Spi_send_byte(addr & 0xff);

        SPI_CS_H;
        Spi_Write_Disable();
}

void main()
{
uchar spi_dat=0;
Uart0_Init();   //串口初始化

Spi_init();

Spi_Erase_Chip();//擦出芯片

Spi_Write_Byte(0,0xfb);


spi_dat = Spi_Read_Byte(0);
printexp("spi_dat",spi_dat,16);   //读出来的数据通过串口发送到电脑上,此时的数据是0xff



Spi_Write_PageByte(1,mama320240,256);

Spi_Read_nByte(1,256,spi_nByte);

for(i=0;i<256;i++)
{
                printexp("spi_nByte",spi_nByte,16);//此时的数据时0X00,不知道是什么原因??????那个16表示的是以16进制输出数据
}




for(;;)
{

}
}

51fan 发表于 2010-10-16 00:22:01

同求。请问有中文的是序资料不?我用的是25X80
,也没有看懂,

honami520 发表于 2010-10-16 08:44:46

我给你提供一个51的例子吧,是W25X16的,型号不同,操作方法应该是一样的!我看了这个再根据官方的文档就写出了STM8L152的驱动程序了,你看来要是搞不定就不好说了!!!
点击此处下载 ourdev_590225HOLE5B.rar(文件大小:45K) (原文件名:W25X32_CON.rar)

hpdell 发表于 2010-10-16 22:13:41

回复【1楼】 51fan :我也没有中文的资料。回复【2楼】 honami520 的,谢谢,我现在再根据那个32的好好的研究一下!!!!!!!!! 请问你的那个W25X16的例子程序能够发到我的邮箱吗???我的邮箱是:shewang131@163.com 先谢谢了

honami520 发表于 2010-10-17 09:19:39

大哥,我传的这个32的和16的差不多!!!再说这个是51单片机的正适合你,我自己写的是STM8的程序,你还不一定看得懂了

hpdell 发表于 2010-10-17 11:25:35

【4楼】 honami520 大哥,你好!!!我按照你的那个32的,好像还是不能够读写数据,不知道是何故啊?????是不是我的硬件有问题啊????我的硬件的接法是WP、HOLD都是直接接高电平的,你看对不????

eefans 发表于 2010-10-18 11:20:17

这类通讯调试,还是应该用逻辑分析仪看看硬件线路上的信号,才好分析了。

hpdell 发表于 2010-10-18 12:04:22

现在的是,读写状态寄存器的数据都是对的,而单个字节的进行读写数据,就不正确了(现在是可以读写,单补正确)????我现在是进行单个字节读写的,不知道可不可以???????因为没有逻辑分析仪,所以就...........

13410362373 发表于 2011-6-1 10:20:23

以前怎么没看到,发一个驱动你参考下:
#include   "GlobalDef.h"

//Data is shifted out on the falling edge of the CLK.
unsigned char SPI_ReadByte(void){
    unsigned char i,j;
   
    j=0;
    for(i=0;i<8;i++){
            SPI_CLK=0;
            SPI_CLK=1;
           
            j<<=1;
            if(SPI_SDO){j++;}
    }

        return j;
}
//Data is shifted in on the rising edge of the CLK.
void SPI_WriteByte(unsigned char wByte){
    unsigned char i;
   
    for(i=0;i<8;i++){
            if(wByte&0x80){SPI_SDI=1;}
            else{SPI_SDI=0;}
            wByte<<=1;
           
            SPI_CLK=0;
            SPI_CLK=1;
    }
}
//忙状态寄存器的BUSY位(D0位)只读
//在写动作(页写、扇区擦除、块擦除、芯片擦除、写状态寄存器)期间BUSY位有效(指示忙),其余状态非忙
//此函数执行后一直等到非忙状态才退出
void W25X40_CheckBusyStatus(void){
        SPI_CS=0;
                SPI_WriteByte(0x05);
                while(SPI_ReadByte()&0x01);
        SPI_CS=1;
}
void W25X40_WriteEnable(void){
        W25X40_CheckBusyStatus();

        SPI_CS=0;
        SPI_WriteByte(0x06);
        SPI_CS=1;
}
//扇区擦除
void W25X40_SectorErase(unsigned int sector){
        unsigned long address;
        unsigned char add2,add1,add0;

        address=sector*4096L;
        add2=(unsigned char)(address>>16);
    add1=(unsigned char)(address>>8);
        add0=(unsigned char)(address);

        W25X40_WriteEnable();
        W25X40_CheckBusyStatus();
        SPI_CS=0;
                SPI_WriteByte(0x20);
                SPI_WriteByte(add2);
                SPI_WriteByte(add1);
                SPI_WriteByte(add0);
        SPI_CS=1;
}
//address - 24位地址
//pHead   - 存储读出数据的头指针
//len   - 读出数据长度
void W25X40_ReadData(unsigned long address,unsigned char* pHead,unsigned int len){
        unsigned inti;
        unsigned char add2,add1,add0;
       
        add2=(unsigned char)(address>>16);
    add1=(unsigned char)(address>>8);
        add0=(unsigned char)(address);

        W25X40_CheckBusyStatus();
    SPI_CS=0;
                SPI_WriteByte(0x03);
                SPI_WriteByte(add2);
                SPI_WriteByte(add1);
                SPI_WriteByte(add0);
                for(i=0;i<len;i++){pHead=SPI_ReadByte();}
        SPI_CS=1;
}
//address - 24位地址
//pHead   - 存储读出数据的头指针
//len   - 读出数据长度
void W25X40_PageProgram(unsigned long address,unsigned char* pHead,unsigned int len){
        unsigned inti;
        unsigned char add2,add1,add0;
       
        add2=(unsigned char)(address>>16);
    add1=(unsigned char)(address>>8);
        add0=(unsigned char)(address);

        W25X40_WriteEnable();
        SPI_CS=0;
                SPI_WriteByte(0x02);
                SPI_WriteByte(add2);
                SPI_WriteByte(add1);
                SPI_WriteByte(add0);
                for(i=0;i<len;i++){SPI_WriteByte(pHead);}
        SPI_CS=1;
}

unsigned char W25X40_ReadStatusRegister(void){
        unsigned char i;

        W25X40_CheckBusyStatus();
        SPI_CS=0;
                SPI_WriteByte(0x05);
                i=SPI_ReadByte();
        SPI_CS=1;

        return i;
}
void W25X40_ChipErase(void){
        W25X40_CheckBusyStatus();
        SPI_CS=0;
        SPI_WriteByte(0xc7);
        SPI_CS=1;
}
UCHAR W25X40_ReadManufacturer(void){
        UCHAR data id;

        W25X40_CheckBusyStatus();
        SPI_CS=0;
                SPI_WriteByte(0x9f);
                id=SPI_ReadByte();
        SPI_CS=1;

        return id;
}

W25X40AVSSIG 目前深圳现货价格1.20元RMB
W25X16AVSSIG 目前深圳现货价格1.60元RMB

longyan993 发表于 2011-7-6 10:16:31

mark

ziwuchen 发表于 2011-10-9 10:23:52

请问:你们使用W25X系列的“双通道快读”这一功能了吗?软硬件各是如何实现的?谢谢!

zft_216 发表于 2012-7-6 09:03:53

你的读写问题解决了吗?怎么解决的,我现在也遇到你说的问题了!能给我发一份解决的资料吗?谢谢!zft_216@yahoo.com.cn{:smile:}

hpdell 发表于 2012-7-6 11:53:05

zft_216 发表于 2012-7-6 09:03 static/image/common/back.gif
你的读写问题解决了吗?怎么解决的,我现在也遇到你说的问题了!能给我发一份解决的资料吗?谢谢!{:smile: ...


你好,祝你成功!!!!!!!!11

rickly_hzy 发表于 2013-8-25 14:06:51

51读写25系列芯片,非常好!

sunplus 发表于 2013-9-24 10:48:43

MARK SPIFLASH 驱动

YF_Wang 发表于 2013-11-13 21:04:50

正需要这个参考,打算把我的桌面时钟升级为语音报时

simon_leung 发表于 2014-10-25 00:34:57

#define Dummy_Byte                0xA5
改成
#define Dummy_Byte                0xFF
试试

wkman 发表于 2014-10-25 08:36:36

w25x 和 MX25L8005 这类PC主板bios最常用spi_flash芯片 多大区别?{:sweat:}{:shocked:}
页: [1]
查看完整版本: w25x40读写求助??????