GPIO口模拟SPI - 驱动W25Qxx

废话少说,直接上代码:
DataFlash_reg.h:

/*
Using SPIO simulator
PB8  -- spi cs
PA9  -- spi clock
PA10 -- spi MOSI
PB7  -- spi MISO
PA8  -- hold
PC4  -- Write protect
*/
#define SPI_CS_Port         gpioPortB 
#define SPI_CS_Pin          8
#define SPI_CS              (*((uint32_t *)(BITBAND_PER_BASE + (((uint32_t)&(GPIO->P[SPI_CS_Port].DOUT) - PER_MEM_BASE) * 32) + (SPI_CS_Pin * 4))))

#define SPI_CLK_Port        gpioPortA 
#define SPI_CLK_Pin         9
#define SPI_CLK             (*((uint32_t *)(BITBAND_PER_BASE + (((uint32_t)&(GPIO->P[SPI_CLK_Port].DOUT) - PER_MEM_BASE) * 32) + (SPI_CLK_Pin * 4))))

#define SPI_MOSI_Port        gpioPortA 
#define SPI_MOSI_Pin         10
#define SPI_MOSI             (*((uint32_t *)(BITBAND_PER_BASE + (((uint32_t)&(GPIO->P[SPI_MOSI_Port].DOUT) - PER_MEM_BASE) * 32) + (SPI_MOSI_Pin * 4))))

#define SPI_MISO_Port        gpioPortB 
#define SPI_MISO_Pin         7
#define SPI_MISO             (*((uint32_t *)(BITBAND_PER_BASE + (((uint32_t)&(GPIO->P[SPI_MISO_Port].DIN) - PER_MEM_BASE) * 32) + (SPI_MISO_Pin * 4))))


unsigned char DataFlash_Write_Byte(unsigned char Data);

DataFlash_cmd.h:

#ifndef __DATAFLASH_CMD_H__
#define __DATAFLASH_CMD_H__

#define W25X_BUSY       0
#define W25X_NotBUSY    1    
#define Dummy_Byte1     0xA5


/*********************************************
 - W25X16的操作指令表,MCU通过向W25X16
  发送以下指令就可以对W25X16进行以下的操作
*********************************************/
#define W25X_WriteEnable            0x06    //Write Enable
#define W25X_WriteEnableVSR         0x50    //Write Enable for Volatile Status Register
#define W25X_WriteDisable           0x04    //Write Disable
#define W25X_ReadStatusReg1         0x05    //读状态寄存器1:S7~S0
#define W25X_ReadStatusReg2         0x35    //读状态寄存器2:S15~S8
#define W25X_WriteStatusReg         0x01    //写读状态寄存器:BYTE1:S7~S0  BYTE2:S15~S8
#define W25X_PageProgram            0x02    //单页编程:BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0  BYTE4:D7~D0
#define W25X_SectorErase            0x20    //扇区擦除:4K  BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0
#define W25X_BlockErase32K          0x52    //块擦除:32K  BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0
#define W25X_BlockErase64K          0xD8    //块擦除:64K  BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0
#define W25X_ChipErase              0xC7    //芯片擦除
#define W25X_EraseSuspend           0x75    //暂停擦除
#define W25X_EraseResume            0x7A    //恢复擦除
#define W25X_PowerDown              0xB9    //掉电
#define W25X_ContinuousReadMode     0xFF    //连续读模式

#define W25X_ReadData               0x03    //读数据:BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0  BYTE4:D7~D0
#define W25X_FastReadData           0x0B    //快速读取:BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0  BYTE4:dummy  BYTE5:D7~D0
#define W25X_FastReadDual           0x3B    //快速双读取:BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0  BYTE4:dummy  BYTE5:D7~D0

#define W25X_ReleasePowerDown       0xAB   
#define W25X_DeviceID               0xAB 
#define W25X_ManufactDeviceID       0x90 
#define W25X_JedecDeviceID          0x9F 

#endif

DataFlash_reg.c:

#include <stdint.h>
#include <stdbool.h>
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "DataFlash_reg.h"
#include "DataFlash_cmd.h"

/*
Using SPIO simulator
PB8  -- spi cs
PA9  -- spi clock
PA10 -- spi MOSI
PB7  -- spi MISO
PA8  -- hold
PC4  -- Write protect
*/
void DataFlash_Initial_IO(void)
{
    GPIO_PinModeSet(gpioPortB,8,gpioModePushPull,1);
    GPIO_PinModeSet(gpioPortA,9,gpioModePushPull,1);
    GPIO_PinModeSet(gpioPortA,10,gpioModePushPull,1);
    GPIO_PinModeSet(gpioPortB,7,gpioModeInputPull,1);
    GPIO_PinModeSet(gpioPortA,8,gpioModePushPull,1);
    GPIO_PinModeSet(gpioPortC,4,gpioModePushPull,1);
}

//*************** Write enable ****************************  OK
void DataFlash_WriteEnable  (void)
{
    SPI_CS = 0;
    __NOP();
    __NOP();
    DataFlash_Write_Byte(W25X_WriteEnable);
    __NOP();
    __NOP();
    SPI_CS = 1;
}

