SPI_FLASH高速读写

来源:互联网 发布:在哪看淘宝自动售货 编辑:程序博客网 时间:2024/04/30 13:02
#include  "KH25L6406.h"

#define    SPI_WAIT()     while(FLASH_SPI->SR & BSY)

/*********************************************************************************************************
** Function name:       Send_Byte
** Descriptions:        通过硬件SPI发送一个字节到串行Flash器件
** input parameters:    data:  发送的数据
** output parameters:   NONE
** Returned value:      NONE
*********************************************************************************************************/
static void Send_Byte(unsigned char ucdata)
{
//   SSIDataPut(SSI0_BASE, ucdata);
    SPI_WAIT();
    FLASH_SPI->DR = ucdata;
}
/*********************************************************************************************************
** Function name:       Get_Byte
** Descriptions:        通过硬件SPI接口接收一个字节到处理器
** input parameters:    NONE
** output parameters:   NONE
** Returned value:      ReadData  读回的数据
*********************************************************************************************************/
static unsigned char Get_Byte(void)
{
   uint16_t ulReadData;

//   SSIDataPut(SSI0_BASE, 0xFF);                         //  发送一个无效字节,以产生接收时钟
//   SSIDataGet(SSI0_BASE, &ulReadData);
    SPI_WAIT();
    FLASH_SPI->DR = 0xFF;
    SPI_WAIT();
    while (FLASH_SPI->SR & RNE)
    ulReadData = FLASH_SPI->DR;
    return ((unsigned char)ulReadData);
}
/*********************************************************************************************************
** Function name:       SPIFIFOClear
** Descriptions:        SPI 清空FIFO
** input parameters:    NONE
** Returned value:      NONE
*********************************************************************************************************/
static void SPIFIFOClear(void)
{
    uint16_t ulRecBuf = 0;
    SPI_WAIT();
    while (FLASH_SPI->SR & RNE)
    {
      ulRecBuf = FLASH_SPI->DR;
    }                                                   /* 清空FIFO                     */    
}

/*********************************************************************************************************
** Function name:       FLASH_GPIO_Init
** Descriptions:        GPIO口初始化
** input parameters:    NONE
** output parameters:   NONE
** Returned value:      NONE
*********************************************************************************************************/
static void FLASH_KH25L6406E_GPIO_Init(void)
{
    SPI_CS_FLASH_GPIO ->FIODIR |= _BV(SPI_CS_FLASH_PIN);
}

/*********************************************************************************************************
** Function name:       serialFlashInit
** Descriptions:        初始化控制串行Flash的SSI管脚
** input parameters:    tAnyDevice:  串行Flash特性描述的结构体指针
** output parameters:   NONE
** Returned value:      NONE
*********************************************************************************************************/
void  serialFlashInit ( void)
{
    FLASH_KH25L6406E_GPIO_Init();
    CE_Low();
    SPIFIFOClear();
    CE_High();
}

/*********************************************************************************************************
** Function name:       serialFlash_RdID
** Descriptions:        读取串行Flash完整的ID
** input parameters:    tAnyDevice: 串行Flash特性描述的结构体指针
**                      ulReadID:   存储ID变量的指针
** output parameters:   NONE
** Returned value:      操作成功则返回FLASH_OK,失败则返回FLASH_ERROR
** 注   意:             若填入的参数不符合要求,则返回FLASH_ERROR
*********************************************************************************************************/
static uint32 serialFlash_RdID ( void)
{
    uint32 ultemp = 0;

    CE_Low();
    Send_Byte(  ucReadJEDEC_ID);
    SPIFIFOClear();
    ultemp = (ultemp | Get_Byte()) << 8;                        // 接收数据
    ultemp = (ultemp | Get_Byte()) << 8;
    ultemp = (ultemp | Get_Byte());
    SPI_WAIT();
    CE_High();
    return ultemp;
}

/*********************************************************************************************************
** Function name:       serialFlash_SelfTest
** Descriptions:        串行Flash自检程序
** input parameters:    NONE
** output parameters:   FLASH_OK    : SPI_FLASH正常
**                      FLASH_ERROR : SPI_FLASH器件错误
** Returned value:      操作成功则返回FLASH_OK,失败则返回FLASH_ERROR
** 注   意:             若填入的参数不符合要求,则返回FLASH_ERROR
*********************************************************************************************************/
uint8 serialFlash_SelfTest( void)
{
    if(serialFlash_RdID() == ulID)
    {
        return FLASH_OK;
    }
    
    return FLASH_ERROR;    
}

