標(biāo)題:
GPIO模擬驅(qū)動(dòng)W25Q16 FLASH源程序
[打印本頁]
作者:
liupdeng
時(shí)間:
2019-8-21 15:24
標(biāo)題:
GPIO模擬驅(qū)動(dòng)W25Q16 FLASH源程序
GPIO模擬驅(qū)動(dòng)W25Q16 FLASH
程序代碼應(yīng)用到產(chǎn)品,非常穩(wěn)定
源程序如下:
#include "_cpus.h"
#include "_coms.h"
/*=====================================================================================================================*/
//SPI模式:CPOL=1 CPHA=1 CS Active low
//clock is high when inactive
//Data is valid on clock trailing edge
//不活動(dòng)時(shí),時(shí)鐘為高 也就是數(shù)據(jù)可改變區(qū)
//數(shù)據(jù)在時(shí)鐘后沿有效 數(shù)據(jù)作用點(diǎn)
#define ENTER_CRITICAL()
#define EXIT_CRITICAL()
#define MOSI PC6
#define SPSCK PC7
#define ADD_EN_WP PC8
#define MISO PC9
#define SS PC10
#define SS_OUT_L b_hGpioOut(SS,0)
#define SS_OUT_H b_hGpioOut(SS,1)
#define WP_OUT_L b_hGpioOut(ADD_EN_WP,0)
#define WP_OUT_H b_hGpioOut(ADD_EN_WP,1)
#define SPI_CLK b_hGpioOut(SPSCK,0);b_dNOP();b_dNOP();b_dNOP();b_dNOP();b_dNOP();b_hGpioOut(SPSCK,1);//和EE相位相反
#define Flash_CS_0 b_hGpioOut(SPSCK,1); ENTER_CRITICAL();WP_OUT_H;SS_OUT_L;
#define Flash_CS_1 WP_OUT_L;SS_OUT_H;EXIT_CRITICAL(); b_hGpioOut(SPSCK,0);
void b_hExFlashSetChip2NomlPower(void);
extern void b_hExFlashInit(void)
{
b_hGpioInit(SS,eOUT_PUSH_PULL,1);
b_hGpioInit(SPSCK,eOUT_PUSH_PULL,0);
b_hGpioInit(MOSI,eOUT_PUSH_PULL,0);
b_hGpioInit(MISO,eOUT_PUSH_PULL,0);
b_hGpioInit(ADD_EN_WP,eOUT_PUSH_PULL,0);
b_hExFlashSetChip2NomlPower();
}
/*****************************************************************
** function name : SPISendByte
** description : SPI1 send one byte
** input parameter: byte to be sent
** return : byte received
******************************************************************/
static uint08_t ExFlash_hSendByte(uint08_t b)
{
//時(shí)鐘低到高輸出,高到低輸入
//將b寫到ee中,返回?cái)?shù)據(jù)寫到f中
uint8_t i,f;
f=0;
// b_hGpioOut(SS,0);
//SPI_SDI_DDR = IOisIN;
b_hGpioInit(MISO,eIN_PULL_UP,0);
//h_bGpioInit(SPSCK,eOUT_PUSH_PULL,0);
//h_bGpioInit(MOSI,eOUT_PUSH_PULL,0);
//SPI_SDI_UP=1; SPI_SCK_UP=1; SPI_SDO_UP=1;
for(i=8;i;i--)
{
//TicksDelayMs(1);
if(b&bit7){
// SPI_SDO_ODR=1; /*向ee寫1輸出1p4.3*/
b_hGpioOut(MOSI,1);
}else{
//SPI_SDO_ODR=0; /*向ee寫0*/
b_hGpioOut(MOSI,0);
}
SPI_CLK;
// b_hGpioOut(SPSCK,0); //低到高跳變時(shí)鐘
// TicksDelayMs(1);
// b_hGpioOut(SPSCK,1);
// TicksDelayMs(1);
b<<=1;
f<<=1;
if(b_hGpioRead(MISO))f|=bit0; /*接收數(shù)據(jù)*/
}
// SPI_SDO_UP=0; SPI_SCK_UP=0;SPI_SDI_DDR = IOisOUT;SPI_SDI_ODR= IOisLOW;SPI_SDI_UP=0;
b_hGpioInit(MISO,eOUT_PUSH_PULL,0);
//b_hGpioOut(SS,1);
return f;
}
/*****************************************************************
** function name : SPIReceiveByte
** description : SPI1 receive byte
** input parameter: none
** return : byte received
******************************************************************/
static uint08_t ExFlash_hReceiveByte(void)
{
uint8_t i,f, b=0xff;;
f=0;
// b_hGpioOut(SS,0);
// SPI_SDI_DDR = IOisIN; SPI_SDI_UP=1; SPI_SCK_UP=1; SPI_SDO_UP=1;
b_hGpioInit(MISO,eIN_PULL_UP,0);
for(i=8;i;i--)
{
if(b&bit7)
b_hGpioOut(MOSI,1);
else
b_hGpioOut(MOSI,0);
SPI_CLK;
// b_hGpioOut(SPSCK,0);
// TicksDelayMs(1);
// b_hGpioOut(SPSCK,1);
// TicksDelayMs(1);
b<<=1;
f<<=1;
if(b_hGpioRead(MISO))f|=bit0;
}
b_hGpioInit(MISO,eOUT_PUSH_PULL,0);
// b_hGpioOut(SS,1);
return f;
}
/******************************************
** 函 數(shù) 名:WriteEnable
** 功能描述:寫使能
** 參 數(shù):無
** 返 回:無
*******************************************/
static void ExFlash_hWriteEnable(void)
{
Flash_CS_0;
ExFlash_hSendByte(0x06);//寫使能
Flash_CS_1;
}
static void ExFlash_hWriteDisable( void )
{
Flash_CS_0;
ExFlash_hSendByte(0x04);//寫禁能
Flash_CS_1;
}
/******************************************************************************/
/* 函數(shù)名稱:uint8 check_flash_busy(void) */
/* 功能描述:檢查flash是否忙 */
/* 參數(shù)說明:無 */
/* 參數(shù)返回: 如果忙返回1,不忙返回0 */
/******************************************************************************/
extern uint08_t b_hExFlashCheckBusy(void)
{
uint08_t busy_flag;
Flash_CS_0;
ExFlash_hSendByte(0x05);
busy_flag=ExFlash_hReceiveByte();
Flash_CS_1;
if(busy_flag & 0x03)
busy_flag = 1;
else
busy_flag = 0;
return busy_flag;
}
extern uint16_t ExFlash_hReadStateReg1_2( void )
{
uint16_t temp_state;
Flash_CS_0;
temp_state=ExFlash_hSendByte(0x05);
temp_state=temp_state<<8;
temp_state=temp_state+ExFlash_hSendByte(0x35);
Flash_CS_1;
return temp_state;
}
extern void ExFlash_hWriteStateReg1_2( uint08_t highS,uint08_t lowS)
{
ExFlash_hWriteEnable();
Flash_CS_0;
ExFlash_hSendByte(0x01);//send write state regster cmd
ExFlash_hSendByte(lowS);
ExFlash_hSendByte(highS);
Flash_CS_1;
ExFlash_hWriteDisable();
}
/******************************************************************************
** 函 數(shù) 名:ExFlash_hPageProgram
** 功能描述: 向指定的地址寫入指定數(shù)量的字節(jié)
** 參 數(shù):數(shù)據(jù)緩沖區(qū),字節(jié)數(shù),FLASH起始地址
** 返 回:無
******************************************************************************/
extern void ExFlash_hFlashProgram(uint08_t *databuffer,uint32_t address,uint32_t datasize)
{
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0x02);
ExFlash_hSendByte((uint08_t)(address>>16));
ExFlash_hSendByte((uint08_t)(address>>8));
ExFlash_hSendByte((uint08_t)address);
while(datasize>0)
{
ExFlash_hSendByte(*databuffer);
databuffer++;
datasize--;
}
Flash_CS_1; //置cs高不選中
while(b_hExFlashCheckBusy()); //等待器件寫完結(jié)束
}
/********************************************
**函 數(shù) 名:ReadUniqueID
**功能描述:讀取芯片唯一ID號(hào),總共8字節(jié)
**參 數(shù):數(shù)據(jù)緩沖區(qū)
*********************************************/
extern void ExFlash_hReadUniqueID(uint08_t *databuffer)
{
uint08_t i;
// EnterNoInt();
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0x4B);
ExFlash_hSendByte(0xff); //這里發(fā)送的三個(gè)字節(jié)是任意的,不一定是0xff
ExFlash_hSendByte(0xff);
ExFlash_hSendByte(0xff);
ExFlash_hSendByte(0xff);
for(i=0;i<8;i++)
{
*databuffer=ExFlash_hReceiveByte();
databuffer++;
}
Flash_CS_1;
// ExitNoInt();
}
/********************************************************
** 函 數(shù) 名:SectorErase
** 功能描述:扇區(qū)擦除
** 參 數(shù):扇區(qū)地址
** 返 回:無
*********************************************************/
void ExFlash_hSector4KErase(uint32_t sector4kN)
{
// b_dDI();
sector4kN*=4096;
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0x20);
ExFlash_hSendByte((uint08_t)(sector4kN>>16));
ExFlash_hSendByte((uint08_t)(sector4kN>>8));
ExFlash_hSendByte((uint08_t)sector4kN);
Flash_CS_1; //置cs高不選中
// while(b_hExFlashCheckBusy()); //等待器件寫完結(jié)束
// EI;
}
extern void b_hExFlashSector4KEraseAddr(uint32_t sectorAddr)
{
//b_dDI();
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0x20);
ExFlash_hSendByte((uint08_t)(sectorAddr>>16));
ExFlash_hSendByte((uint08_t)(sectorAddr>>8));
ExFlash_hSendByte((uint08_t)sectorAddr);
Flash_CS_1; //置cs高不選中
//while(b_hExFlashCheckBusy()); //等待器件寫完結(jié)束
// EI;
}
void ExFlash_hBlock32KErase(uint32_t sector32kN)
{
// b_dDI();
sector32kN*=131072;
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0x52);
ExFlash_hSendByte((uint08_t)(sector32kN>>16));
ExFlash_hSendByte((uint08_t)(sector32kN>>8));
ExFlash_hSendByte((uint08_t)sector32kN);
Flash_CS_1; //置cs高不選中
// while(b_hExFlashCheckBusy()); //等待器件寫完結(jié)束
// EI;
}
void ExFlash_hBlock64KErase(uint32_t address)
{
// b_dDI();
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0xD8);
ExFlash_hSendByte((uint08_t)(address>>16));
ExFlash_hSendByte((uint08_t)(address>>8));
ExFlash_hSendByte((uint08_t)address);
Flash_CS_1; //置cs高不選中
// while(b_hExFlashCheckBusy()); //等待器件寫完結(jié)束
// EI;
}
void ExFlash_hAllChipErase(void)
{
// b_dDI();
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0xC7);
Flash_CS_1; //置cs高不選中
// while(b_hExFlashCheckBusy()); //等待器件寫完結(jié)束
// EI;
}
extern void b_hExFlashSetChip2LowPower(void)
{
// b_dDI();
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0xB9);
Flash_CS_1; //置cs高不選中
// while(b_hExFlashCheckBusy()); //等待器件寫完結(jié)束
// EI;
}
extern void ExFlash_hSetChip2HighPower(void)
{
// b_dDI();
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0xA3);
Flash_CS_1; //置cs高不選中
// while(b_hExFlashCheckBusy()); //等待器件寫完結(jié)束
// EI;
}
void b_hExFlashSetChip2NomlPower(void)
{
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0xAB);
Flash_CS_1; //置cs高不選中
ExFlash_hWriteDisable();
// while(b_hExFlashCheckBusy());//FDW去掉的
// EI;
}
/*****************************************************************
** 函 數(shù) 名:ReadRFlash
** 功能描述:從指定的地址讀取指定數(shù)量的字節(jié)
** 參 數(shù):數(shù)據(jù)緩沖區(qū),字節(jié)數(shù),起始地址
** 返 回:無
******************************************************************/
extern void b_hExFlashRead(uint08_t *databuffer,uint32_t address,uint16_t datasize)
{
uint16_t i;
// b_dDI();
//while( b_hExFlashCheckBusy());
Flash_CS_0;
ExFlash_hSendByte(0x03);
ExFlash_hSendByte((uint08_t)(address>>16));
ExFlash_hSendByte((uint08_t)(address>>8));
ExFlash_hSendByte((uint08_t)address);
for(i=0;i<datasize;i++)
{
databuffer[i]=ExFlash_hReceiveByte();
}
Flash_CS_1; //置cs高不選中
// EI;
}
/**************************************************************************
** 函數(shù)名:CheckData
** 功能描述:檢驗(yàn)指定的Flash起始地址的數(shù)據(jù)和指定的緩沖區(qū)的數(shù)據(jù)是否全部相等
** 參數(shù):數(shù)據(jù)緩沖區(qū)DataBuffer, Flash起始地址DataAddr,數(shù)據(jù)字節(jié)數(shù)
** 返回:全部相同返回1,否則返回0
***************************************************************************/
extern uint8_t ExFlash_hCheckData(uint08_t *DataBuffer, uint32_t DataAddr, uint16_t DataSize)
{
uint08_t data;
uint16_t i;
for(i=0;i<DataSize;i++)
{
b_hExFlashRead(&data,1,DataAddr+i);
if(data!=DataBuffer[i])return 0;
}
return 1;
}
//extern void ExFlash_mWDataToSector(uint08_t *pDataBuffer,uint16_t dataSize, uint08_t sector)
//{
//
// uint08_t
// for(uint16_t i=0;i<dataSize;i++)//校驗(yàn)數(shù)據(jù)
// {
// if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除
// }
//}
//無檢驗(yàn)寫SPI FLASH
//必須確保所寫的地址范圍內(nèi)的數(shù)據(jù)全部為0XFF,否則在非0XFF處寫入的數(shù)據(jù)將失敗!
//具有自動(dòng)換頁功能
//在指定地址開始寫入指定長(zhǎng)度的數(shù)據(jù),但是要確保地址不越界!
//pBuffer:數(shù)據(jù)存儲(chǔ)區(qū)
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節(jié)數(shù)(最大65535)
//CHECK OK
extern void ExFlash_hWriteMustErase(uint08_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint16_t pageremain;
pageremain=256-WriteAddr%256; //單頁剩余的字節(jié)數(shù)
if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256個(gè)字節(jié)
while(1)
{
ExFlash_hFlashProgram(pBuffer,WriteAddr,pageremain);
if(NumByteToWrite==pageremain)break;//寫入結(jié)束了
else //NumByteToWrite>pageremain
{
pBuffer+=pageremain;
WriteAddr+=pageremain;
NumByteToWrite-=pageremain; //減去已經(jīng)寫入了的字節(jié)數(shù)
if(NumByteToWrite>256)pageremain=256; //一次可以寫入256個(gè)字節(jié)
else pageremain=NumByteToWrite; //不夠256個(gè)字節(jié)了
}
};
}
//寫SPI FLASH
//在指定地址開始寫入指定長(zhǎng)度的數(shù)據(jù)
//該函數(shù)帶擦除操作!
//pBuffer:數(shù)據(jù)存儲(chǔ)區(qū)
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節(jié)數(shù)(最大65535)
//屏敝注解掉此隨機(jī)寫SPI_FLASH函數(shù),
//原因:資源消耗大--需要?臻g要調(diào)設(shè)到 4096+0x200 測(cè)試時(shí)用的是 0x2200的棧空間
//void ExFlash_hWrite(uint08_t *pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
//{
// static uint32_t secpos;
// uint16_t secoff;
// uint16_t secremain;
// uint16_t i;
// uint08_t SPI_FLASH_BUF[4096];
//
//
// secpos=WriteAddr/4096;//起始地址所在扇區(qū)號(hào) 地址 0~511 for w25x16
// secoff=WriteAddr%4096;//起始地址所在扇區(qū)號(hào)的偏移 在扇區(qū)內(nèi)的偏移
// secremain=4096-secoff;//起始地址所在扇區(qū)剩余空間大小
//
//
// if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096個(gè)字節(jié) 裝的下
// while(1)
// {
// b_hExFlashRead(SPI_FLASH_BUF,secpos*4096,4096);//讀出整個(gè)扇區(qū)的內(nèi)容
// for(i=0;i<secremain;i++)//校驗(yàn)數(shù)據(jù)
// {
// if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除
// }
// if(i<secremain)//需要擦除
// {
// ExFlash_hSector4KErase(secpos);//擦除這個(gè)扇區(qū)
// for(i=0;i<secremain;i++) //復(fù)制
// {
// SPI_FLASH_BUF[i+secoff]=pBuffer[i];
// }
// ExFlash_hWriteMustErase(SPI_FLASH_BUF,secpos*4096,4096);//寫入整個(gè)扇區(qū)
//
// }else ExFlash_hWriteMustErase(pBuffer,WriteAddr,secremain);//寫已經(jīng)擦除了的,直接寫入扇區(qū)剩余區(qū)間.
//
// if(NumByteToWrite==secremain)break;//寫入結(jié)束了
// else//寫入未結(jié)束
// {
// secpos++;//扇區(qū)地址增1
// secoff=0;//偏移位置為0
//
// pBuffer+=secremain; //指針偏移
// WriteAddr+=secremain;//寫地址偏移
// NumByteToWrite-=secremain; //字節(jié)數(shù)遞減
// if(NumByteToWrite>4096)secremain=4096; //下一個(gè)扇區(qū)還是寫不完
// else secremain=NumByteToWrite; //下一個(gè)扇區(qū)可以寫完了
// }
// };
//}
extern void b_hExFlashWrite(uint08_t *databuffer,uint32_t address,uint32_t datasize)
{
ExFlash_hWriteEnable(); //寫使能
Flash_CS_0; //置cs低選中
ExFlash_hSendByte(0x02);
ExFlash_hSendByte((uint08_t)(address>>16));
ExFlash_hSendByte((uint08_t)(address>>8));
ExFlash_hSendByte((uint08_t)address);
while(datasize>0)
{
ExFlash_hSendByte(*databuffer);
databuffer++;
datasize--;
}
Flash_CS_1; //置cs高不選中
//等待器件寫完結(jié)束
}
復(fù)制代碼
作者:
liupdeng
時(shí)間:
2019-8-21 15:26
自已頂一下,有需要的拿走
作者:
Muker
時(shí)間:
2023-3-12 23:56
感謝分享,回頭試試
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1