8418|17

84

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

103的SPI,还未调通 [复制链接]

我用的是64脚的103,SPI接口的串行FLASH与103的接口是:
    CS  - PA4(20脚,SPI1_NSS)
    CLK - PA5(21脚,SPI1_SCK)
    SDO - PA6(22脚,SPI1_MISO)
    SDI - PA7(23脚,SPI1_MOSI)
初始化代码如下:
  1-在RCC初始化中,包含了使能SPI1的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  |
                           RCC_APB2Periph_GPIOB  |
                           RCC_APB2Periph_GPIOD  | 
                           RCC_APB2Periph_AFIO   |
                           RCC_APB2Periph_USART1 |
                           RCC_APB2Periph_SPI1,
                           ENABLE);

  2-在GPIO初始化中,分配了管脚,并把CS设置为软件控制方式
    //Configure SPI1 pins: SCK, MISO and MOSI
    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);
    
    //Configure I/O for Flash Chip select
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
  3-SPI1接口初始化
    SPI_InitTypeDef  SPI_InitStructure;

    GPIOA->BSRR = GPIO_Pin_4;
    
    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_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);
    
    SPI_Cmd(SPI1, ENABLE);
经过以上3步设置后,我用软件控制CS引脚的高低电平均可以,但是操作SPI接口就是没反应,是不是我的设置有缺漏的地方?
此帖出自stm32/stm8论坛

最新回复

                                 不是用示波器看的问题,我现在已经搞定了,像我在17楼说的,多出了一个空读操作,这是我不明白的地方。虽然我17楼贴上去的函数都好用了,但我还是对5处不太明白,现在暂时不用SPI接口,还用我原来模拟的时序,很好用,因为项目紧,等做完项目再研究为什么多出来一个空读操作   详情 回复 发表于 2008-8-21 16:00
点赞 关注
 

回复
举报

81

帖子

0

TA的资源

一粒金砂(初级)

沙发
 

AFIO时钟

                                  
此帖出自stm32/stm8论坛
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

板凳
 

在第1步中不是已经打开了AFIO的时钟么?

                                  
此帖出自stm32/stm8论坛
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

4
 

“操作SPI接口就是没反应”是什么意思?

用示波器看过吗?

如何操作SPI接口的?
此帖出自stm32/stm8论坛
 
 
 

回复

88

帖子

0

TA的资源

一粒金砂(初级)

5
 

读写W25X20

首先我用W25X_ReadManufacturer()函数读取芯片的ID就不成功,返回的是FF


#include "stm32f10x_lib.h"

void W25X_CheckBusyStatus(void);
void W25X_WriteEnable(void);
void W25X_SectorErase(u16 sector);
void W25X_ReadData(u32 address,u8 *pHead,u16 len);
void W25X_PageProgram(u32 address,u8 *pHead,u16 len);
u8 W25X_ReadManufacturer(void);