/*********************************************************************************************************
** Function name:       serialFlash_RD
** Descriptions:        从串行Flash的指定起始地址读取指定字节的数据
** input parameters:    tAnyDevice: 串行Flash特性描述的结构体指针
**                      ulDstAddr:  指定读取数据的起始地址,范围要根据具体的器件而定
**                      pucRcvBuf: 读取数据存放的缓冲区指针
**                      ulNByte: 指定读取数据的大小,以字节为单位。为0,表示不读出任何数据。
** output parameters:   NONE
** Returned value:      实际取出的字节数。一般情况下,应该等于ulNByte。如果小于ulNByte,则表示读取数据
**                      已经达到最大地址处。
*********************************************************************************************************/
unsigned long serialFlash_RD ( unsigned long ulDstAddr,
                             unsigned char* pucRcvBuf, unsigned long ulNByte)
{
    unsigned long i = 0;
    if((ulNByte == 0) || (ulDstAddr > (  ulMaxAddr)))
        return (0);                                                     //  检查入口参数
    
    if ((ulDstAddr + ulNByte - 1) > (  ulMaxAddr))
        ulNByte = (  ulMaxAddr) - ulDstAddr + 1;


     CE_Low();
     Send_Byte(  ucRead);                     // 发送读命令
     Send_Byte(((ulDstAddr & 0xFFFFFF) >> 16));                         // 发送地址信息:该地址由3个字节组成
     Send_Byte(((ulDstAddr & 0xFFFF) >> 8));
     Send_Byte(ulDstAddr & 0xFF);
     if(  ucIsReadWait != 0)
        Send_Byte(0xFF);
     SPIFIFOClear();
     for (i = 0; i < ulNByte; i++)
     {
         pucRcvBuf[i] = Get_Byte();
     }
     SPI_WAIT();
     CE_High();


    return (ulNByte);
}

/*********************************************************************************************************
** Function name:       serialFlash_WR
** Descriptions:        向串行Flash指定地址写入指定字节的数据
** input parameters:    tAnyDevice: 串行Flash特性描述的结构体
**                      ulDstAddr:  指定读取数据的起始地址,范围要根据具体的器件而定
**                      pucSndBuf:  发送缓冲区的指针
**                      ulNByte:    发送数据的大小,以字节为单位。为0,表示不编程任何数据。
** output parameters:   NONE
** Returned value:      实际取出的字节数。一般情况下,应该等于ulNByte。如果小于ulNByte,则表示读取数据
**                      已经达到最大地址处。
*********************************************************************************************************/
unsigned char serialFlash_PageProgram ( unsigned long ulDstAddr,
                               unsigned char* pucSndBuf,uint16 ulNByte)
{
    unsigned char ucTemp = 0, ucStatus = 0;
    uint16 i;
    uint8 ulReturn = 0;
    
//    if((ulNByte == 0) || (ulDstAddr > ulMaxAddr) || (ulNByte > 0x100))
//    {
//        return 0;
//    }
//    ulNByte = (ulDstAddr/0x100 + ulNByte)/0x100;
//    if((ulDstAddr/0x100 + ulNByte) > 0x100)
//    {
//        ulNByte = 0x100 - ulDstAddr/0x100 + 1;
//        ulReturn = ulNByte;
//    }
    
    do {
        CE_Low();
        Send_Byte( ucReadStatus);  // 发送读状态寄存器命令
        SPIFIFOClear();
        ucTemp = Get_Byte();        // 保存读得的状态寄存器值
        SPI_WAIT();
        CE_High();
    }while(ucTemp & 0x01);
         
    do {    
        CE_Low();
        Send_Byte( ucEnWrite);       // 发送写使能命令
        SPI_WAIT();
        CE_High();
        
        CE_Low();
        Send_Byte( ucReadStatus);  // 发送读状态寄存器命令
        SPIFIFOClear();
        ucTemp = Get_Byte();        // 保存读得的状态寄存器值
        SPI_WAIT();
        CE_High();
    } while(!(ucTemp & 0x02));
    
    CE_Low();
    Send_Byte(ucWrite);     // 发送字节数据烧写命令
    Send_Byte(((ulDstAddr & 0xFFFFFF) >> 16));    // 发送3个字节的地址信息
    Send_Byte(((ulDstAddr & 0xFFFF) >> 8));
    Send_Byte(ulDstAddr & 0xFF);
    for (i = 0; i <= ulNByte; i ++)
    {
        Send_Byte(*pucSndBuf++);                    // 发送被烧写的数据
    }
    CE_High();
    DelayUS(100);
    do {
        CE_Low();
        Send_Byte( ucReadStatus);  // 发送读状态寄存器命令
        SPIFIFOClear();
        ucTemp = Get_Byte();        // 保存读得的状态寄存器值
        SPI_WAIT();
        CE_High();
    }while(ucTemp & 0x01);
        
 
    CE_Low();
    Send_Byte( ucDisWrite);       // 发送写使能命令
    SPI_WAIT();
    CE_High();

    return ulReturn;
}

