日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

SpiFlash同步/异步读写单片机裸机实例

發(fā)布時間:2024/1/1 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpiFlash同步/异步读写单片机裸机实例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
單片機裸機開發(fā)中會經(jīng)常遇到外設速度過慢,長時間讀忙等待,但CPU又不能長時間阻塞的問題。
這種問題可以通過實現(xiàn)一個狀態(tài)機來異步處理。

異步狀態(tài)機代碼結(jié)構(gòu)示例:

enum {eIDLE = 0,eSTART,eWAIT,eSUCCESS };static uint8_t stage = 0; //啟動異步處理 void DoSomethingRequest() {if(stage != eIDLE){printf("AsyncMachine is busy!!!,return\n");return;}SomethingReq = TRUE; } //異步處理任務 void AsyncMachine() {switch(stage){case eIDLE:if(SomethingReq){stage = eSTART;printf("A task will be start\n");}break;case eSTART: do_something();stage = eWAIT;printf("do something\n");break;case eWAIT: if(something_state() == OK){stage = eSUCCESS;}printf("Wait...\n");break;case eSUCCESS: stage = eIDLE;printf("task exec success\n");break;} }

通過把阻塞的任務單獨分離出來,交給一個狀態(tài)機子任務來處理。則應用程序只需要調(diào)用一個處理請求而無需原地死等,狀態(tài)機處理完成后,可以異步回調(diào)來通知應用程序任務已完成。


下面附上SPI FLASH 同步/異步讀寫實例。

//SPI狀態(tài)機狀態(tài) typedef enum {eFLASH_STATE_IDLE = 0,eFLASH_STATE_WRITE = 1, eFLASH_STATE_READ = 2,eFLASH_STATE_BUSY = 3,eFLASH_STATE_ERASE_CHIP = 4,eFLASH_STATE_ERASE = 5, }FlashState_e; //SPI設備結(jié)構(gòu)體 typedef struct SpiDevice_s {SPI_TypeDef *spiHandle;//SPI物理屬性uint8_t *pTxBuffer;//異步發(fā)送緩存uint32_t uTxDstAddr;//異步發(fā)送目地地址uint16_t wTxLen;//異步發(fā)送長度uint16_t wTxOffset; //異步當前緩存已發(fā)送偏移 uint8_t *pRxBuffer;uint32_t uRxSrcAddr;uint16_t wRxLen;uint16_t wRxOffset; void (*pWriteAsyncNotifyCallback)(); //異步寫完成回調(diào)通知void (*pEraseChipAsyncNotifyCallback)();//異不擦除回調(diào)通知struct {FlashState_e eStage;//當前狀態(tài)機狀態(tài)//BOOL bTxBusy:1; //發(fā)送忙BOOL bTxReq:1; //發(fā)送請求BOOL bTxCompleted:1;//發(fā)送完成//BOOL bRxBusy:1; //讀忙BOOL bRxReq:1; //讀請求BOOL bEraseChipReq:1;//擦整片請求BOOL bEraseSectorReq:1;//擦扇區(qū)請求BOOL bEraseSuccess:1; //擦成功}tState;void (*Init)(void);uint8_t (*EraseChip)(void);//同步擦void (*Read)(uint8_t* pBuffer,uint32_t uReadAddr,uint16_t wNumByteToRead);//同步讀uint32_t (*WriteByte)(uint8_t Byte, uint32_t uWriteAddr);//同步寫字節(jié)uint32_t (*Write)(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite);//同步寫B(tài)OOL (*WriteAsync)(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite);//異步寫B(tài)OOL (*EraseChipAsync)(void);//異步整片擦BOOL (*EraseAsync)(uint32_t uAddr, uint16_t wlen);//奶步擦void (*WriteAsyncNotifyCallbackRegister)(void* pfn);//異步寫完成回調(diào)注冊void (*EraseChipAsyncNotifyCallbackRegister)(void *pfn);//異步擦完成回調(diào)注冊 }SpiDevice_t;實例化