//忙状态寄存器的BUSY位(D0位,只读)在写动作(页写、扇区擦除、块擦除、芯片擦除、写
//状态寄存器)期间有效(指示忙),其余状态非忙,此函数执行后一直等到非忙状态才退出
///////////////////////////////////////////////////////////////////////////////
void W25X_CheckBusyStatus(void){
    GPIOA->BRR = GPIO_Pin_4;
    do{
        SPI_I2S_SendData(SPI1,0x05);
    while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET);
    }while(SPI_I2S_ReceiveData(SPI1)&0x01);

    GPIOA->BSRR = GPIO_Pin_4;
}
void W25X_WriteEnable(void){
    W25X_CheckBusyStatus();

    GPIOA->BRR = GPIO_Pin_4;
    SPI_I2S_SendData(SPI1,0x06);
    GPIOA->BSRR = GPIO_Pin_4;
}
//扇区擦除
void W25X_SectorErase(u16 sector){
    u32 address;
    u8  add2,add1,add0;

    address = sector*4096L;
    add2    = (u8)(address>>16);
    add1    = (u8)(address>>8);
    add0    = (u8)(address);

    W25X_WriteEnable();
    W25X_CheckBusyStatus();
    GPIOA->BRR = GPIO_Pin_4;
    SPI_I2S_SendData(SPI1,0x20);
    SPI_I2S_SendData(SPI1,add2);
    SPI_I2S_SendData(SPI1,add1);
    SPI_I2S_SendData(SPI1,add0);
    GPIOA->BSRR = GPIO_Pin_4;
}
//address - 24位地址
//pHead   - 存储读出数据的头指针
//len     - 读出数据长度
void W25X_ReadData(u32 address,u8 *pHead,u16 len){
    u16 i;
    u8  add2,add1,add0;
    
    add2=(u8)(address>>16);
    add1=(u8)(address>>8);
    add0=(u8)(address);

    W25X_CheckBusyStatus();
    GPIOA->BRR = GPIO_Pin_4;
    SPI_I2S_SendData(SPI1,0x03);
    SPI_I2S_SendData(SPI1,add2);
    SPI_I2S_SendData(SPI1,add1);
    SPI_I2S_SendData(SPI1,add0);
    for(i=0;i<len;i++){
            SPI_I2S_SendData(SPI1,0xff);
          while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET);
        pHead=SPI_I2S_ReceiveData(SPI1);
    }
    GPIOA->BSRR = GPIO_Pin_4;
}
//address - 24位地址
//pHead   - 存储读出数据的头指针
//len     - 读出数据长度
void W25X_PageProgram(u32 address,u8 *pHead,u16 len){
    u16 i;
    u8  add2,add1,add0;
    
    add2=(u8)(address>>16);
    add1=(u8)(address>>8);
    add0=(u8)(address);

    W25X_WriteEnable();
    GPIOA->BRR = GPIO_Pin_4;
    SPI_I2S_SendData(SPI1,0x02);
    SPI_I2S_SendData(SPI1,add2);
    SPI_I2S_SendData(SPI1,add1);
    SPI_I2S_SendData(SPI1,add0);
    for(i=0;i<len;i++){
        SPI_I2S_SendData(SPI1,pHead);
        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET);
    }
    GPIOA->BSRR = GPIO_Pin_4;
}
u8 W25X_ReadManufacturer(void){
    u8 id;

    W25X_CheckBusyStatus();
    GPIOA->BRR = GPIO_Pin_4;
        SPI_I2S_SendData(SPI1,0x9f);
    id = SPI_I2S_ReceiveData(SPI1);
    GPIOA->BSRR = GPIO_Pin_4;

    return id;
}
此帖出自stm32/stm8论坛
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

6
 

请问SCK和MOSI线上有没有时钟和数据输出

                                 如果有时钟和数据输出,则硬件没有问题,是软件的问题。
此帖出自stm32/stm8论坛
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

7
 

懒得看你程序了,把我调好的贴给你参考

void SST25_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
   
  /* Enable SPI1 and GPIOA clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
  
  /* Configure SPI1 pins: NSS, SCK, MISO and MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure PB.12 as Output push-pull, used as Flash Chip select */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();

  /* SPI2 configuration */ 
  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_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);
  
  /* Enable SPI1  */
  SPI_Cmd(SPI1, ENABLE);   
}

/*******************************************************************************
* Function Name  : SPI_FLASH_ReadID
* Description    : Reads FLASH identification.
* Input          : None
* Output         : None
* Return         : FLASH identification
*******************************************************************************/
u32 SST25_ReadID(void)
{
  u32 Temp0 = 0, Temp1 = 0;

  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();
  
  /* Send "RDID " instruction */
  SPI_FLASH_SendByte(0x90);

  SPI_FLASH_SendByte(0);
  SPI_FLASH_SendByte(0);
  SPI_FLASH_SendByte(0);
  Temp0 = SPI_FLASH_ReadByte();
  Temp1 = SPI_FLASH_ReadByte();

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();
         
  return (Temp0 << 8) | Temp1;
}

/*******************************************************************************
* Function Name  : SPI_FLASH_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_FLASH_ReadByte(void)
{
  return (SPI_FLASH_SendByte(0x5A));
}

/*******************************************************************************
* Function Name  : SPI_FLASH_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_FLASH_SendByte(u8 byte)
{
  /* Loop while DR register in not emplty */
  while(SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET);

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

  /* Wait to receive a byte */
  while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET);

  /* Return the byte read from the SPI bus */
  return SPI_ReceiveData(SPI1);
}

