打印
[AVR单片机]

关于M25P80flash的储存模块有问题

[复制链接]
3101|5
手机看帖
扫描二维码
随时随地手机跟帖
沙发
laslison|  楼主 | 2010-7-8 21:01 | 只看该作者
把代码发出来
/*********************************************************************
*模 块 名:     SPI总线FLASHRAM读写模块 *
*功能描述:PD4是C(clk),PD5是D(Serial Data Input),PD6是S即片选,Chip Select,低电平有效 PD7是Q,即Serial Data Ouput
*其他说明:                               *
**********************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>

#define M25_CLK_0 PORTD &= ~(1 << 7)   //时钟置0
#define M25_CLK_1 PORTD |= (1 << 7)   //时钟置1

#define M25_SI_0 PORTD &= ~(1 << 6)   //输入0,上升沿写数据
#define M25_SI_1 PORTD |= (1 << 6)   //输入1

#define M25_SO   PIND & (1 << 5) //读出数据,下降沿读数

#define M25_CS_0 PORTD &= ~(1 << 4)   //片选有效
#define M25_CS_1 PORTD |= (1 << 4)   //片选无效

#define WREN 0X06       //写使能
#define WRDI 0X04       //写禁止
#define RDSR 0X05       //读状态寄存器
#define WRSR 0X01       //写状态寄存器,WEL为0不允许写
#define READ 0X03       //读字节
#define FAST_READ 0X0B   //快读指令
#define PP 0X02       //页写指令
#define Sector_Erase 0XD8       //区域擦除
#define BE 0XC7       //批擦除
#define DP 0XB9       //深度掉电模式
#define RES 0XAB       //从深度掉电模式苏醒

#define uchar       unsigned char
#define uint         unsigned int

#define CPU 4000000
#define BAUD 9600

volatile long address_test = 0x00001;   //测试的地址
volatile uchar read_data;           //从flash里面读出来的数据

/*********************************************************************   
* 函 数 名: MDelay
* 功能描述: 延时子程序
* 函数说明:
* 调用函数:
***********************************************************************/
void MDelay(uint ui_temp)
{
  uint ui_i;
  for(ui_i=ui_temp;ui_i>0;ui_i--)
  {
    ;
  }
}
/*********************************************************************   
* 函 数 名:M25P80_SPI_Write8
* 功能描述: 基于SPI总线的8位数据写操作
* 函数说明: 实现SPI总线的8位数据写操作,上升沿写数据
* 调用函数:
***********************************************************************/
void M25P80_SPI_Write8(uchar temp8)
{
  uchar i;
M25_CLK_0;
  for(i=8;i>0;i--)
  {
    if( ( temp8 & 0X80 ) == 0x80 )
    {
      M25_SI_1;   //写入1
    }
    else
    {
      M25_SI_0;   //写入0
    }
    M25_CLK_0;     
    MDelay(5);
    M25_CLK_1;      
    temp8<<=1;   //左移   
  }
}

/*********************************************************************   
* 函 数 名:MP25_WriteEnable
* 功能描述: 写使能
* 函数说明: PP,Sector_Erase,BE,WRSR之前必须进行写使能
* 调用函数:M25P80_SPI_Write8
***********************************************************************/
void MP25_WriteEnable(void)
{

  
  M25_CS_0;   //片选
  M25P80_SPI_Write8(WREN); //写使能
  M25_CS_1;   //禁止片选
  MDelay(10);
}

/*********************************************************************   
* 函 数 名:SPI_Write24
* 功能描述: 基于SPI总线的24位数据写操作
* 函数说明: 实现SPI总线的24位数据写操作,上升沿写数据
***********************************************************************/
void M25P80_SPI_Write24(long temp24)
{
  uchar i;
M25_CLK_0;
  for(i=24;i>0;i--)
  {
    if( ( temp24 & 0X800000 ) == 0x800000 )
    {
      M25_SI_1;   //写入1
    }
    else
    {
      M25_SI_0;             //写入0
    }
    M25_CLK_0;
    MDelay(5);
    M25_CLK_1;
    temp24<<=1;               //左移
  }
}