//*************** Write disable ****************************    OK
void DataFlash_WriteDisable (void)
{
    SPI_CS = 0;
    __NOP();
    __NOP();
    DataFlash_Write_Byte(W25X_WriteDisable);
    __NOP();
    __NOP();
    SPI_CS = 1;
}

//***************判BUSY********************************
unsigned char DataFlash_SPI_BUSY_OrNot (void) //在读和写之前得先判断FLASH是否BUSY
{                        //BUSY的原因是擦除,或是连续读写
    unsigned char k;          //如果没有以上方式,不必判定可以写读  
    SPI_CS = 0;
    __NOP();
    __NOP();
    DataFlash_Write_Byte(W25X_ReadStatusReg1);
    k = DataFlash_Write_Byte(Dummy_Byte1);
    __NOP();
    __NOP();
    SPI_CS = 1;
    if(k&0x01)return (W25X_BUSY);
    else return (W25X_NotBUSY);
}

void SPI_Flash_Read(uint32_t ReadAddr, uint32_t numBytes,void *data)
{
    uint8_t *rxBuffer = (uint8_t *) data;

    /* Enable chip select */
    SPI_CS = 0;
    __NOP();
    __NOP();

    DataFlash_Write_Byte(W25X_ReadData);
    DataFlash_Write_Byte(ReadAddr >> 16);
    DataFlash_Write_Byte(ReadAddr >> 8);
    DataFlash_Write_Byte(ReadAddr);
    while (numBytes--)
    { 
        *rxBuffer = DataFlash_Write_Byte(Dummy_Byte1); //Read one byte
        rxBuffer++;
    }

    /* Disable chip select */
    __NOP();
    __NOP();
    SPI_CS = 1;
}

/*******************************************************************************
* Function Name  : SPI_FLASH_ReadID
* Description    : Reads FLASH identification.
* Input          : None
* Output         : None
* Return         : FLASH identification
*******************************************************************************/

unsigned long SPI_Flash_ReadID(void)
{
    unsigned int Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;

   /* Enable chip select */
    SPI_CS = 0;
    __NOP();
    __NOP();

    /* Send "RDID " instruction */
    DataFlash_Write_Byte(0x9F);
    /* Read a byte from the FLASH */
    Temp0 = DataFlash_Write_Byte(Dummy_Byte1);
    /* Read a byte from the FLASH */
    Temp1 = DataFlash_Write_Byte(Dummy_Byte1);
    /* Read a byte from the FLASH */
    Temp2 = DataFlash_Write_Byte(Dummy_Byte1);

    /* Disable chip select */
    __NOP();
    __NOP();
    SPI_CS = 1;

    Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

    return Temp;
}


////每次写一页面 地址低8位应为0
//void SPI_Flash_Page_Write(uint32_t pageNum, unsigned char* data)
//{
//    uint8_t *rxBuffer = data;
//    while(1)
//    {
//        if(SPI_BUSY_OrNot() == W25X_NotBUSY) break;
//    }
//    
//    WriteEnable();   //写允许
//    
//    /* Enable chip select */
//    GPIO_PinOutClear(Flash_SPI_CS_PORT, Flash_SPI_CS_BIT);
//    
//    SPI_FlashWrite(W25X_PageProgram);
//    
//    unsigned int WriteAddr = pageNum<<8;
//    
//    SPI_FlashWrite((WriteAddr >> 16));
//    SPI_FlashWrite((uint32_t)(WriteAddr >> 8));
//    SPI_FlashWrite((uint32_t) WriteAddr);
//    
//    for(int i=0;i<SPI_FLASH_PAGE_SIZE;i++)
//    { 
//        SPI_FlashWrite(*rxBuffer); 
//        rxBuffer++;
//    }
//    /* Disable chip select */
//    GPIO_PinOutSet(Flash_SPI_CS_PORT, Flash_SPI_CS_BIT);
//    
//    WriteDisable();//写禁止
//}
//
////**************片擦除****************** OK
//void SPI_EraseDevice(void)
//{
//    while(1)
//    {
//        if(SPI_BUSY_OrNot() == W25X_NotBUSY) break;
//    }
//    WriteEnable();   //写允许
//    GPIO_PinOutClear(Flash_SPI_CS_PORT, Flash_SPI_CS_BIT);
//    SPI_FlashWrite(W25X_ChipErase);
//    GPIO_PinOutSet(Flash_SPI_CS_PORT, Flash_SPI_CS_BIT);
//}




unsigned char DataFlash_Write_Byte(unsigned char Data)
{
    unsigned char Out = 0;
    unsigned char i = 0;

    SPI_CLK = 0;
    for(i = 0; i < 8; i++)
    {
        if(Data & 0x80)SPI_MOSI = 1;
        else SPI_MOSI = 0;
        Data = Data << 1;
        __NOP();
        __NOP();
        __NOP();
        SPI_CLK = 1;
        if(SPI_MISO)Out |= 0x80 >> i;
        __NOP();
        __NOP();
        __NOP();
        SPI_CLK = 0;
    }
    SPI_CLK = 0;

    return Out;
}

猜你喜欢

转载自blog.csdn.net/EFM32/article/details/50500089
今日推荐