/************************************************************************/
/* PROCEDURE: Read_Status_Register                    */
/*                                    */
/* This procedure read the status register and returns the byte.    */
/*                                    */
/* Input:                                */
/*        None                            */
/*                                    */
/* Returns:                                */
/*        byte                            */
/************************************************************************/
unsigned char Read_Status_Register()
{
    unsigned char byte = 0;
    SPI_FLASH_CS_LOW();            /* enable device */
    SPI_FLASH_SendByte(0x05);        /* send RDSR command */
    byte = SPI_FLASH_ReadByte();        /* receive byte */
    SPI_FLASH_CS_HIGH();            /* disable device */
    return byte;
}

/************************************************************************/
/* PROCEDURE: EWSR                            */
/*                                    */
/* This procedure Enables Write Status Register.              */
/*                                    */
/* Input:                                */
/*        None                            */
/*                                    */
/* Returns:                                */
/*        Nothing                            */
/************************************************************************/
void CMD_EWSR()
{
    SPI_FLASH_CS_LOW();            /* enable device */
    SPI_FLASH_SendByte(0x50);        /* enable writing to the status register */
    SPI_FLASH_CS_HIGH();            /* disable device */
}

/************************************************************************/
/* PROCEDURE: WRSR                            */
/*                                    */
/* This procedure writes a byte to the Status Register.            */
/*                                    */
/* Input:                                */
/*        byte                            */
/*                                    */
/* Returns:                                */
/*        Nothing                            */
/************************************************************************/
void CMD_WRSR(u8 byte)
{
    SPI_FLASH_CS_LOW();            /* enable device */
    SPI_FLASH_SendByte(0x01);        /* select write to status register */
    SPI_FLASH_SendByte(byte);        /* data that will change the status of BPx 
                        or BPL (only bits 2,3,7 can be written) */
    SPI_FLASH_CS_HIGH();            /* disable the device */
}

/************************************************************************/
/* PROCEDURE: WREN                            */
/*                                    */
/* This procedure enables the Write Enable Latch.            */
/*                                    */
/* Input:                                */
/*        None                            */
/*                                    */
/* Returns:                                */
/*        Nothing                            */
/************************************************************************/
void CMD_WREN()
{
    SPI_FLASH_CS_LOW();            /* enable device */
    SPI_FLASH_SendByte(0x06);        /* send WREN command */
    SPI_FLASH_CS_HIGH();            /* disable device */
}

/************************************************************************/
/* PROCEDURE: WRDI                            */
/*                                    */
/* This procedure disables the Write Enable Latch.            */
/*                                    */
/* Input:                                */
/*        None                            */
/*                                    */
/* Returns:                                */
/*        Nothing                            */
/************************************************************************/
void CMD_WRDI()
{
    SPI_FLASH_CS_LOW();            /* enable device */
    SPI_FLASH_SendByte(0x04);        /* send WRDI command */
    SPI_FLASH_CS_HIGH();            /* disable device */
}

//************************************************************************
// This procedure reads one address of the device.  It will return the
// byte read in variable byte.
//************************************************************************
u8 SST25_ReadByte(u32 Dst)
{
    unsigned char byte = 0;    

    SPI_FLASH_CS_LOW();            /* enable device */
    SPI_FLASH_SendByte(0x03);         /* read command */
    SPI_FLASH_SendByte(((Dst & 0xFFFFFF) >> 16));    /* send 3 address bytes */
    SPI_FLASH_SendByte(((Dst & 0xFFFF) >> 8));
    SPI_FLASH_SendByte(Dst & 0xFF);
    byte = SPI_FLASH_ReadByte();
    SPI_FLASH_CS_HIGH();            /* disable device */
    return byte;            /* return one byte read */
}

//***************************************************************************************
// This procedure reads multiple addresses of the device and stores data into buffer.
//***************************************************************************************
void SST25_ReadBuffer(u32 nAddr, u32 nSize, u8* pBuf)
{
    u32 i = 0;
    SPI_FLASH_CS_LOW();                    // enable device
    SPI_FLASH_SendByte(0x03);            //read command */
    SPI_FLASH_SendByte((u8)(nAddr>>16));    // send 3 address bytes
    SPI_FLASH_SendByte((u8)(nAddr>>8 ));
    SPI_FLASH_SendByte((u8)nAddr);
    for (i = 0; i < nSize; i++)        // read until no_bytes is reached
    {
        pBuf = SPI_FLASH_ReadByte();        // receive byte and store to buffer
    }
    SPI_FLASH_CS_HIGH();                /* disable device */
}

