OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4029|回复: 1

最近用51模拟SPI 写FLASH,但是读出来的数据和写进去的不一样

[复制链接]

3

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
72
金钱
72
注册时间
2015-4-24
在线时间
6 小时
发表于 2015-8-7 11:17:49 | 显示全部楼层 |阅读模式
5金钱

原子哥帮忙看看,我觉得程序应该没问题啊。下附代码:


#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
 

unsigned char ID1,ID2;

unsigned char    BUSY;    //判忙碌
unsigned long Addre24;    //24位的Flash地址



//   ----W25X系统Flash读写
sbit CS          = P3^7; //选通 
sbit DIO         = P3^6;  //单片机输出
sbit DO          = P3^5; //FLASH输出
sbit SCLK        = P3^4; //时钟


#define W25X_ReadStatus       0x05  //读状态寄存器
#define W25X_WriteStatus      0x01  //写状态寄存器
#define W25X_ReadDATA8        0x03  //普读_数据
#define W25X_FastRead         0x0B  //快读_数据
#define W25X_Write            0x02  //写_数据_0~255个字节
#define W25X_S_Erase          0x20  //扇区擦除4KB
#define W25X_B_Erase          0xD8  //块区擦除64KB
#define W25X_C_Erase          0xC7  //整片格式化
#define W25X_PowerDown        0xB9  //待机
#define W25X_PowerON_ID       0xAB  //开机或是读ID
#define W25X_READ_ID    0x90  //读ID
#define W25X_JEDEC_ID         0x9F  //十六位的JEDEC_ID
#define W25X_WriteEnable      0x06  //写充许
#define W25X_WriteDisable     0x04  //写禁止

#define W25X_BUSY             0x01  //FLASH忙
#define W25X_NotBUSY          0x00  //FLASH闲 这是自定义的


//*********************************************** OK

void Send_OneByte(unsigned char DATA8) //从SPI发8位数
{                 //上升沿写入
   unsigned char x;
    
   for (x=0;x<8;x++)
    {
//  DATA8=DATA8<<1;
  SCLK=0; 
  if(DATA8&0x80)
   DIO=1;
 else
  DIO=0;
  SCLK=1;
  DATA8=DATA8<<1;
 
  }
}
//***********************************************  OK
unsigned char Read_OneByte(void)     //从SPI收8位数
   {               //下降沿输出
   unsigned char DATA8;
   unsigned char x;
//   DATA8=0;
//   DO=0;
   SCLK=1;
   for (x=0;x<8;x++)
     {
  SCLK=1;
  SCLK=0;
  DATA8=(DATA8<<1)|DO; 
  }
   return (DATA8);
}
//*************** 写允许 ****************************  OK
 void WriteEnable  (void)
{
   CS=0;
   Send_OneByte(W25X_WriteEnable); 
   CS=1;
}
//*************** 写禁止 **************************** OK
 void WriteDisable (void)
{
   CS=0;
   Send_OneByte(W25X_WriteDisable); 
   CS=1;
}
//***************判BUSY********************************
unsigned char W25X_BUSY_OrNot (void) //在读和写之前得先判断FLASH是否BUSY
   {             //BUSY的原因是擦除,或是连续读写
   unsigned char k;          //如果没有以上方式,不必判定可以写读 
//   PCA0CPH2 = 0x00;
   SCLK=1;
   _nop_();
   CS=0;
   Send_OneByte(W25X_ReadStatus);  //读状态寄存器
   k=Read_OneByte();  //读一个字节
   k=k&0x01;
   CS=1;_nop_();
   SCLK=1;
   if(k)return (W25X_BUSY);
   else return (W25X_NotBUSY);
   } //end of check BUSY
//***********************************************
void W25X_Flash_Byte_Write(unsigned long Addre24,unsigned char dat)
   {      
     
   while(W25X_BUSY_OrNot ()  );  //判BUSY 等到Flash闲才能操作

   WriteEnable();   //写允许
      //把地址拆开来
  
   CS=0;
   Send_OneByte(W25X_Write);  //命令
   Send_OneByte(Addre24>>16);
   Send_OneByte(Addre24>>8);
   Send_OneByte(Addre24);
   Send_OneByte(dat);
   CS=1;  
   WriteDisable ();
   }  //写FLASH结束

//***********************************************

