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(;;)
{
}
} 同求。请问有中文的是序资料不?我用的是25X80
,也没有看懂, 我给你提供一个51的例子吧,是W25X16的,型号不同,操作方法应该是一样的!我看了这个再根据官方的文档就写出了STM8L152的驱动程序了,你看来要是搞不定就不好说了!!!
点击此处下载 ourdev_590225HOLE5B.rar(文件大小:45K) (原文件名:W25X32_CON.rar) 回复【1楼】 51fan :我也没有中文的资料。回复【2楼】 honami520 的,谢谢,我现在再根据那个32的好好的研究一下!!!!!!!!! 请问你的那个W25X16的例子程序能够发到我的邮箱吗???我的邮箱是:shewang131@163.com 先谢谢了 大哥,我传的这个32的和16的差不多!!!再说这个是51单片机的正适合你,我自己写的是STM8的程序,你还不一定看得懂了 【4楼】 honami520 大哥,你好!!!我按照你的那个32的,好像还是不能够读写数据,不知道是何故啊?????是不是我的硬件有问题啊????我的硬件的接法是WP、HOLD都是直接接高电平的,你看对不???? 这类通讯调试,还是应该用逻辑分析仪看看硬件线路上的信号,才好分析了。 现在的是,读写状态寄存器的数据都是对的,而单个字节的进行读写数据,就不正确了(现在是可以读写,单补正确)????我现在是进行单个字节读写的,不知道可不可以???????因为没有逻辑分析仪,所以就........... 以前怎么没看到,发一个驱动你参考下:
#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 mark 请问:你们使用W25X系列的“双通道快读”这一功能了吗?软硬件各是如何实现的?谢谢! 你的读写问题解决了吗?怎么解决的,我现在也遇到你说的问题了!能给我发一份解决的资料吗?谢谢!zft_216@yahoo.com.cn{:smile:} zft_216 发表于 2012-7-6 09:03 static/image/common/back.gif
你的读写问题解决了吗?怎么解决的,我现在也遇到你说的问题了!能给我发一份解决的资料吗?谢谢!{:smile: ...
你好,祝你成功!!!!!!!!11
51读写25系列芯片,非常好! MARK SPIFLASH 驱动 正需要这个参考,打算把我的桌面时钟升级为语音报时 #define Dummy_Byte 0xA5
改成
#define Dummy_Byte 0xFF
试试 w25x 和 MX25L8005 这类PC主板bios最常用spi_flash芯片 多大区别?{:sweat:}{:shocked:}
页:
[1]