MT25QL128/MTQL256_FLASH驱动——基于华大单片机

MT25QL256的数据手册:

https://download.csdn.net/download/weixin_47041339/85933399?spm=1001.2014.3001.5501

关于FLASH的具体信息自行查看数据手册。

有一点特别注意:MT25QL如果有#HOLD引脚,必须要拉高!不然数据写不进去

mt25ql.h

#ifndef  _MT25QL_H
#define  _MT25QL_H


# ifdef __cplusplus
 extern "C" {
# endif 
/***用华大的库****/
#include "hc32_ddl.h"
#include "cmsis_os2.h"
	
	 
	 
/* 片选信号控制引脚 */
#define SPI_CSPIN_HIGH()                  (GPIO_SetPins(GPIO_PORT_B, GPIO_PIN_02))
#define SPI_CSPIN_LOW()                   (GPIO_ResetPins(GPIO_PORT_B,GPIO_PIN_02))

/**MT25QL256有HOLD引脚,发数据时必须拉高**/ 
#define SPI_HOLD_PIN_HIGH()               (GPIO_SetPins(GPIO_PORT_B, GPIO_PIN_08))
#define SPI_HOLD_PIN_LOW()                   (GPIO_ResetPins(GPIO_PORT_B,GPIO_PIN_08))
	 
	 
	  
#define FLASH_MAX_ADDR                    (0xFFFFFFUL)	//最大地址 
#define FLASH_PAGE_SIZE                   (0x100U)      //一页大小,最大256字节
		
		
/************************指令定义***********************************/	 
	 
	 	 //写命令
	 #define	WRITE_ENABLE_cmd		(0x06U)	//允许写/写使能
	 #define	WRITE_RESET_cmd		    (0x66)	//允许写/写使能
	 #define	WRITE_DISABLE_cmd		(0x04U)	//禁止写
	 #define	WRITE_PAGE_cmd			(0X02U)	//写一页
	 #define    WRITE_STATUS_REG_cmd	(0x01U)	//写状态寄存器
	 
	 
	 //读命令
	 #define	READ_STATUS_REG_cmd		 0x05	 //读取状态寄存器
	 #define	READ_FLAG_STATUS_REG	 0x70	 //读状态寄存器标志位
	 #define	READ_cmd				 0x03
	 #define 	READ_4BYTE_cmd			 0x13
	 #define	READ_ID_cmd				 0X9E
	 #define    Page_Read_Cmd            0xD2   //读取一页
	 
	 
	 ///擦除命令
	 #define	ERASE_32KB_cmd			0x52	//擦除32KB
	 #define	ERASE_4KB_cmd			0x20	//擦除4KB
	 #define	ERASE_SECTOR_cmd 		0XD8	//擦除扇区
	 #define    ERASE_BULK_cmd			0x60	//擦除磁盘
	 #define	ERASE_4BYTE_cmd			0xDC	//擦除4字节

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


uint32_t 	SPI_FLASH_test_fuc(void)	 ;     //测试函数

void        mt25ql_init(p_mt25ql_dev_t pdev,read_write_t fun) ;  //初始化函数


unsigned char StatusRegisterRead(void);





	 # ifdef __cplusplus
}
# endif
# endif

mt25ql.c

#include "mt25ql.h"
#include "bspspi.h"
#include "bspuart.h"
#include "string.h"

static p_mt25ql_dev_t  p_mt25ql_dev;

/********************************************************
 *功能描述:初始化#CS片选引脚和#HOLD引脚
 *******************************************************/
static void mt25ql_gpio_init(void)
{
			stc_gpio_init_t stcGpioInit;

    /* Register write enable for some required peripherals. */
    GPIO_Unlock();
	
		(void)GPIO_StructInit(&stcGpioInit);
		stcGpioInit.u16PinDir = PIN_DIR_OUT;
		stcGpioInit.u16PullUp = PIN_PU_ON;
		stcGpioInit.u16PinDrv = PIN_DRV_HIGH;
		(void)GPIO_Init(GPIO_PORT_B,GPIO_PIN_02, &stcGpioInit);
	    (void)GPIO_Init(GPIO_PORT_B,GPIO_PIN_08, &stcGpioInit);
	
	    /* Register write protected for some required peripherals. */
    GPIO_Lock();
		SPI_CSPIN_HIGH() ;
		SPI_HOLD_PIN_HIGH() ;
}

/**********************************************
功能描述:读取FLASH的状态
参数输入:无
返    回:状态寄存器的内容
***********************************************/
unsigned char StatusRegisterRead(void)
{
  unsigned char status;
  SPI_CSPIN_LOW();
	
	(void)spi3_read_write_byte(READ_STATUS_REG_cmd); 
  status = spi3_read_write_byte(0xff);
  SPI_CSPIN_HIGH();
  return status;
	
}