void SST25_WriteEnable(u8 bEn)
{
    if(bEn)
    {
        CMD_EWSR();
        CMD_WRSR(0);
    }
    else
    {
        CMD_EWSR();
        CMD_WRSR(0x0C);
    }
}
//************************************************************************/
// This procedure programs one address of the device.
// Assumption:  Address being programmed is already erased and is NOT block protected.
//************************************************************************/
void SST25_WriteByte(u32 Dst, u8 byte)
{
    SPI_FLASH_CS_LOW();                /* enable device */
    SPI_FLASH_SendByte(0x02);             /* send Byte Program command */
    SPI_FLASH_SendByte(((Dst & 0xFFFFFF) >> 16));    /* send 3 address bytes */
    SPI_FLASH_SendByte(((Dst & 0xFFFF) >> 8));
    SPI_FLASH_SendByte(Dst & 0xFF);
    SPI_FLASH_SendByte(byte);            /* send byte to be programmed */
    SPI_FLASH_CS_HIGH();                /* disable device */

    SPI_FLASH_WaitReady();
}


//***************************************************************************************
// This procedure write multiple data from buffer to the device.
//***************************************************************************************
void SST25_WriteBuffer(u32 nAddr, u32 nSize, u8* pBuf)
{
    u32 i = 0;

    SPI_FLASH_WaitReady();
    CMD_WREN();
    SPI_FLASH_CS_LOW();                        // enable device
    SPI_FLASH_SendByte(0xAF);                // send AAI command
    SPI_FLASH_SendByte((u8)(nAddr>>16));    // send 3 address bytes
    SPI_FLASH_SendByte((u8)(nAddr>>8 ));
    SPI_FLASH_SendByte((u8)nAddr);
    SPI_FLASH_SendByte(pBuf[0]);                // send byte to be programmed */
    SPI_FLASH_CS_HIGH();                    // disable device */

    for(i=1;i<nSize;i++)
    {
        SPI_FLASH_WaitReady();
        SPI_FLASH_CS_LOW();                    // enable device
        SPI_FLASH_SendByte(0xAF);            // send AAI command
        SPI_FLASH_SendByte(pBuf);            // send byte to be programmed
        SPI_FLASH_CS_HIGH();                // disable device
    }
    CMD_WRDI();
    SPI_FLASH_WaitReady();
}

//************************************************************************
// This procedure erases the entire Chip.
//************************************************************************
void SST25_EraseChip()
{
    CMD_WREN();

    SPI_FLASH_CS_LOW();                /* enable device */
    SPI_FLASH_SendByte(0x60);            /* send Chip Erase command */
    SPI_FLASH_CS_HIGH();                /* disable device */

    CMD_WRDI();
    SPI_FLASH_WaitReady();            // waste time until not busy
}

//************************************************************************
// This procedure Sector Erases the Chip.
//************************************************************************
void SST25_EraseSector(u32 Dst)
{
    SPI_FLASH_CS_LOW();                /* enable device */
    SPI_FLASH_SendByte(0x20);            /* send Sector Erase command */
    SPI_FLASH_SendByte(((Dst & 0xFFFFFF) >> 16));     /* send 3 address bytes */
    SPI_FLASH_SendByte(((Dst & 0xFFFF) >> 8));
    SPI_FLASH_SendByte(Dst & 0xFF);
    SPI_FLASH_CS_HIGH();                /* disable device */
}

//************************************************************************
// This procedure Block Erases the Chip.
//************************************************************************
void SST25_EraseBlock(u32 Dst)
{
    SPI_FLASH_CS_LOW();                /* enable device */
    SPI_FLASH_SendByte(0x52);            /* send Block Erase command */
    SPI_FLASH_SendByte(((Dst & 0xFFFFFF) >> 16));     /* send 3 address bytes */
    SPI_FLASH_SendByte(((Dst & 0xFFFF) >> 8));
    SPI_FLASH_SendByte(Dst & 0xFF);
    SPI_FLASH_CS_HIGH();                /* disable device */
}

