跟大家分享一个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]