打印
[应用相关]

STM32读写M95040 SPI EEPROM问题求教

[复制链接]
5336|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
just_soso|  楼主 | 2009-3-9 20:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用SPI1读写SPI EEPROM M95040. clock和MOSI都能正常工作,就是MISO上没有信号。用示波器看信号,MOSI信号符合时序。但是MISO上就是没有信号。
还有个很奇怪的问题。就是单步执行,发现能够写入,也能读出数量,任意修改写入某地址的数据,都能正确读出。但是全速运行时读出来的都是0xFF.是不是延时的问题?


程序如下:请高手看看。谢谢!
/* EEPROM instructions */
#define WREN    0x06
#define WRDI    0x04
#define RDSR     0x05
#define WRSR    0x01
#define READ    0x03
#define WRITE    0x02
/* Private variables ---------------------------------------------------------*/
SPI_InitTypeDef  SPI_InitStructure;

/*-----------------------------------------------------------------------------
ROUTINE NAME : SPI_Init
INPUT/OUTPUT : None

DESCRIPTION  : Configure the SPI peripheral

COMMENTS     :
-----------------------------------------------------------------------------*/

void SPI_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;  
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);


  /* Configure SPI1 pins: SCK, MISO and MOSI ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);  
  GPIO_SetBits(GPIOA, GPIO_Pin_4);
  
  /* SPI1 configuration */
  SPI_I2S_DeInit(SPI1);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);

  /* Enable SPI1  */
  SPI_Cmd(SPI1, ENABLE);  
  

}            

 
     

/*-----------------------------------------------------------------------------
ROUTINE NAME : Chk_WP_Bit
INPUT/OUTPUT : None/Boolean

DESCRIPTION  : Return 'TRUE' if write is still in progress in the EEPROM (M95040)

COMMENTS     :
-----------------------------------------------------------------------------*/

bool Chk_WP_Bit(void)
{
  u8 i;
  SPI_Cmd(SPI1, ENABLE);//SetBit(SPICR,6);  // spi enable

  GPIO_ResetBits(GPIOA,GPIO_Pin_4);
  //SPI_SendByte(RDSR);  
  //SPI_SendByte(RDSR); 
 
  while((SPI1->SR & SPI_I2S_FLAG_TXE) == RESET);       
  SPI1->DR=RDSR;
  while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET);
  i=SPI1->DR;  
  while((SPI1->SR & SPI_I2S_FLAG_TXE) == RESET);       
  SPI1->DR=RDSR;
  while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET);
  i=SPI1->DR;   
 
 GPIO_SetBits(GPIOA,GPIO_Pin_4);//SetBit(PADR,6);
 SPI_Cmd(SPI1, DISABLE);//ClrBit(SPICR,6);  // spi disable


 if(((SPI1->DR)|0xFE)==0xFE) return(TRUE);//(ValBit(SPIDR,0)) return(TRUE);
 else 
 return(FALSE);
}



     
/*-----------------------------------------------------------------------------
ROUTINE NAME : Read_EEPROM
INPUT/OUTPUT : u8 (adress) / u8 (data)

DESCRIPTION  : Return data located at the adress specified

COMMENTS     :
-----------------------------------------------------------------------------*/
 
u8 Read_EEPROM(u8 add)
{
  u8 data;

  SPI_Cmd(SPI1, ENABLE);//SetBit(SPICR,6);  // spi enable
  GPIO_ResetBits(GPIOA,GPIO_Pin_4);  
  SPI_SendByte(READ); 
  SPI_SendByte(add);  
  data=SPI_ReadByte();
  GPIO_SetBits(GPIOA,GPIO_Pin_4);  
  SPI_Cmd(SPI1, DISABLE);//ClrBit(SPICR,6);  // spi disable   
  return (data);  
}
 
                                
 
 
/*-----------------------------------------------------------------------------
ROUTINE NAME : Send_EEPROM
INPUT/OUTPUT : u8,u8 (adress,data) / None 

DESCRIPTION  : Send data byte to the adress specified

COMMENTS     :
-----------------------------------------------------------------------------*/

void Send_EEPROM(u8 add, u8 data)
{


  SPI_Cmd(SPI1, ENABLE);//SetBit(SPICR,6);  // spi enable
  GPIO_ResetBits(GPIOA,GPIO_Pin_4);//ClrBit(PADR,6);

  SPI_SendByte(WREN);
  GPIO_SetBits(GPIOA,GPIO_Pin_4);//SetBit(PADR,6);        

        
  GPIO_ResetBits(GPIOA,GPIO_Pin_4);//ClrBit(PADR,6);         
  SPI_SendByte(WRITE);
  SPI_SendByte(add);        
  SPI_SendByte(data);

  GPIO_SetBits(GPIOA,GPIO_Pin_4);//SetBit(PADR,6);
  SPI_Cmd(SPI1, DISABLE);//ClrBit(SPICR,6);  // spi disable  
 

}
 