/*********************************************************************   
* 函 数 名: M25P80_Read
* 功能描述: 基于SPI总线的8位数据读操作
* 函数说明: 实现SPI总线的8位数据读操作,下降沿输出数据
***********************************************************************/
uchar M25P80_Read(void)
{
  uchar i,tempbit;
  uchar tempData8 = 0x00;
  
  M25_CLK_1;     
  
  for(i=8;i>0;i--)
  {
    if(M25_SO)           // 这里没有弄清楚
    {
      tempbit=1;   //置1
    }
    else
    {
      tempbit=0;   //置0
    }
    M25_CLK_1;
    MDelay(5);
    M25_CLK_0;
    tempData8= ( (tempData8<<1) | tempbit );     //数据读出操作
  }                       
  return (tempData8);
}
/*********************************************************************   
* 函 数 名:MP25_ReadReg
* 功能描述: 读功能寄存器
* 函数说明:
* 调用函数:M25P80_SPI_Write8,MP25_WriteEnable
***********************************************************************/
uchar MP25_ReadReg(void)
{
  uchar Reg_Temp;
  M25_CS_0;     //片选
  M25P80_SPI_Write8(RDSR);   //写指令
  Reg_Temp=M25P80_Read();   //数据读出
  M25_CS_1;     //禁止片选
  MDelay(10);
  return(Reg_Temp);                       //返回值
}
/*********************************************************************   
* 函 数 名: MP25_Check
* 功能描述: WIP位检查
* 函数说明: 1,表示写操作未完成,0表示写操作完成
* 调用函数: MP25_ReadReg
***********************************************************************/
void MP25_Check(void)
{
  while(MP25_ReadReg() & 0X01)      
  {
    ;
  }
}
/*********************************************************************   
* 函 数 名:MP25_WriteDis
* 功能描述: 写禁止
* 函数说明:
* 调用函数:M25P80_SPI_Write8
***********************************************************************/
void MP25_WriteDis(void)
{
  M25_CS_0;     //片选
  M25P80_SPI_Write8(WRDI);   //写禁止
  M25_CS_1;     //禁止片选
  //
  MDelay(10);
}

/*********************************************************************   
* 函 数 名:MP25_WriteReg
* 功能描述: 写功能寄存器
* 函数说明:
* 调用函数:M25P80_SPI_Write8,MP25_WriteEnable
***********************************************************************/
void MP25_WriteReg(uchar comm)
{
  MP25_WriteEnable();   //写使能
  M25_CS_0;     //片选
  M25P80_SPI_Write8(WRSR);   //写指令
  M25P80_SPI_Write8(comm);   //写数据
  M25_CS_1;     //禁止片选
  MP25_Check();
  MP25_WriteDis();   //写禁止
}
/*********************************************************************   
* 函 数 名:M25P80_SPI_Read
* 功能描述: 从M25P80的指定地址读出一字节数
* 函数说明:
* 调用函数:M25P80_Read
***********************************************************************/
uchar M25P80_SPI_Read(long ADDR)
{
  uchar Data_Temp;
  M25_CS_0;     //片选
  M25P80_SPI_Write8(READ);   //写指令
  M25P80_SPI_Write24(ADDR);   //写地址   
  Data_Temp = M25P80_Read();   //数据读出操作
  M25_CS_1;     //禁止片选
  MDelay(10);
  return (Data_Temp);
}
/*********************************************************************   
*
* 函 数 名:MP25_Write_Byte
* 功能描述: 存储单字节数据
* 函数说明:
* 调用函数:M25P80_SPI_Write8,MP25_WriteEnable,M25PWriteWait
***********************************************************************/
void MP25_Write_Byte(long Addr,uchar data)
{
  MP25_WriteEnable();   //写使能
  M25_CS_0;     //片选
  M25P80_SPI_Write8(PP);   //页写指令
  M25P80_SPI_Write24(Addr);   //写指令
  M25P80_SPI_Write8(data);   //写数据
  M25_CS_1;     //禁止片选
  MDelay(10);
  MP25_Check();
  MDelay(10);
  MP25_WriteDis();   //写禁止
}