SpiDevice_t g_tSpiDevice = {SPI2,g_aTxBuffer,0,0,0,g_aRxBuffer,0,0,0,0,0,{0,0},Spi_Init,SPI_Flash_Erase_Chip, //í?2?????2áSPI_Flash_Read, //í?2??áSPI_Flash_WriteByte, //í?2?D′×??úSPI_Flash_Write, //í?2?D′SPI_FlashWriteAsync, //òì2?D′SPI_FlashEraseChipAsync, //òì2?????2á3ySPI_FlashEraseAsync,SPI_WriteAsyncNotifyCallbackRegister,//D′×′ì?òì2?í¨?a??μ÷SPI_EraseChipAsyncNotifyCallbackRegister,//2á3y×′ì?òì2?í¨?a??μ÷ };


//SPI同步操作 /***************** 2á3yò???éè?? 0~511 ******************/ unsigned char SPI_Flash_Erase_Sector(unsigned int Dst_Addr) { unsigned char cnt=0; SPI_FLASH_Write_Enable(); //SET WEL while((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE;} SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(SECTOR_ERASE); SPI_Flash_ReadWrite_Byte((unsigned char)((Dst_Addr)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((Dst_Addr)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)Dst_Addr); SPI_CS_HIGH(); SPI_Flash_Wait_Busy(); return TRUE; } /*64K Flash????2á3y*/ unsigned char SPI_Flash_Erase_64k(unsigned int Dst_Addr) { unsigned char cnt=0;SPI_FLASH_Write_Enable(); //SET WEL while((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE;} SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(BLOCK_ERASE_64K); SPI_Flash_ReadWrite_Byte((unsigned char)((Dst_Addr)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((Dst_Addr)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)Dst_Addr); SPI_CS_HIGH(); SPI_Flash_Wait_Busy(); return TRUE; } /*2á3yD???*/ unsigned char SPI_Flash_Erase_Chip(void) { unsigned char cnt=0; SPI_FLASH_Write_Enable(); //SET WELwhile((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE;}SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(CHIP_ERASE); SPI_CS_HIGH(); SPI_Flash_Wait_Busy(); return TRUE; } /*???¨μ??·?áè????¨3¤?èêy?Y*/ void SPI_Flash_Read(unsigned char* pBuffer,unsigned int ReadAddr,unsigned short int NumByteToRead) {unsigned short int index; SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(READ_DATA); /*?3?μμ??·*/SPI_Flash_ReadWrite_Byte((unsigned char)((ReadAddr)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((ReadAddr)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)ReadAddr);for(index=0;index<NumByteToRead;index++){pBuffer[index]=SPI_Flash_ReadWrite_Byte(DUMMY); }SPI_CS_HIGH(); } uint32_t SPI_Flash_WriteByte(unsigned char Byte,unsigned int WriteAddr) {unsigned char cnt=0;SPI_FLASH_Write_Enable(); //SET WEL while((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE; /*·μ??D′ê§°ü*/} SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(PAGE_PRG); SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)WriteAddr);SPI_Flash_ReadWrite_Byte(Byte);SPI_CS_HIGH(); SPI_Flash_Wait_Busy();return TRUE;}uint32_t SPI_Flash_Write(unsigned char* pBuffer,unsigned int WriteAddr,unsigned short int NumByteToWrite) {unsigned short int pageoffset=PAGE_SIZE-(WriteAddr%PAGE_SIZE); /*??????ò3?D?1óD?àéùê£óà????*/unsigned char cnt=0;unsigned short int index;unsigned int pagenum =WriteAddr/PAGE_SIZE; /*±?′?D′è?μ?ò3êy*/unsigned int Addr;if(pageoffset >= NumByteToWrite) //ê£óà????′óóúòaD′μ?êyá?{SPI_FLASH_Write_Enable(); //SET WEL while((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE; /*·μ??D′ê§°ü*/} SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(PAGE_PRG); SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)WriteAddr); for(index=0; index<NumByteToWrite;index++){SPI_Flash_ReadWrite_Byte(*(pBuffer+index)); }SPI_CS_HIGH(); SPI_Flash_Wait_Busy(); return TRUE;}else{/*?è????ò3ì??ú*/SPI_FLASH_Write_Enable(); //SET WEL while((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE; /*·μ??D′ê§°ü*/} SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(PAGE_PRG); SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)WriteAddr); for(index=0; index<pageoffset;index++){SPI_Flash_ReadWrite_Byte(*(pBuffer+index)); }SPI_CS_HIGH(); SPI_Flash_Wait_Busy(); NumByteToWrite -=pageoffset; /*3¤?è??è¥D′è?êy?Y*/pagenum++;Addr = pagenum*PAGE_SIZE; //??è???ò?ò3μ??eê?μ??·while(NumByteToWrite >0){if(NumByteToWrite > PAGE_SIZE) //è?è?′óóúò?ò3{SPI_FLASH_Write_Enable(); //SET WEL while((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE; /*·μ??D′ê§°ü*/} SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(PAGE_PRG); SPI_Flash_ReadWrite_Byte((unsigned char)((Addr)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((Addr)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)Addr); for(index=0; index<PAGE_SIZE;index++){SPI_Flash_ReadWrite_Byte(*(pBuffer+index+pageoffset)); }SPI_CS_HIGH(); SPI_Flash_Wait_Busy();NumByteToWrite -=PAGE_SIZE;pageoffset +=PAGE_SIZE;pagenum++;Addr = pagenum*PAGE_SIZE; //??è???ò?ò3μ??eê?μ??·}else{SPI_FLASH_Write_Enable(); //SET WEL while((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE; /*·μ??D′ê§°ü*/} SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(PAGE_PRG); SPI_Flash_ReadWrite_Byte((unsigned char)((Addr)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((Addr)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)Addr); for(index=0; index<NumByteToWrite;index++){SPI_Flash_ReadWrite_Byte(*(pBuffer+index+pageoffset)); }SPI_CS_HIGH(); SPI_Flash_Wait_Busy();NumByteToWrite =0;}}return TRUE;} } /************************************************************************************************SPI異步操作*************************************************************************************************//***************************************************************************************** oˉêy??3?:SPI_FlashWriteAsync異步寫請求 oˉêy?èê?:òì2?D′ ê?è?2?êy: ê?3?2?êy: oˉêy·μ??: ******************************************************************************************/ BOOL SPI_FlashWriteAsync(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite) {if(wNumByteToWrite > FLASH_TX_BUFFER_SIZE){return FALSE;}if(g_tSpiDevice.tState.eStage != eFLASH_STATE_IDLE){Debug(eDBUG_LEVEL_ERROR,"[%d]Flash_Write:busy,return\r\n", GetTicks());return FALSE;}memcpy(g_tSpiDevice.pTxBuffer, pBuffer, wNumByteToWrite);g_tSpiDevice.wTxLen = wNumByteToWrite;g_tSpiDevice.uTxDstAddr = uWriteAddr;g_tSpiDevice.wTxOffset = 0;g_tSpiDevice.tState.bTxReq = TRUE; //請求標志g_tSpiDevice.tState.bTxCompleted = FALSE;//g_tSpiDevice.tState.bTxBusy = TRUE;return TRUE; } /***************************************************************************************** oˉêy??3?:SPI_FlashWriteAsync oˉêy?èê?:òì2?2á???? ê?è?2?êy: ê?3?2?êy: oˉêy·μ??: ******************************************************************************************/ BOOL SPI_FlashEraseChipAsync(void) {//unsigned char cnt=0; if(g_tSpiDevice.tState.eStage != eFLASH_STATE_IDLE){Debug(eDBUG_LEVEL_ERROR,"[%d]Flash_earse:busy,return\r\n", GetTicks());return FALSE;}g_tSpiDevice.tState.bEraseChipReq = TRUE;return TRUE; } /***************************************************************************************** oˉêy??3?:異步擦除 oˉêy?èê?:òì2?2á???¨μ??· ê?è?2?êy: ê?3?2?êy: oˉêy·μ??: ******************************************************************************************/ BOOL SPI_FlashEraseAsync(uint32_t uAddr, uint16_t wlen) {//unsigned char cnt=0; if(g_tSpiDevice.tState.eStage != eFLASH_STATE_IDLE){Debug(eDBUG_LEVEL_ERROR,"[%d]Flash_earse:busy,return\r\n", GetTicks());return FALSE;}g_tSpiDevice.wTxLen = wlen;g_tSpiDevice.uTxDstAddr = uAddr;g_tSpiDevice.wTxOffset = 0;g_tSpiDevice.tState.bEraseSectorReq = TRUE;return TRUE; } //注冊完成通知 void SPI_WriteAsyncNotifyCallbackRegister(void *pfn) {g_tSpiDevice.pWriteAsyncNotifyCallback = (void (*)())pfn; } void SPI_EraseChipAsyncNotifyCallbackRegister(void *pfn) {g_tSpiDevice.pEraseChipAsyncNotifyCallback = (void (*)())pfn; }//?D??SPI FLASH ?| static BOOL SPI_FlashBusyCheck(void) {if((SPI_Flash_Read_SR()&0x01)==0x01){return TRUE;} else {return FALSE;} } //D′ò?ò3 static BOOL __SPI_FlashWritePage(uint32_t uWriteAddr, uint8_t *pData, uint16_t wWriteLen) {uint8_t cnt;uint16_t index;SPI_FLASH_Write_Enable(); //SET WEL while((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE; /*·μ??D′ê§°ü*/} SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(PAGE_PRG); SPI_Flash_ReadWrite_Byte((unsigned char)((uWriteAddr)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((uWriteAddr)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)uWriteAddr); for(index=0; index < wWriteLen; index++){SPI_Flash_ReadWrite_Byte(*(pData+index)); }SPI_CS_HIGH();return TRUE; } //òì2?D′′|àí×óè??? static int32_t __SPI_FlashWrite(void) {uint16_t wWriteRemainNum = g_tSpiDevice.wTxLen - g_tSpiDevice.wTxOffset;uint8_t *pData = g_tSpiDevice.pTxBuffer + g_tSpiDevice.wTxOffset;uint32_t uWriteAddr = g_tSpiDevice.uTxDstAddr + g_tSpiDevice.wTxOffset;uint16_t wPageRemain = PAGE_SIZE - (uWriteAddr % PAGE_SIZE);//?D??D′íê3éif(wWriteRemainNum == 0){//D′íê3ég_tSpiDevice.tState.bTxCompleted = TRUE;//g_tSpiDevice.tState.bRxBusy = FALSE;g_tSpiDevice.tState.bTxReq = FALSE;g_tSpiDevice.tState.eStage = eFLASH_STATE_IDLE; //D′íê3é ×a???Dif(g_tSpiDevice.pWriteAsyncNotifyCallback){//TODO òì2?í¨?a??μ÷ 1?μ÷ó???êμ??g_tSpiDevice.pWriteAsyncNotifyCallback();}return eSUCCESS;} //D?óúò?ò3ê£óà?éD′×??úif(wWriteRemainNum <= wPageRemain){__SPI_FlashWritePage(uWriteAddr, pData, wWriteRemainNum);g_tSpiDevice.wTxOffset += wWriteRemainNum;//D′íêê£óà}else {__SPI_FlashWritePage(uWriteAddr, pData, wPageRemain);g_tSpiDevice.wTxOffset += wPageRemain;//D′ò???ò3£?}//òì2??á?|g_tSpiDevice.tState.eStage = eFLASH_STATE_BUSY;return eSUCCESS; } //òì2??á?|×óè??? static void __SPI_FlashBusy(void) {//?á?| ·?×èè?if(SPI_FlashBusyCheck()){return ;}//SPIé?′?2ù×÷ò?íê3é//TX processif(g_tSpiDevice.tState.bTxReq == TRUE){g_tSpiDevice.tState.eStage = eFLASH_STATE_WRITE;}//RX process// TODO 2á3yò?íê3éif(g_tSpiDevice.tState.bEraseChipReq == TRUE){g_tSpiDevice.tState.eStage = eFLASH_STATE_ERASE_CHIP;}if(g_tSpiDevice.tState.bEraseSectorReq == TRUE){g_tSpiDevice.tState.eStage = eFLASH_STATE_ERASE;} } //òì2?2á3y×óè??? ???? static int32_t __SPI_FlashEraseChip(void) {uint8_t cnt = 0;SPI_FLASH_Write_Enable(); //SET WELif(g_tSpiDevice.tState.bEraseSuccess == TRUE){g_tSpiDevice.tState.bEraseSuccess = FALSE;g_tSpiDevice.tState.bEraseChipReq = FALSE;g_tSpiDevice.tState.eStage = eFLASH_STATE_IDLE;//D′íê3é ×a???Dif(g_tSpiDevice.pEraseChipAsyncNotifyCallback){TODO òì2?í¨?a??μ÷ 1?μ÷ó???êμ??g_tSpiDevice.pEraseChipAsyncNotifyCallback();}return TRUE;}while((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE;}SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(CHIP_ERASE); SPI_CS_HIGH(); //SPI_Flash_Wait_Busy(); g_tSpiDevice.tState.eStage = eFLASH_STATE_BUSY;//òì2??á?|return TRUE; } //òì2?2á3y×óè??? static int32_t __SPI_FlashErase(void) {uint8_t cnt = 0; //uint32_t uSectorIdxFirst = g_tSpiDevice.uTxDstAddr/SECTOR_SIZE;uint32_t uSectorIdxTail = (g_tSpiDevice.uTxDstAddr+g_tSpiDevice.wTxLen)/SECTOR_SIZE;uint32_t uCurrentSectorIdx = (g_tSpiDevice.uTxDstAddr + g_tSpiDevice.wTxOffset)/SECTOR_SIZE;if(uCurrentSectorIdx > uSectorIdxTail){g_tSpiDevice.tState.bEraseSectorReq = FALSE;g_tSpiDevice.tState.bEraseSuccess = TRUE;g_tSpiDevice.tState.eStage = eFLASH_STATE_IDLE;//D′íê3é ×a???Dif(g_tSpiDevice.pEraseChipAsyncNotifyCallback){TODO òì2?í¨?a??μ÷ 1?μ÷ó???êμ??g_tSpiDevice.pEraseChipAsyncNotifyCallback();}return TRUE;}SPI_FLASH_Write_Enable(); //SET WELwhile((SPI_Flash_Read_SR()&0x2)!=0x2) {cnt ++;if(cnt >200)return FALSE;}SPI_CS_LOW(); SPI_Flash_ReadWrite_Byte(SECTOR_ERASE); SPI_Flash_ReadWrite_Byte((unsigned char)((uCurrentSectorIdx*SECTOR_SIZE)>>16)); SPI_Flash_ReadWrite_Byte((unsigned char)((uCurrentSectorIdx*SECTOR_SIZE)>>8)); SPI_Flash_ReadWrite_Byte((unsigned char)(uCurrentSectorIdx*SECTOR_SIZE)); SPI_CS_HIGH(); g_tSpiDevice.wTxOffset += SECTOR_SIZE;//SPI_Flash_Wait_Busy(); g_tSpiDevice.tState.eStage = eFLASH_STATE_BUSY;//òì2??á?|return TRUE; } //???D′|àí×óè??? static void __SPI_FlashIdle(void) {//???ˉ?÷??è???if(g_tSpiDevice.tState.bTxReq == TRUE){g_tSpiDevice.tState.eStage = eFLASH_STATE_WRITE;} else if(g_tSpiDevice.tState.bRxReq == TRUE){g_tSpiDevice.tState.eStage = eFLASH_STATE_READ;} else if(g_tSpiDevice.tState.bEraseChipReq == TRUE){g_tSpiDevice.tState.eStage = eFLASH_STATE_ERASE_CHIP;}else if(g_tSpiDevice.tState.bEraseSectorReq == TRUE){g_tSpiDevice.tState.eStage = eFLASH_STATE_ERASE;} } //SPIòì2?2ù×÷′|àí×üè??? void SPI_FlashAsyncProcTask(void) {switch(g_tSpiDevice.tState.eStage){case eFLASH_STATE_IDLE:__SPI_FlashIdle();break;case eFLASH_STATE_WRITE:__SPI_FlashWrite();break;case eFLASH_STATE_READ://TODObreak;case eFLASH_STATE_BUSY:__SPI_FlashBusy();break;case eFLASH_STATE_ERASE_CHIP:__SPI_FlashEraseChip();break;case eFLASH_STATE_ERASE:__SPI_FlashErase();break;default:break;}}

總結(jié)

以上是生活随笔為你收集整理的SpiFlash同步/异步读写单片机裸机实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。