//************************************************************************
// This procedure waits until device is no longer busy (can be used by
// Byte-Program, Sector-Erase, Block-Erase, Chip-Erase).
//************************************************************************
void SPI_FLASH_WaitReady()
{
    while (Read_Status_Register() & 0x01);
}

//************************************************************************
// This procedure waits until device is no longer busy for AAI mode.
//************************************************************************
void Wait_Busy_AAI()
{
    while (Read_Status_Register() == 0x43)    /* waste time until not busy */
        Read_Status_Register();
}

//************************************************************************
// This procedure checks to see if WEL bit set before program/erase.
//************************************************************************
void WREN_Check()
{
    unsigned char byte;
    byte = Read_Status_Register();    /* read the status register */
    if (byte != 0x02)        /* verify that WEL bit is set */
    {
//        while(1)
                    /* option: insert a display to view error on LED? */
    }
}

//************************************************************************
// This procedure checks for AAI and WEL bit once in AAI mode.
//************************************************************************
void WREN_AAI_Check()
{
    unsigned char byte;
    byte = Read_Status_Register();    /* read the status register */
    if (byte != 0x42)        /* verify that AAI and WEL bit is set */
    {
//        while(1)        
                    /* option: insert a display to view error on LED? */
    }
}
此帖出自stm32/stm8论坛
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(初级)

8
 

另外再把测试程序送给懒惰的你,送佛送到西

    for(tmp=0;tmp<0x100;tmp++)
    {
        pBuffer1[tmp] = tmp;
        pBuffer2[tmp] = 0;
    }

    SST25_Init();
    ChipID = SST25_ReadID();
    SST25_WriteEnable(1);
    SST25_EraseChip();

    SST25_WriteBuffer(0, 0x100, pBuffer1);
    SST25_ReadBuffer (0, 0x100, pBuffer2);
此帖出自stm32/stm8论坛
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

9
 

晕,你的初始化跟我的是一样的为什么我的不中

                                 另外我的函数都是把原来用软件模拟SPI的函数翻译过来的,同时采参考了ST的例程,应该没问题,别老说我懒:(
此帖出自stm32/stm8论坛
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

10
 

我也遇到过这个问题:是这样的:

因为SPI_I2S_ReceiveData(SPI1);只从接收缓冲区中取数,而W25X20仍需要发送时钟信号才能读出数据.而且SPI_I2S_SendData(SPI1,0x05);也需要读出数据才能保证后续读出数据正确.所以你无论是送数还是取数,都应该完成这四个语句:
       u8 SPI_FLASH_SendByte(u8 byte)
{
  /* Loop while DR register in not emplty */
  while(SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET);

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

  /* Wait to receive a byte */
  while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET);

  /* Return the byte read from the SPI bus */
  return SPI_ReceiveData(SPI1);
}

    
此帖出自stm32/stm8论坛
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

11
 

SPI的时钟总是Master控制的

而STM32就是Master

你先把我这个demo跑,然后一步步换成你自己的。
从哪里开始有问题,不就一下子就出来了吗。

另外,懒惰的不是你,是我,因为我实在无法打起精神看你的source code,所以才直接把我的测试程序发出来。

我这个程序SPI1和SPI2都有用过,都可以,我用的是SST25VF010,128K byte的
此帖出自stm32/stm8论坛
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

12
 

多谢楼上

我知道什么原因了
刚才把原来在51下用模拟方式读写W25X20的程序改了改,主要是操作IO口的地方,其它一样,在103下运行OK了,能正常读些FLASH了,回头又改了下用真正SPI口读写W25X20的程序,发现真正SPI口方式的读些速度有可能没有模拟的方式快,因为真正SPI口的方式执行的代码好像多一些,下面是我模拟的:
#include "stm32f10x_lib.h"

u8   SPI_ReadByte(void);
void SPI_WriteByte(u8 wByte);
void W25X_CheckBusyStatus(void);
void W25X_WriteEnable(void);
void W25X_SectorErase(u16 sector);
void W25X_ReadData(u32 address,u8 *pHead,u16 len);
void W25X_PageProgram(u32 address,u8 *pHead,u16 len);
//u8   W25X_ReadManufacturer(void);