/*********************************************************************   
*
* 函 数 名:MP25_EraseSector
* 功能描述: 扇区擦除
* 函数说明:
* 调用函数:M25P80_SPI_Write8,MP25_WriteEnable,M25PWriteWait
***********************************************************************/
void MP25_EraseSector(long Addr)
{
  MP25_WriteEnable();   //写使能
  M25_CS_0;   //片选
  M25P80_SPI_Write8(Sector_Erase); //扇区擦除指令
  M25P80_SPI_Write24(Addr);       //写指令
  M25_CS_1;   //禁止片选
  MP25_Check();
  MP25_WriteDis();   //写禁止
}

使用特权

评论回复
板凳
laslison|  楼主 | 2010-7-8 21:01 | 只看该作者
/*********************************************************************   
*
* 函 数 名:MP25_EraseBulk
* 功能描述: 批擦除
* 函数说明:
* 调用函数:M25P80_SPI_Write8,MP25_WriteEnable,M25PWriteWait,MP25_WriteDis
***********************************************************************/
void MP25_EraseBulk(void)
{
  MP25_WriteEnable();   //写使能
  M25_CS_0;   //片选
  M25P80_SPI_Write8(BE); //批擦除指令
  M25_CS_1;   //禁止片选
  MP25_Check();   //等待操作完毕
  MP25_WriteDis();   //写禁止
}

/*********************************************************************   
*
* 函 数 名:M25PWriteStatus
* 功能描述:写状态寄存器
* 函数说明:
***********************************************************************/
void M25PWriteStatus(uchar databyte)
{
  MP25_WriteEnable();               // Must enable write latch first
  M25_CS_0;                     // Set CS_N low
  M25P80_SPI_Write8(WRSR);
  //MP25_Check();
  M25P80_SPI_Write8(databyte);
  //MP25_Check();
  M25_CS_1;                     // Set CS_N high
  MDelay(10);
  MP25_Check();
  MP25_WriteDis();
}
/*********************************************************************   
*
* 函 数 名: Init_m25p80
* 功能描述: 初始化M25P80
* 函数说明: 初始化M25P80
***********************************************************************/
void Init_m25p80(void)
{
  M25_CS_1;
  M25_CLK_0;
  M25PWriteStatus(0x02);
}

//串口初始化
void Usart_init(void)
{
  UCSRA = 0X00; //正常速度
  UCSRB |= (1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN); //使能接收/发送,接收/发送结束中断使能
  UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//8bit,异步,无奇偶校验,1个停止位
  UBRRH=(CPU/16/(BAUD-1))/256;
  UBRRL=(CPU/16/(BAUD-1))%256;   
}

//向串口发送数据
void send_char(uchar c)
{
while( !(UCSRA & (1<<UDRE)) );
UDR=c;
}

void m25p80_io_init(void)
{
DDRD |= (1 << PD1)|(1 << PD4)|(1 << PD6)|(1 << PD7);   //M25_S,M25_IN,M25_CLK 对于AVR是输出,TXD输出
DDRD &= ~((1 << PD0)|(1 << PD5));                 //M25_OUT 对于AVR是输入 ,RXD输入

}

int main(void)
{

cli();           //清全局中断
m25p80_io_init();   //M25P80端口初始化和串口端口初始化
Init_m25p80();     //M25P80内部初始化
Usart_init();       //串口初始化
sei();           //开全局中断

MP25_EraseSector(address_test);
MDelay(1000);
MP25_Write_Byte(address_test,0x45);
MDelay(1000);   
read_data = M25P80_SPI_Read(address_test);
MDelay(1000);
while(1)
{ send_char(read_data);
}

}

使用特权

评论回复
地板
laslison|  楼主 | 2010-7-11 15:17 | 只看该作者
为什么读出来的数据老是0呢?

使用特权

评论回复
5
guita| | 2010-7-14 17:11 | 只看该作者
太长,不如问个前辈

使用特权

评论回复
6
双龙| | 2010-7-23 10:06 | 只看该作者
这个存储器也不错

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

95

主题

791

帖子

1

粉丝