jianhong_wu 发表于 2016-5-7 21:10:41

跟大家分享一个EPCS16的C语言驱动程序.其它EPCS4,EPCS64,EPCS128都大同小异.

★坚鸿-深圳:
今天为了实现FPGA的在线升级程序,刚刚终于搞出来了。要实现这个功能,我采用的方案就要编写SPI通讯的EPCS16芯片的驱动程序,这个芯片是一个FLASH芯片,专门用来装FPGA程序。FPGA每次上电时就自动从这个外围的FLASH芯片中快速读取并加载程序到FPGA内部。现在我决定把这个EPCS16的C语言驱动程序分享给大家。其它EPCS4,EPCS64,EPCS128都大同小异。

Epcs16.h头文件:
#ifndef _EPCS16_
#define _EPCS16_


#define EPCS16_SPI_CS_ON()       GPIO_SetBits(GPIOF , GPIO_Pin_0)
#define EPCS16_SPI_CS_OFF()      GPIO_ResetBits(GPIOF , GPIO_Pin_0)

#define EPCS16_SPI_SCK_ON()      GPIO_SetBits(GPIOF , GPIO_Pin_1)
#define EPCS16_SPI_SCK_OFF()   GPIO_ResetBits(GPIOF , GPIO_Pin_1)

#define EPCS16_SPI_SI_ON()       GPIO_SetBits(GPIOF , GPIO_Pin_2)
#define EPCS16_SPI_SI_OFF()      GPIO_ResetBits(GPIOF , GPIO_Pin_2)

#define EPCS16_SPI_READ_SO()   GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_3)

void Epcs16Initial(void);
void Epcs16SendByte(u8 u8SendData);
u8   Epcs16GetByte(void);
void Epcs16WriteDisable(void);
void Epcs16WriteEnable(void);
void Epcs16CheckBusy(u16 u16TimeOut);   //注意,这里用到定时中断的延时,每1ms定时中断一次的累计时间。
void Epcs16WriteStatus(u8 u8Epcs16Data);
void Epcs16WriteByte(u32 u32Epcs16Addr,u8 u8Epcs16Data);
u8   Epcs16ReadByte(u32 u32Epcs16Addr);
void Epcs16EraseSector(u32 u32Epcs16Addr);
void Epcs16EraseBulk(void);






#endif




Epcs16.c源文件:
#include "stm32f4xx.h"
#include"Epcs16.h"
#include "delay.h"



void Epcs16Initial(void)
{
        GPIO_InitTypeDefGPIO_InitStructure;
          RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOF, ENABLE);                                                
       
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
          GPIO_Init(GPIOF, &GPIO_InitStructure);
       
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
          GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_UP;
          GPIO_Init(GPIOF, &GPIO_InitStructure);       
       

       
    EPCS16_SPI_CS_ON();

}


void Epcs16SendByte(u8 u8SendData)
{
        u8 i=0;

        for(i=0;i<8;i++)              //8位数据串行输出
        {

    EPCS16_SPI_SCK_OFF();
                if(u8SendData&0x80)
                {
      EPCS16_SPI_SI_ON();
                }
                else
                {
      EPCS16_SPI_SI_OFF();
                }
    u8Delay(1);
                u8SendData=u8SendData<<1;       
    EPCS16_SPI_SCK_ON();
    u8Delay(1);
        }
}

u8 Epcs16GetByte(void)
{
        u8 u8GetData;
        u8 i;
       
        for(i=0;i<8;i++)
        {

    EPCS16_SPI_SCK_OFF();
    u8Delay(1);
                u8GetData=u8GetData<<1;
    EPCS16_SPI_SCK_ON();
    u8Delay(1);
                if(0!=EPCS16_SPI_READ_SO())               //如果存储器输出高电平
                {
                   u8GetData=u8GetData|0x01;
                }

        }
        return u8GetData;                       
}


void Epcs16WriteDisable(void)
{
                EPCS16_SPI_CS_OFF();
                Epcs16SendByte(0x04);               // 设置禁止写使能锁存
                EPCS16_SPI_CS_ON();

}

void Epcs16WriteEnable(void)
{
                EPCS16_SPI_CS_OFF();
                Epcs16SendByte(0x06);               // 设置写使能锁存
                EPCS16_SPI_CS_ON();
}