/********************************************************
 * 功能描述: SPI flash 允许写/写使能
 *******************************************************/
static void SpiFlash_WriteEnable(void)
{
    SPI_CSPIN_LOW();
    (void)spi3_read_write_byte(WRITE_ENABLE_cmd);
    SPI_CSPIN_HIGH();
}

/********************************************************
 *功能描述: SPI flash RESET
 *******************************************************/
static void SpiFlash_RESET_FUC(void)
{
    SPI_CSPIN_LOW();
    (void)spi3_read_write_byte(WRITE_RESET_cmd);  //允许复位
    SPI_CSPIN_HIGH();
	DDL_DelayMS(3);
	SPI_CSPIN_LOW();
	    (void)spi3_read_write_byte(0x99);		//复位
    SPI_CSPIN_HIGH();	
}


/********************************************************
 * 功能描述: SPI flash wait for write operation end function
 *            //SPI等待写完
 * @retval Ok                   //写入成功
 * @retval ErrorTimeout         //超时
 *******************************************************/
static en_result_t SpiFlash_WaitForWriteEnd(void)
{
    en_result_t enRet = Ok;
    uint8_t u8Status;
    uint32_t u32Timeout;
    stc_clk_freq_t stcClkFreq;

    (void)CLK_GetClockFreq(&stcClkFreq);
    u32Timeout = stcClkFreq.sysclkFreq / 1000U;
    SPI_CSPIN_LOW();
    (void)spi3_read_write_byte(READ_STATUS_REG_cmd);	//读状态寄存器
    do
    {
        u8Status = spi3_read_write_byte(0xffU);
        u32Timeout--;
    } while ((u32Timeout != 0UL) &&
             ((u8Status & FLASH_BUSY_BIT_flag) == FLASH_BUSY_BIT_flag));

    if (FLASH_BUSY_BIT_flag == u8Status)
    {
        enRet = ErrorTimeout;
    }
    SPI_CSPIN_HIGH();

    return enRet;
}


/*****************************************************************************
 * @brief SPI flash page write program function
 *				//SPI flash写一页函数
 * @param [in] u32Addr                 	   地址
 * @param [in] pData                       发送数据缓冲区的指针
 * @param [in] len                         发送数据长度
 * @retval Error                           写入失败
 * @retval Ok                              写入成功
 *****************************************************************************/
static en_result_t SpiFlash_WritePage(uint32_t u32Addr, const uint8_t pData[], uint16_t len)
{
    en_result_t enRet;
    uint16_t u16Index = 0U;

    if ((u32Addr > FLASH_MAX_ADDR) || (NULL == pData) || (len > FLASH_PAGE_SIZE))
    {
        enRet = Error;
    }
    else
    {
        SpiFlash_WriteEnable();
        /* Send data to flash */
        SPI_CSPIN_LOW();
        (void)spi3_read_write_byte(WRITE_PAGE_cmd);
        (void)spi3_read_write_byte((uint8_t)((u32Addr & 0xFF0000UL) >> 16U));
        (void)spi3_read_write_byte((uint8_t)((u32Addr & 0xFF00U) >> 8U));
        (void)spi3_read_write_byte((uint8_t)(u32Addr & 0xFFU));
        while (0U != (len--))
        {
            (void)spi3_read_write_byte(pData[u16Index]);
            u16Index++;
        }
        SPI_CSPIN_HIGH();
        /* Wait for flash idle */
        enRet = SpiFlash_WaitForWriteEnd();
    }

    return enRet;
}


/**************************************************************************
 * @brief  SPI flash read data function
 *         //读取FLASH
 * @param  [in] u32Addr             FLASH地址            
 * @param  [out] pData              数据缓冲区指针        
 * @param  [in] len                 读取的数据长度        
 * @retval Error                    读取失败
 * @retval Ok                       读取成功
 *************************************************************************************/
static en_result_t SpiFlash_ReadData(uint32_t u32Addr, uint8_t pData[], uint16_t len)
{
    en_result_t enRet = Ok;
    uint16_t u16Index = 0U;

    if ((u32Addr > FLASH_MAX_ADDR) || (NULL == pData))
    {
        enRet = Error;
    }
    else
    {
        SpiFlash_WriteEnable();
        /* 向flash发送指令*/
        SPI_CSPIN_LOW();
        (void)spi3_read_write_byte(READ_cmd);
        (void)spi3_read_write_byte((uint8_t)((u32Addr & 0xFF0000UL) >> 16U));
        (void)spi3_read_write_byte((uint8_t)((u32Addr & 0xFF00U) >> 8U));
        (void)spi3_read_write_byte((uint8_t)(u32Addr & 0xFFU));
        while (0U != (len--))
        {
            pData[u16Index] = spi3_read_write_byte(FLASH_DUMMY_BYTE_VALUE);
            u16Index++;
        }
        SPI_CSPIN_HIGH();
    }

    return enRet;
}


