搜索
bottom↓
回复: 17

w25x40读写求助??????

[复制链接]

出0入0汤圆

发表于 2010-10-15 09:45:56 | 显示全部楼层 |阅读模式
我现在在调试一个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[256]=
{
  0xfa,0xfe,0xb5 ...........
};

unsigned char spi_nByte[256];



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信息

#define  FLASH_WriteAddress       0x700700
#define  FLASH_ReadAddress        FLASH_WriteAddress
#define  FLASH_SectorToErase      FLASH_WriteAddress
#define  M25P64_FLASH_ID          0xEF0000
#define  BufferSize               (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(;;)
{

}
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2010-10-16 00:22:01 | 显示全部楼层
同求。请问有中文的是序资料不?我用的是25X80
,也没有看懂,

出0入90汤圆

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

出0入0汤圆

 楼主| 发表于 2010-10-16 22:13:41 | 显示全部楼层
回复【1楼】 51fan :我也没有中文的资料。回复【2楼】 honami520 的,谢谢,我现在再根据那个32的好好的研究一下!!!!!!!!! 请问你的那个W25X16的例子程序能够发到我的邮箱吗???我的邮箱是:shewang131@163.com 先谢谢了

出0入90汤圆

发表于 2010-10-17 09:19:39 | 显示全部楼层
大哥,我传的这个32的和16的差不多!!!再说这个是51单片机的正适合你,我自己写的是STM8的程序,你还不一定看得懂了

出0入0汤圆

 楼主| 发表于 2010-10-17 11:25:35 | 显示全部楼层
【4楼】 honami520 大哥,你好!!!我按照你的那个32的,好像还是不能够读写数据,不知道是何故啊?????是不是我的硬件有问题啊????我的硬件的接法是WP、HOLD都是直接接高电平的,你看对不????

出0入0汤圆

发表于 2010-10-18 11:20:17 | 显示全部楼层
这类通讯调试,还是应该用逻辑分析仪看看硬件线路上的信号,才好分析了。

出0入0汤圆

 楼主| 发表于 2010-10-18 12:04:22 | 显示全部楼层
现在的是,读写状态寄存器的数据都是对的,而单个字节的进行读写数据,就不正确了(现在是可以读写,单补正确)????我现在是进行单个字节读写的,不知道可不可以???????因为没有逻辑分析仪,所以就...........

出0入0汤圆

发表于 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 int  i;
        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 int  i;
        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

出0入0汤圆

发表于 2011-7-6 10:16:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-9 10:23:52 | 显示全部楼层
请问:你们使用W25X系列的“双通道快读”这一功能了吗?软硬件各是如何实现的?谢谢!

出0入0汤圆

发表于 2012-7-6 09:03:53 | 显示全部楼层
你的读写问题解决了吗?怎么解决的,我现在也遇到你说的问题了!能给我发一份解决的资料吗?谢谢!zft_216@yahoo.com.cn

出0入0汤圆

 楼主| 发表于 2012-7-6 11:53:05 | 显示全部楼层
zft_216 发表于 2012-7-6 09:03
你的读写问题解决了吗?怎么解决的,我现在也遇到你说的问题了!能给我发一份解决的资料吗?谢谢!{:smile: ...


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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-8-25 14:06:51 | 显示全部楼层
51读写25系列芯片,非常好!

出0入0汤圆

发表于 2013-9-24 10:48:43 | 显示全部楼层
MARK SPIFLASH 驱动

出0入0汤圆

发表于 2013-11-13 21:04:50 | 显示全部楼层
正需要这个参考,打算把我的桌面时钟升级为语音报时

出0入0汤圆

发表于 2014-10-25 00:34:57 | 显示全部楼层
  1. #define Dummy_Byte                0xA5
复制代码

改成
  1. #define Dummy_Byte                0xFF
复制代码

试试

出0入0汤圆

发表于 2014-10-25 08:36:36 | 显示全部楼层
w25x 和 MX25L8005 这类PC主板bios最常用spi_flash芯片 多大区别?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 12:32

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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