void Epcs16CheckBusy(u16 u16TimeOut) //注意,这里用到定时中断的延时,每1ms定时中断一次的累计时间。
{

        u8 u8ReadStatusData;
       
        Gu8DelayTimerFlag=0;//注意,这里用到定时中断的延时,每1ms定时中断一次的累计时间。
Gu16DelayTimerCnt=u16TimeOut; //注意,这里用到定时中断的延时,每1ms定时中断一次的累计时间。
        Gu8DelayTimerFlag=1; //注意,这里用到定时中断的延时,每1ms定时中断一次的累计时间。
       
        while(1)
        {
                if(0==Gu16DelayTimerCnt)//注意,这里用到定时中断的延时,每1ms定时中断一次的累计时间。
                {
                   break;
                }
               
                EPCS16_SPI_CS_OFF();
                Epcs16SendByte(0x05);    //获取存储器的状态
                u8ReadStatusData=Epcs16GetByte();
          EPCS16_SPI_CS_ON();

               
                if(0==(u8ReadStatusData&0x01))       //如果读出的最低位为1则表示存储器还在存储,此时单片机等待,知道存储完毕
                {
                        break;
                }

        }
       
        EPCS16_SPI_CS_ON();
}

void Epcs16WriteStatus(u8 u8Epcs16Data)
{

       
Epcs16WriteEnable();
       
        EPCS16_SPI_CS_OFF();
        Epcs16SendByte(0x01);               // 设置写状态指令
        Epcs16SendByte(u8Epcs16Data);               // 设置写状态数据
        EPCS16_SPI_CS_ON();
Epcs16CheckBusy(15);

}



void Epcs16WriteByte(u32 u32Epcs16Addr,u8 u8Epcs16Data)
{

        u8 u8Addr=0;
       
Epcs16WriteEnable();
       
        EPCS16_SPI_CS_OFF();
        Epcs16SendByte(0x02);                //发送写数据指令

        u8Addr=u32Epcs16Addr>>16;
        Epcs16SendByte(u8Addr);                        //写入存储数据的地址
        u8Addr=u32Epcs16Addr>>8;
        Epcs16SendByte(u8Addr);                        //写入存储数据的地址
        u8Addr=u32Epcs16Addr;
        Epcs16SendByte(u8Addr);                        //写入存储数据的地址
       
        Epcs16SendByte(u8Epcs16Data);                        //写入待存储的数据
       
        EPCS16_SPI_CS_ON();
Epcs16CheckBusy(5);
}


u8 Epcs16ReadByte(u32 u32Epcs16Addr)
{
        u8 u8ReadData=0;
        u8 u8Addr;
       
        EPCS16_SPI_CS_OFF();
        Epcs16SendByte(0x03);                //首先向存储器发送读数据指令

        u8Addr=u32Epcs16Addr>>16;
        Epcs16SendByte(u8Addr);                        //写入存储数据的地址
        u8Addr=u32Epcs16Addr>>8;
        Epcs16SendByte(u8Addr);                        //写入存储数据的地址
        u8Addr=u32Epcs16Addr;
        Epcs16SendByte(u8Addr);                        //写入存储数据的地址
       
        u8ReadData=Epcs16GetByte();                   //读出数据
       
        EPCS16_SPI_CS_ON();

        return u8ReadData;
}

void Epcs16EraseSector(u32 u32Epcs16Addr)
{

        u8 u8Addr;

Epcs16WriteStatus(0x02);
       
Epcs16WriteEnable();
       
        EPCS16_SPI_CS_OFF();

       
        Epcs16SendByte(0xD8);                //首先向存储器发送擦除扇区指令

        u8Addr=u32Epcs16Addr>>16;
        Epcs16SendByte(u8Addr);                        //写入存储数据的地址
        u8Addr=u32Epcs16Addr>>8;
        Epcs16SendByte(u8Addr);                        //写入存储数据的地址
        u8Addr=u32Epcs16Addr;
        Epcs16SendByte(u8Addr);                        //写入存储数据的地址
       
        EPCS16_SPI_CS_ON();
Epcs16CheckBusy(3000);
       

}


void Epcs16EraseBulk(void)
{

Epcs16WriteStatus(0x02);

Epcs16WriteEnable();
       
        EPCS16_SPI_CS_OFF();

       
        Epcs16SendByte(0xC7);                //首先向存储器发送擦除整片指令


        EPCS16_SPI_CS_ON();
Epcs16CheckBusy(40000);
       

}







页: [1]
查看完整版本: 跟大家分享一个EPCS16的C语言驱动程序.其它EPCS4,EPCS64,EPCS128都大同小异.