unsigned char W25X_Flash_Byte_Read (unsigned long Addre24)  //从Flash里读出小于256字节数
{
 unsigned char temp;  

   while(W25X_BUSY_OrNot ());  //判BUSY
   WriteEnable();
  
   CS=0;
   Send_OneByte(W25X_ReadDATA8);//命令读
   Send_OneByte(Addre24>>16);
   Send_OneByte(Addre24>>8);
   Send_OneByte(Addre24);
 temp=Read_OneByte();
   CS=1;
   WriteDisable (); 
   return temp;
}
//**************片擦除 (MAX_80S)****************** OK
void W25X_ChipErase(void)
  {
  WriteEnable();   //写允许
  SCLK=1;
  CS=0;
  Send_OneByte(W25X_C_Erase);//整片擦除命令
  CS=1;   //从CS=1时开始执行擦除 
  }

//*************** 4K扇擦除************************ OK
void W25X_SectorErase(unsigned long Addre24) //擦除资料图示的4KB空间
  {
   unsigned char Addre3;
   unsigned char Addre2;
   unsigned char Addre1;

   WriteEnable();   //写允许
   Addre1=Addre24;
   Addre24=Addre24>>8;
   Addre2=Addre24;
   Addre24=Addre24>>8;
   Addre3=Addre24;   //把地址拆开来

   SCLK=1;
   CS=0;
   Send_OneByte(W25X_S_Erase);//整扇擦除命令
   Send_OneByte(Addre3);
   Send_OneByte(Addre2);
   Send_OneByte(Addre1);
   CS=1;
  }
//*************** 64K页/块擦除************************* OK
void W25X_BlockErase(unsigned long Addre24) //擦除资料图示的64KB空间
{
   unsigned char Addre3;
   unsigned char Addre2;
   unsigned char Addre1;

   WriteEnable();   //写允许
   Addre1=Addre24;
   Addre24=Addre24>>8;
   Addre2=Addre24;
   Addre24=Addre24>>8;
   Addre3=Addre24;   //把地址拆开来

   SCLK=1;
   CS=0;
   Send_OneByte(W25X_B_Erase);//整扇擦除命令
   Send_OneByte(Addre3);
   Send_OneByte(Addre2);
   Send_OneByte(Addre1);
   CS=1;

}


//******************************************************** OK
void Delay_ms(unsigned int ms) //ms级延时
{
  unsigned char i;
  while(ms--)
   for(i=0;i<110;i++);
}

void  W25X_Flash_ID_Read ()
{
   while(W25X_BUSY_OrNot ());  //判BUSY
  
   CS=0;
   Send_OneByte(W25X_READ_ID);
   Send_OneByte(0x00);
   Send_OneByte(0x00);
   Send_OneByte(0x00);

   ID1=Read_OneByte(); 
   ID2=Read_OneByte();
   CS=1;  

unsigned char W25X_Status ()
{            
   unsigned char k;          
   SCLK=1;
   _nop_();
   CS=0;
   Send_OneByte(W25X_ReadStatus);  //读状态寄存器
   k=Read_OneByte();  //读一个字节
   CS=1;
   return k;
}
void W25X_Flash_Status_Write()
{      
   while(W25X_BUSY_OrNot ()  );  //判BUSY 等到Flash闲才能操作

   WriteEnable();   //写允许
   SCLK=1;    
  
   CS=0;
   Send_OneByte(W25X_WriteStatus);  //命令
   Send_OneByte(0x80);
   CS=1;
}
void main() 
  {
  TMOD=0X20;
  TH1=0XFD;
        TL1=0XFD;
        TR1=1;
        REN=1;
        SM0=0;
        SM1=1;
//     W25X_ChipErase();           //片擦除
   W25X_SectorErase(0);   //4K擦除        
//   W25X_BlockErase (Addre24);   //64K块擦除
     W25X_Flash_Byte_Write(0,0x02);  //存储数据
  while(W25X_BUSY_OrNot ());
 while(1)      
 {
//  while(!RI);
//  RI=0;
  SBUF=W25X_Flash_Byte_Read (0);
  while(!TI);
  TI=0;

 }
     
}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

42

主题

358

帖子

0

精华

高级会员

Rank: 4

积分
890
金钱
890
注册时间
2014-8-16
在线时间
193 小时
发表于 2015-8-7 17:12:51 | 显示全部楼层
既然写进去的跟读出来的不一样 那肯定是你程序有问题啊,你参考一下原子提供的spi写w25Q128的例程吧 。都差不多的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-18 19:15

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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