/*******************************************************************************
* Function Name  : SPI_SendByte
* Description    : Sends a byte through the SPI interface and return the byte
*                  received from the SPI bus.
* Input          : byte : byte to send.
* Output         : None
* Return         : The value of the received byte.
*******************************************************************************/
u8 SPI_SendByte(u8 byte)
{
  /* Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

  /* Send byte through the SPI1 peripheral */
  SPI_I2S_SendData(SPI1, byte);

  /* Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  /* Return the byte read from the SPI bus */
  return SPI_I2S_ReceiveData(SPI1);
}
/*******************************************************************************
* Function Name  : SPI_ReadByte
* Description    : Reads a byte from the SPI Flash.
*                  This function must be used only if the Start_Read_Sequence
*                  function has been previously called.
* Input          : None
* Output         : None
* Return         : Byte Read from the SPI Flash.
*******************************************************************************/
u8 SPI_ReadByte(void)
{
  return (SPI_SendByte(0x55));
}  


/*-----------------------------------------------------------------------------*/
 
void Delay_us(u16 us)
{
    while(us--);
}
/*-----------------------------------------------------------------------------
ROUTINE NAME : Delay_ms
INPUT/OUTPUT : ms

DESCRIPTION  : 

COMMENTS     :
-----------------------------------------------------------------------------*/

void Delay_ms(u16 ms)
{
    u16 i,j;
    for(i=0;i<ms;i++)
        {
    for(j=0;j<15;j++)
        {
    Delay_us(1);
        }
        }
    
}
沙发
pray2013| | 2017-4-14 14:26 | 只看该作者
请问你调试好了吗?

使用特权

评论回复
板凳
mnynt121| | 2017-4-14 22:41 | 只看该作者
读取速度怎么样?

使用特权

评论回复
地板
mnynt121| | 2017-4-14 22:42 | 只看该作者
SPI读取速度最大是2M左右吧。

使用特权

评论回复
5
Prry| | 2017-4-15 12:07 | 只看该作者
单片机常用的总线如i2c、spi、uart等,将其硬件抽象层分离,相关外设在其抽象层上的应用函数接口调用。这样的好处是 :
1、外设的驱动方便移植到任何单片机;
2、外设总线方便移植到其他单片机,只需更改部分寄存器配置;
3、总线调试OK后,调试新的外设程序时,不用重重复复调试总线的程序。
比如,楼上的程序分层就不够好,ispi总线和eeprom交叉,假如我这个ispi总线要挂其他ispi设备(传感器、ADC等),那又得重新写一次总线程序?又重新配置?又调试时序对不对?做重复的工作就是浪费青春啊!假设换了一家公司,用了不同单片机,这个eeprom程序移植到其他单片机时又是重新写一遍,多吃力啊。
4、附上25系列(spi)接口eeprom驱动程序,spi函数做了封装,只需调用相关抽象层接口即可,程序方便移植到任何单片机,只需修改相应spi底层接口。
#include         "main.h"
#include        "spi.h"
#include  "25xx.h"

//module variable
#define                EE25XX_PAGE_SIZE        64                                //25aa256
struct st_spi_device        ee_25xx_spi_dev;

//module function
static uint8_t ee_25xx_wait_busy(void);

//
void ee_25xx_init(void)
{
                SPI_InitTypeDef  SPI_InitStructure;
                GPIO_InitTypeDef GPIO_InitStructure;
       
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);

                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
                GPIO_Init(GPIOB, &GPIO_InitStructure);
       
                //SPI2 cs
                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                                                                                //ÍÆÍìÊä³ö
                GPIO_Init(GPIOB, &GPIO_InitStructure);
                GPIO_SetBits(GPIOB, GPIO_Pin_12);
       
                SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;        //È«Ë«¹¤
                SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                                                                                                //Ö÷ģʽ
                SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                                                          //data_width                                               
                SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
                SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
                SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                                                                         
                SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //spiʱÖÓ£¬¸ù¾ÝÆ÷¼þËÙ¶ÈÉèÖÃ
                SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                                                        //¸ßλÔÚÇ°
                SPI_InitStructure.SPI_CRCPolynomial = 7;
                SPI_Init(SPI2, &SPI_InitStructure);
                       
                //device init
                ee_25xx_spi_dev.cs_io.GPIOx = GPIOB;
                ee_25xx_spi_dev.cs_io.GPIO_Pin = GPIO_Pin_12;
                ee_25xx_spi_dev.data_width = 8;
                ee_25xx_spi_dev.SPI = SPI2;
               
                SPI_Cmd(SPI2, ENABLE);                                       
}

//
void ee_25xx_write_enable(uint8_t select)
{
                spi_send(&ee_25xx_spi_dev,&select,1);
}