///////////////////////////////////////////////////////////////////////////////
//W25X系列FLASH驱动程序:
//        W25X10~W25X64,容量128K、256K、512K、1M、2M、4M、8M、16M Bytes
//
//        内部存储结构相同,基本存储单元为页,页容量均为256 Bytes,在整个芯片范
//        围内连续读,但以页为单位写,即一页内如果写不够256 Bytes的话则剩余空间
//        被自动写入FFH
//
//        擦除时是以扇区为单位的,每个扇区容量为4K Bytes,即16页
///////////////////////////////////////////////////////////////////////////////
//Data is shifted out on the falling edge of the CLK.
u8 SPI_ReadByte(void){
    u8 i,j;
    
    j=0;
    for(i=0;i<8;i++){
        GPIOA->BRR  = GPIO_Pin_5;
        GPIOA->BSRR = GPIO_Pin_5;
        
        j<<=1;
        if(GPIOA->IDR & GPIO_Pin_6){j++;}
    }

    return j;
}
//Data is shifted in on the rising edge of the CLK.
void SPI_WriteByte(u8 wByte){
    u8 i;
    
    for(i=0;i<8;i++){
        if(wByte&0x80){GPIOA->BSRR = GPIO_Pin_7;} 
        else{GPIOA->BRR  = GPIO_Pin_7;}
        wByte<<=1;
        
        GPIOA->BRR  = GPIO_Pin_5;
        GPIOA->BSRR = GPIO_Pin_5;
    }
}
//忙状态寄存器的BUSY位(D0位)只读
//在写动作(页写、扇区擦除、块擦除、芯片擦除、写状态寄存器)期间BUSY位有效(指示忙),其余状态非忙
//此函数执行后一直等到非忙状态才退出
void W25X_CheckBusyStatus(void){
    GPIOA->BRR = GPIO_Pin_4;
    SPI_WriteByte(0x05);
    while(SPI_ReadByte()&0x01);
    GPIOA->BSRR = GPIO_Pin_4;
}
void W25X_WriteEnable(void){
    W25X_CheckBusyStatus();

    GPIOA->BRR = GPIO_Pin_4;
    SPI_WriteByte(0x06);
    GPIOA->BSRR = GPIO_Pin_4;
}
//扇区擦除
void W25X_SectorErase(u16 sector){
    u32 address;
    u8  add2,add1,add0;

    address = sector*4096L;
    add2=(u8)(address>>16);
    add1=(u8)(address>>8);
    add0=(u8)(address);

    W25X_WriteEnable();
    W25X_CheckBusyStatus();
    
    GPIOA->BRR = GPIO_Pin_4;
    SPI_WriteByte(0x20);
    SPI_WriteByte(add2);
    SPI_WriteByte(add1);
    SPI_WriteByte(add0);
    GPIOA->BSRR = GPIO_Pin_4;
}
//address - 24位地址
//pHead   - 存储读出数据的头指针
//len     - 读出数据长度
void W25X_ReadData(u32 address,u8 *pHead,u16 len){
    u16 i;
    u8  add2,add1,add0;
    
    add2=(u8)(address>>16);
    add1=(u8)(address>>8);
    add0=(u8)(address);

    W25X_CheckBusyStatus();
    
    GPIOA->BRR = GPIO_Pin_4;
    SPI_WriteByte(0x03);
    SPI_WriteByte(add2);
    SPI_WriteByte(add1);
    SPI_WriteByte(add0);
    for(i=0;i<len;i++){pHead=SPI_ReadByte();}
    GPIOA->BSRR = GPIO_Pin_4;
}
//address - 24位地址
//pHead   - 存储读出数据的头指针
//len     - 读出数据长度
void W25X_PageProgram(u32 address,u8 *pHead,u16 len){
    u16 i;
    u8  add2,add1,add0;
    
    add2=(u8)(address>>16);
    add1=(u8)(address>>8);
    add0=(u8)(address);

    W25X_WriteEnable();
    GPIOA->BRR = GPIO_Pin_4;
    SPI_WriteByte(0x02);
    SPI_WriteByte(add2);
    SPI_WriteByte(add1);
    SPI_WriteByte(add0);
    for(i=0;i<len;i++){SPI_WriteByte(pHead);}
    GPIOA->BSRR = GPIO_Pin_4;
}
/*u8 W25X_ReadManufacturer(void){
    u8 id;

    W25X_CheckBusyStatus();
    GPIOA->BRR = GPIO_Pin_4;
    SPI_WriteByte(0x9f);
    id = SPI_ReadByte();
    GPIOA->BSRR = GPIO_Pin_4;

    return id;
}*/
此帖出自stm32/stm8论坛
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

