W25X80读不到数据,使用MSP430F247单片机
如题,程序如下:#include "define.h"
#include "w25x80add.h"
/*
W25x80,8M-bit
共16个扇区,每扇区64Kbyte
每扇区有256页,每页256byte
*/
//#include <stdio.h>
//#include <string.h>
#define W25X_CS P2OUT_bit.P7
#define W25X_CLK P3OUT_bit.P3
//#define W25X_SI P3OUT_bit.P1
//#define W25X_SO P3IN_bit.P1
#define W25X_SO P3IN_bit.P2
#define W25X_SI P3OUT_bit.P1
#define W25X_WP P3OUT_bit.P0
#define WREN 0x06
#define WRDIS 0x04
#define RDSR 0x05
#define WRSR 0x01
#define READ 0x03
#define FARD 0x0b
#define PGPM 0x02
#define STES4K 0x20
#define BKES32K 0x52
#define BKES64K 0xd8
#define CPES 0xc7
#define W25X_DeviceID 0xAB
#define W25X_ManufactDeviceID 0x90
#define W25X_JedecDeviceID 0x9F
/*--------------------------------------------------
w25x80延时n*300us
IN:i,延时系数
OUT:NONE
____________________________________________________*/
void w25_wait(u16 i)
{
for(;i>0;i--)
delay_us(300);
}
/*------------------------------------------------*/
//w25X80初始化
void w25_init(void)
{
//IO初始化
P2SEL_bit.P7=0;//CS
P2DIR_bit.P7=1;
P3SEL_bit.P0=0;//WP
P3SEL_bit.P1=0;//SI,输出
P3SEL_bit.P2=0;//SO,输入
P3SEL_bit.P3=0;//SCLK
P3DIR_bit.P0=1;//wp
P3DIR_bit.P1=1;//si
P3DIR_bit.P3=1;//sclk
P3DIR_bit.P2=0;//so
W25X_WP=1;//低电平有效
W25X_CLK=0;//软件模拟MODE0,CLK平时低电平
W25X_CS=1;
}
void w25_wrbyte(unsigned char sbyte)
{
unsigned char i;
//W25X_CLK=0;
//W25X_CS=1;
W25X_CLK=0;
W25X_CS=0;
//P3DIR_bit.P2=1;
for(i=0;i<8;i++)
{
W25X_CLK=0;
if((sbyte&0x80)==0x80)
W25X_SI=1;//din=1;
else
W25X_SI=0;//din=0;
sbyte<<=1;
//delay_us(2);
W25X_CLK=1;
}
W25X_CS=1;
W25X_CLK=0;
}
/*-----------------------------------------------
_________________________________________________________*/
unsigned char w25_rdbyte(void)
{
unsigned char i=0,temp=0;
W25X_CLK=0;
W25X_CS=0;
//P3DIR_bit.P2=0;
for(i=0;i<8;i++)
{
temp<<=1;
W25X_CLK=0;
if(W25X_SO!=0)//if(dio!=0)
temp|=0x01;
//else
//temp&=~0x01;
W25X_CLK=1;
}
W25X_CS=1;
W25X_CLK=0;
return temp;
}
/*----------------------------------------------------
//描述:写允许函数
//功能:在写入状态或者擦除或者数据时必须进行写允许操作
//形参:无
//返回:无
__________________________________________________________*/
void w25_enable(void)
{
W25X_CLK=0;
W25X_CS=0;
w25_wrbyte(WREN);
W25X_CS=1;
W25X_CLK=0;
}
/*----------------------------------------------------
//描述:写禁止函数
//功能:禁止写操作
//形参:无
//返回:无
__________________________________________________________*/
void w25_disable(void)
{
W25X_CLK=0;
W25X_CS=0;
w25_wrbyte(WRDIS);
W25X_CS=1;
W25X_CLK=0;
}
/*----------------------------------------------------
//描述:读ID1函数
//功能:读取ID1值
//形参:无
//返回:byte (字节数据)
__________________________________________________________*/
u8 w25_rdid1(void)
{
u8 byte;
W25X_CS=0;
w25_wrbyte(W25X_DeviceID);
w25_wrbyte(0);
w25_wrbyte(0);
w25_wrbyte(0);
byte=w25_rdbyte();
W25X_CS=1;
delay_us(2);
return byte;
}
/*----------------------------------------------------
//描述:读ID2函数
//功能:读取ID2值
//形参:ID_Addr (字节数据)
//返回:IData16(16位)
__________________________________________________________*/
u16 w25_rdid2(u8 ID_Addr)
{
u16 dd;
W25X_CS=0;
w25_wrbyte(W25X_ManufactDeviceID);
w25_wrbyte(0);
w25_wrbyte(0);
w25_wrbyte(ID_Addr);
dd=w25_rdbyte();
dd |= w25_rdbyte();
W25X_CS=1;
return dd;
}
/*----------------------------------------------------
//描述:读ID3函数
//功能:读取ID3值
//形参:无
//返回:IData16(16位)
__________________________________________________________*/
u16 w25_rdid3(void)
{
u16 dd;
W25X_CS=0;
w25_wrbyte(W25X_JedecDeviceID);
dd=w25_rdbyte();
dd |= w25_rdbyte();
w25_rdbyte();
W25X_CS=1;
return dd;
}
/*----------------------------------------------------------
读取寄存器的值
IN:NONE
OUT:u8 byte
_______________________________________________________________*/
unsigned char w25_rdsr(void)
{
unsigned char pbyte;
W25X_CLK=1;
W25X_CS=0;
w25_wrbyte(RDSR);
pbyte=w25_rdbyte();
W25X_CS=1;
W25X_CLK=1;
return pbyte;
}
/*----------------------------------------------------------
//描述:写状态寄存器函数(可设置写保护状态)
//功能:写状态到flash状态寄存器里 ( 需要时间15ms)
//形参:byte (字节数据)
//返回:无
_______________________________________________________________*/
void w25_wrsr(u8 byte)
{
W25X_CLK=1;
W25X_CS=0;
w25_wrbyte(WRSR);
w25_wrbyte(byte);
W25X_CS=1;
W25X_CLK=1;
}
void w25_busy(void)
{
while (w25_rdsr() == 0x03)
w25_rdsr(); // waste time until not busy WEL & Busy bit all be 1 (0x03)
}
/*-----------------------------------------------------------
//描述:读flash中某个地址的数据字节
//功能:读取指定地址上的数据
//形参:waddr(24位的地址)
//返回:byte(字节数据)
________________________________________________________________*/
u8 w25_RD(unsigned long waddr)
{
unsigned char byte;
W25X_CS=0;
w25_wrbyte(READ);
w25_wrbyte((u8)((waddr & 0xFFFFFF) >> 16));
w25_wrbyte((u8)((waddr & 0xFFFF) >> 8));
w25_wrbyte((u8)(waddr & 0xFF));
byte=w25_rdbyte();
W25X_CS=1;
return byte;
}
/*-----------------------------------------------------------
//描述:读flash多字节数据的函数
//功能:读取指定地址上的数据 (读取的数据以字节的形式放在缓存数组tx_buff中)
//形参:waddr (24位的地址),nBytes_128 (字节个数)
//返回:无
________________________________________________________________*/
void w25_RDS(unsigned long waddr,u8 * w25buf,u16 len)
{
unsigned long i;
W25X_CS=0;
w25_wrbyte(READ);
w25_wrbyte((u8)((waddr & 0xFFFFFF) >> 16));
w25_wrbyte((u8)((waddr & 0xFFFF) >> 8));
w25_wrbyte((u8)(waddr & 0xFF));
for(i=0;i<len;i++)
*(w25buf+i)=w25_rdbyte();
W25X_CS=1;
}
/*-----------------------------------------------------------
//描述:快速读flash数据的函数
//功能:快速读取指定地址上的数据
//形参:Dst_Addr (24位的地址)
//返回:byte
________________________________________________________________*/
u8 w25_FRD(unsigned long waddr)
{
u8 byte;
W25X_CLK=1;
W25X_CS=0;
w25_wrbyte(FARD);
w25_wrbyte((u8)((waddr & 0xFFFFFF) >> 16));
w25_wrbyte((u8)((waddr & 0xFFFF) >> 8));
w25_wrbyte((u8)(waddr & 0xFF));
w25_wrbyte(0xFF);
byte=w25_rdbyte();
W25X_CS=1;
return byte;
}
/*-----------------------------------------------------------
//描述:快速读flash多字节数据的函数
//功能:快速读取指定地址上的数据 (读取的数据以字节的形式放在缓存数组tx_buff中)
//形参:Dst_Addr (24位的地址),nBytes_128 (字节个数)
//返回:无
________________________________________________________________*/
void w25_FRDS(unsigned long waddr,u8 * w25buf,u16 len)
{
unsigned long i;
W25X_CS=0;
w25_wrbyte(FARD);
w25_wrbyte((u8)((waddr & 0xFFFFFF) >> 16));
w25_wrbyte((u8)((waddr & 0xFFFF) >> 8));
w25_wrbyte((u8)(waddr & 0xFF));
w25_wrbyte(0xFF);
for(i=0;i<len;i++)
*(w25buf+i)=w25_rdbyte();
W25X_CS=1;
}
/*-----------------------------------------------------------
//描述:写flash数据的函数 (以一个字节的形式)
//功能:写入数据到指定地址上
//形参:Dst_Addr (24位的地址),byte (数据)
//返回:无
________________________________________________________________*/
void w25_WR(unsigned long waddr,u8 byte)
{
w25_enable();
w25_busy();
W25X_CS=0;
w25_wrbyte(PGPM);
w25_wrbyte((u8)((waddr & 0xFFFFFF) >> 16));
w25_wrbyte((u8)((waddr & 0xFFFF) >> 8));
w25_wrbyte((u8)(waddr & 0xFF));
w25_wrbyte(byte);
W25X_CS=1;
}
/*-----------------------------------------------------------
//描述:写多个字节flash数据的函数 (以多字节的形式)(这之前要先把数据存到upper_128缓存数组中 )
//功能:写入多个字节数据到指定地址上
//形参:Dst_Addr (24位的地址),nBytes_128 (字节个数)
//返回:无
________________________________________________________________*/
void w25_WRS(unsigned long waddr,u8 *w25buf,u16 len)
{
u8 i;
W25X_CS=0;
w25_enable();
W25X_CS=0;
w25_wrbyte(PGPM);
w25_wrbyte((u8)((waddr & 0xFFFFFF) >> 16));
w25_wrbyte((u8)((waddr & 0xFFFF) >> 8));
w25_wrbyte((u8)(waddr & 0xFF));
for(i=0;i<len;i++)
w25_wrbyte(*(w25buf+i));
W25X_CS=1;
}
/*----------------------------------------------------------
//描述:flash扇区擦除函数(w25x32扇区擦除需要150ms~300ms)
//功能:擦除页,每页4k (如果该页被保护,擦除无效)
//形参:Dst_Addr (24位的地址)(此地址可为此页中的任何地址)
//返回:无
_________________________________________________________________*/
void w25_erase4k(unsigned long waddr)
{
W25X_CS=0;
w25_enable();
W25X_CS=0;
w25_wrbyte(STES4K);
w25_wrbyte((u8)((waddr & 0xFFFFFF) >> 16));
w25_wrbyte((u8)((waddr & 0xFFFF) >> 8));
w25_wrbyte((u8)waddr & 0xFF);
W25X_CS=1;
W25X_CLK=1;
w25_busy();
}
/*----------------------------------------------------------
//描述:flash块区擦除函数(w25x32块区擦除需要0.8s~2s)
//功能:擦除块区,每块64k (如果该块被保护,擦除无效)
//形参:Dst_Addr (24位的地址)
//返回:无
_________________________________________________________________*/
void w25_erase64k(unsigned long waddr)
{
W25X_CLK=1;
W25X_CS=0;
w25_enable();
W25X_CS=0;
w25_wrbyte(BKES64K);
w25_wrbyte((u8)((waddr & 0xFFFFFF) >> 16));
w25_wrbyte((u8)((waddr & 0xFFFF) >> 8));
w25_wrbyte((u8)waddr & 0xFF);
W25X_CS=1;
W25X_CLK=1;
w25_busy();
}
/*------------------------------------------------
//描述:flash芯片擦除函数(w25x32擦除整个芯片需要40s~80s)
//功能:擦除整个芯片 (如果写保护状态,擦除无效)
//形参:无
//返回:无
_________________________________________________________________*/
void w25_erase(void)
{
W25X_CLK=1;
W25X_CS=0;
w25_enable();
W25X_CS=0;
w25_busy();
W25X_CS=0;
w25_wrbyte(CPES);
W25X_CS=1;
W25X_CLK=1;
w25_busy();
}
电路见附图
,求指点....
自己顶贴吧,每一个人关注查看....~~~~(>_<)~~~~ 哥们,你这样一上来扔一堆代码是很难问到答案的,因为一般人没那么好的耐心一行行代码核对过去,难度也太大。
自己找找问题吧,良好的排查问题的思路能事半功倍。
先试试w25_rdid1,看能不能读回ID,如果读回是0x00或是0xFF,那就是IO口配置或SPI读写函数有问题。
另外P3SEL_bit.P0=0这类语句是用宏实现的?怎么觉得不太对劲呢。 最起码的ID要验证读取成功在谈下一步阿! 本帖最后由 peecehood 于 2013-11-6 14:34 编辑
为什么有硬件SPI不用?
void w25_busy(void)
{
while (w25_rdsr() == 0x03)
w25_rdsr(); // waste time until not busy WEL & Busy bit all be 1 (0x03)
}
这个0x03放入写入后面有过吗?不是写完一个指令WEL会自动清零。 dalarang 发表于 2013-11-6 10:55 static/image/common/back.gif
哥们,你这样一上来扔一堆代码是很难问到答案的,因为一般人没那么好的耐心一行行代码核对过去,难度也太大 ...
谢谢你的建议 ,P3OUT_bit.P0等类似的宏是IAR5.5以后的版本中自带的<MSP430Fx24X.h>中定义的,表示要操作的位是P3.0,如果事先设置好P3SEL,那么可以直接P3OUT_bit.P0=0或者P3OUT_bit.P0=1以控制单片机输出高低电平;
我的问题最后解决了,是CS的问题,每次操作的函数只需要开头片选和结束时取消片选;除了片选问题和读忙状态有问题,其它目前测试没有问题; peecehood 发表于 2013-11-6 14:19 static/image/common/back.gif
为什么有硬件SPI不用?
void w25_busy(void)
{
谢谢你的关注,问题已经解决,片选除了问题,参见我上一条回复信息;
另外,读忙的这个函数是写错了;
用硬件SPI,示波器测试无CLK、无DI输出...不知道什么原因,IAR5.5后的头文件看起来有些乱,没找到一个好的用户指南,官方的和IAR中的寄存器也对不上,最终放弃了,改为IO模拟.....
页:
[1]