//
void ee_25xx_write_byte(uint16_t write_addr,uint8_t write_data)
{
                uint8_t send_buff[3];
       
                ee_25xx_write_enable(REG_WRITE_ENABLE);
                send_buff[0] = REG_WRITE_COMMAND;
                send_buff[1] = (write_addr>>8)&0xff;
                send_buff[2] = write_addr&0xff;
                spi_send_then_send(&ee_25xx_spi_dev,send_buff,3,&write_data,1);
                ee_25xx_write_enable(REG_WRITE_DISABLE);
}

/**
  * @brief  25xx write page
  * @param  address,buff,size.write_size is not more than device page size,such as 64 bytes for 25aa256.
  * @retval None
  */
void ee_25xx_write_page(uint16_t write_addr,uint8_t *write_page_buff,uint8_t write_size)
{
                uint8_t send_buff[3];
       
                ee_25xx_write_enable(REG_WRITE_ENABLE);
                send_buff[0] = REG_WRITE_COMMAND;
                send_buff[1] = (write_addr>>8)&0xff;
                send_buff[2] = write_addr&0xff;
                spi_send_then_send(&ee_25xx_spi_dev,send_buff,3,write_page_buff,write_size);
                ee_25xx_write_enable(REG_WRITE_DISABLE);
}

//
void ee_25xx_write_bytes(uint16_t write_addr, uint8_t *write_buff, uint16_t write_bytes)
{
                uint8_t   write_current_bytes,page_offset;
                uint16_t  write_remain,write_current_addr;
                uint8_t         *pbuff;
       
                //ee_25xx_write_enable(REG_WRITE_ENABLE);
                pbuff                                        = write_buff;                        //²»ÒªÖ±½ÓʹÓÃÐβμÆË㣬ÌرðÊÇÖ¸Õë²Ù×÷
                write_remain  = write_bytes;
                write_current_addr = write_addr;
                while(write_remain > 0)
                {
                                page_offset = write_current_addr % EE25XX_PAGE_SIZE;                //Á¬Ðøҳд´óС£¬25aa256Ϊ64×Ö½Ú
                                write_current_bytes   = write_remain > (EE25XX_PAGE_SIZE - page_offset) ? (EE25XX_PAGE_SIZE - page_offset) : write_remain;
                                ee_25xx_write_page(write_current_addr,pbuff, write_current_bytes);
                                write_remain   = write_remain - write_current_bytes;
                                if(write_remain > 0)
                                {
                                                pbuff = pbuff + EE25XX_PAGE_SIZE - page_offset;
                                                write_current_addr  =  write_current_addr + EE25XX_PAGE_SIZE - page_offset;
                                                //Delayms(5);
                                                ee_25xx_wait_busy();//wait free,¸ù¾ÝcpuʱÖÓ¼ÆËãʱ¼ä
                                }
                }
                //ee_25xx_write_enable(REG_WRITE_DISABLE);
}

//
void ee_25xx_read_bytes(uint16_t read_addr,uint8_t *read_buff,uint16_t read_bytes)
{
                uint8_t send_buff[3];
       
                send_buff[0] = REG_READ_COMMAND;
                send_buff[1] = (read_addr>>8)&0xff;
                send_buff[2] = read_addr&0xff;
                spi_send_then_recv(&ee_25xx_spi_dev,send_buff,3,read_buff,read_bytes);
}

//
void ee_25xx_write_status(uint8_t write_data)
{
                u8 send_buff[2];
       
                send_buff[0] = REG_WRITE_STATUS;
                send_buff[1] = write_data;
                spi_send(&ee_25xx_spi_dev,send_buff,2);
}

//
uint8_t ee_25xx_read_status(void)
{
                uint8_t read_status = 0,send_buff[1];
       
                send_buff[0] = REG_READ_STATUS;
                spi_send_then_recv(&ee_25xx_spi_dev,send_buff,1,&read_status,1);
       
                return read_status;
}

//
static uint8_t ee_25xx_wait_busy(void)
{
                uint32_t i;
       
                i = 0xFFFFF;
                while (i--);
               
                return 0;
}

//test
void ee_25xx_test(void)
{
                uint8_t write_buff[255] = {0},read_buff[255] = {0},i;
               
                for(i = 0;i < 0xff;i++)
                                write_buff = i;
                ee_25xx_read_bytes(255,read_buff,255);
                ee_25xx_write_bytes(255,write_buff,255);
                memset(read_buff,0,255);
                ee_25xx_read_bytes(255,read_buff,255);
                for(i = 0;i < 0xff;i++)
                                write_buff = 255-i;
                i=ee_25xx_read_status();
                ee_25xx_write_bytes(255,write_buff,255);
                ee_25xx_read_bytes(255,read_buff,255);
               
}

使用特权

评论回复
6
Prry| | 2017-4-15 12:11 | 只看该作者
中文注释乱码了,还是得练练English,用英文注释,这样在任何地方都不会乱码。

使用特权

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

本版积分规则

3

主题

18

帖子

0

粉丝