13
 

楼上应该用示波器观察,才能正确判断哪种方式快

                                 请问用SPI接口时,你的时钟频率设置为多少?
此帖出自stm32/stm8论坛
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

14
 

香版把这个问题和I2C的一并反馈给Demo程序的设计者吧

while语句太多了,动辄就是我等我等我还等,CPU在这里Loop耗电。

其实如果使用多任务的嵌入式OS,这个问题也可以得到解决,因为时间片切换的缘故,此AP的while等待,其他进程可以做其他的事情。
此帖出自stm32/stm8论坛
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

15
 

在广大兄弟的帮助下终于搞定了,但是还有疑问

                                  
此帖出自stm32/stm8论坛
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

16
 

请看我的读函数:

void W25X_ReadData(u32 address,u8 *pHead,u16 len){
    u16  i;
    u8   add2,add1,add0;
    
    add2=(u8)(address>>16);
    add1=(u8)(address>>8);
    add0=(u8)(address);

    W25X_CheckBusyStatus();
    GPIOA->BRR = GPIO_Pin_4;
        while((SPI1->SR & SPI_I2S_FLAG_TXE) == RESET);       //1-送读命令03H
        SPI1->DR=0x03;
        while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET);
        i=SPI1->DR;
        
        while((SPI1->SR & SPI_I2S_FLAG_TXE) == RESET);       //2-送高字节地址
        SPI1->DR=add2;
        while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET);
    i=SPI1->DR;
        
        while((SPI1->SR & SPI_I2S_FLAG_TXE) == RESET);       //3-送中字节地址
        SPI1->DR=add1;
        while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET);
    i=SPI1->DR;
        
        while((SPI1->SR & SPI_I2S_FLAG_TXE) == RESET);       //4-送低字节地址
    SPI1->DR=add0;
        while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET);
    i=SPI1->DR;
        
        while((SPI1->SR & SPI_I2S_FLAG_TXE) == RESET);       //5-???读出一个字节多余数据????
        SPI1->DR=0xff;
        while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET);
        i = SPI1->DR;
    for(i=0;i<len;i++){
            while((SPI1->SR & SPI_I2S_FLAG_TXE) == RESET);
            SPI1->DR=0x5a;
            while((SPI1->SR & SPI_I2S_FLAG_RXNE) == RESET);
        pHead = SPI1->DR;
    }
    GPIOA->BSRR = GPIO_Pin_4;
}

问题是:为何必须在5中要读出一个字节的多余数据?
我在调试很久后发现如果不在5中读出一个字节多余数据的话那么读出的数据序列中的第一个字节就是00,如果读出一个字节的多余数据后就全对了,按理说在第4步之后就可以越过5进行数据序列的读取了,为什么非要有第5步才能读出正确数据呢?(我事先写入FLASH中的数据是对的,这个不用怀疑)
 
 
此帖出自stm32/stm8论坛
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

17
 

这是因为你不了解SPI的工作原理

                                 我不知道你的Flash是如何操作的,但你可以用示波器仔细看看,很容易就明白了。
此帖出自stm32/stm8论坛
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

18
 

是的,我还是不了解这个SPI接口的工作原理

                                 不是用示波器看的问题,我现在已经搞定了,像我在17楼说的,多出了一个空读操作,这是我不明白的地方。虽然我17楼贴上去的函数都好用了,但我还是对5处不太明白,现在暂时不用SPI接口,还用我原来模拟的时序,很好用,因为项目紧,等做完项目再研究为什么多出来一个空读操作
此帖出自stm32/stm8论坛
 
 
 

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

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表