/****************************************************
 * @brief   读FLASH ID          //一般用来测试    
 * @param   [in] None
 * @retval  uint8_t             Flash ID
 ***************************************************/
static uint8_t SpiFlash_ReadID(void)
{
    uint32_t u8IdRead;
	uint8_t ID[15];
	
    SPI_CSPIN_LOW();
    (void)spi3_read_write_byte(READ_ID_cmd);
   (void)spi3_read_write_byte((uint8_t)0x00U);
   (void)spi3_read_write_byte((uint8_t)0x00U);
   (void)spi3_read_write_byte((uint8_t)0x00U);
    u8IdRead = spi3_read_write_byte((uint8_t)0xffU);
    SPI_CSPIN_HIGH();
    return u8IdRead;
}

/***************************************************************
 * @brief SPI flash erase 4Kb sector function
         //擦除4KB扇区
 * @param [in] u32Addr            FLASH地址
 * @retval Error                  擦除失败
 * @retval Ok                     擦除成功
 ***************************************************************/
static en_result_t SpiFlash_Erase4KbSector(uint32_t u32Addr)
{
    en_result_t enRet;

    if (u32Addr >= FLASH_MAX_ADDR)
    {
        enRet =  Error;
    }
    else
    {
        SpiFlash_WriteEnable();
        /*向flash发送指令 */
        SPI_CSPIN_LOW();
        (void)spi3_read_write_byte(ERASE_4KB_cmd);
        (void)spi3_read_write_byte((uint8_t)((u32Addr & 0xFF0000UL) >> 16U));
        (void)spi3_read_write_byte((uint8_t)((u32Addr & 0xFF00U) >> 8U));
        (void)spi3_read_write_byte((uint8_t)(u32Addr & 0xFFU));
        //SPI_GetStatus(const M4_SPI_TypeDef *SPIx, uint32_t u32Flag) //todo
        SPI_CSPIN_HIGH();
        /* Wait for flash idle */
        enRet = SpiFlash_WaitForWriteEnd();
    }

    return enRet;
}


/**********************************************************
 * FLASH测试函数:
			写入一串字符,然后读出来比较
 ************************************************************/
uint32_t SPI_FLASH_test_fuc(void)
{
	
	SPI_HOLD_PIN_HIGH();     //HOLD

    uint32_t flashAddr = 0x00;
    uint16_t bufferLen;
    char txBuffer[] = "SPI read and write flash test fuction";
    uint8_t rxBuffer[128];

    /* Get tx buffer length */
    bufferLen = (uint16_t)sizeof(txBuffer);
	
    DDL_DelayMS(10);
   
        (void)memset(rxBuffer, 0L, sizeof(rxBuffer));
        /* Erase sector */
        (void)SpiFlash_Erase4KbSector(flashAddr);
        /* Write data to flash */
        (void)SpiFlash_WritePage(flashAddr, (uint8_t*)&txBuffer[0], bufferLen);
        /* Read data from flash */
		    DDL_DelayMS(10);
			
        (void)SpiFlash_ReadData(flashAddr, (uint8_t*)&rxBuffer[0], bufferLen);

        /* Compare txBuffer and rxBuffer */
        if (memcmp(txBuffer, rxBuffer, (uint32_t)bufferLen) != 0)
        {
            return 0;   //结果不一样进这里,说明读取失败
        }
        else
        {
            return 5;   //结果一致进这里,说明读写成功
        }		 
}


void mt25ql_init(p_mt25ql_dev_t pdev,read_write_t fun)
{
	p_mt25ql_dev = pdev;
	p_mt25ql_dev->spi_read_write = fun;       //SPI接口
	mt25ql_gpio_init();			    				      //片选初始化
	DDL_DelayMS(50);												      //上电延迟50ms
}

/**********************************************
功能描述:从flash读一串字符串
参数输入:读取数据起始地址,数据长度
返    回:0
***********************************************/
int spi_read(uint8_t *adder,size_t size)
{
	uint16_t i;
	char a;

	for(i=0;i<size;i++ )
	{
		a = spi3_read_write_byte(0xff);
    *(adder+i) = a;
	}
	
	return 0;
}
/**********************************************
功能描述:往flash写一串字符串
参数输入:写入地址,数据长度
返    回:0
***********************************************/
int spi_write(uint8_t *adder,size_t size)
{
	uint16_t i;
	char a;

	for(i=0;i<size;i++ )
	{
		 a= *(adder+i);
     spi3_read_write_byte(*(adder+i));
	}
	
	return 0;
}

第一次上传文章,望大家支持!!

有问题可以在评论区留言,后期不定期更新

猜你喜欢

转载自blog.csdn.net/weixin_47041339/article/details/125676707
今日推荐