/*********************************************************************************************************
** Function name:           serialFlash_SecErase
** Descriptions:            对串行Flash的指定的扇区进行擦除操作
** input parameters:        tAnyDevice: 串行Flash特性描述的结构体
**                          ulSecNo: 指定需要擦除的扇区,0代表第0扇区
** output parameters:       NONE
** Returned value:          操作成功则返回FLASH_OK,失败则返回FLASH_ERROR
*********************************************************************************************************/
unsigned char serialFlash_SecErase( unsigned long ulSecNo)
{
    unsigned char ucTemp= 0, ucStatus = 0;
    unsigned long ulAddr = 0;
    
    if(ulSecNo > (  ulSecMax))
        return (FLASH_ERROR);
    ulAddr = (  ulSecSize) * ulSecNo;// 计算扇区的起始地址

    do {
        CE_Low();
        Send_Byte( ucReadStatus);  // 发送读状态寄存器命令
        SPIFIFOClear();
        ucTemp = Get_Byte();        // 保存读得的状态寄存器值
        SPI_WAIT();
        CE_High();
    }while(ucTemp & 0x01);
         
    do {    
        CE_Low();
        Send_Byte( ucEnWrite);       // 发送写使能命令
        SPI_WAIT();
        CE_High();
        
        CE_Low();
        Send_Byte( ucReadStatus);  // 发送读状态寄存器命令
        SPIFIFOClear();
        ucTemp = Get_Byte();        // 保存读得的状态寄存器值
        SPI_WAIT();
        CE_High();
    } while(!(ucTemp & 0x02));
    
    CE_Low();
    Send_Byte(  ucSecErase);      // 发送扇区擦除指令
    Send_Byte(((ulAddr & 0xFFFFFF) >> 16));                 // 发送3个字节的地址信息
    Send_Byte(((ulAddr & 0xFFFF) >> 8));
    Send_Byte(ulAddr & 0xFF);
    SPI_WAIT();
    CE_High();
    
    do {
        CE_Low();
        Send_Byte( ucReadStatus);  // 发送读状态寄存器命令
        SPIFIFOClear();
        ucTemp = Get_Byte();        // 保存读得的状态寄存器值
        SPI_WAIT();
        CE_High();
    }while(ucTemp & 0x01);
        
 
    CE_Low();
    Send_Byte( ucDisWrite);       // 发送写使能命令
    SPI_WAIT();
    CE_High();
    
    return (FLASH_OK);
}

/********************************************************************************************************
      END FILE
********************************************************************************************************/

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 镍氢电池没电了怎么办 地下室对讲机信号不好怎么办 cf不能说话了怎么办 cf没办法说话怎么办 cf对讲机没声音怎么办 交警用的对讲机怎么办 cf语音没有声音怎么办 去上海没有流量怎么办 去外地没流量怎么办 外地流量不够用怎么办 手机在外地流量怎么办 联通网卡在外地怎么办 套餐流量不够用怎么办 省内流量去省外怎么办 在外省流量不够怎么办 榨汁机开关坏了怎么办 健伍dvd没遥控器怎么办 佳能 显示屏关不了怎么办 iqos充电闪红灯怎么办 航班取消了乘客怎么办 摩托罗拉电话静音了怎么办 对讲机话筒坏了怎么办 摩托罗拉xt1570费电怎么办 主板没有rgb接口怎么办 对讲机频段没了怎么办 怀孕查出宫颈囊怎么办 办养殖场没地怎么办 宝宝睡觉衣服湿透怎么办 开衫衣服往下滑怎么办 迷你世界没有牛怎么办 火龙果树烂了怎么办 误喝鸵鸟墨水怎么办 被鸵鸟啄伤怎么办 被鸵鸟啄住怎么办 鸟翅膀受伤了怎么办 北京卖房户口怎么办 深户挂人才市场集体户小孩怎么办? 郑州房子限购怎么办 外地怎么送东西怎么办 晚上登华山下雨怎么办 北京摇不到号想买车怎么办