精华内容
下载资源
问答
  • 下面附上SPI FLASH 同步/异步读写实例。 //SPI状态机状态 typedef enum { eFLASH_STATE_IDLE = 0, eFLASH_STATE_WRITE = 1, eFLASH_STATE_READ = 2, eFLASH_STATE_BUSY = 3, eFLASH_STATE_ERASE_CHIP =...
     单片机裸机开发中会经常遇到外设速度过慢,长时间读忙等待,但CPU又不能长时间阻塞的问题。
    
    这种问题可以通过实现一个状态机来异步处理。

    异步状态机代码结构示例:

    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;
    	}
    }

    通过把阻塞的任务单独分离出来,交给一个状态机子任务来处理。则应用程序只需要调用一个处理请求而无需原地死等,状态机处理完成后,可以异步回调来通知应用程序任务已完成。


    下面附上SPI FLASH 同步/异步读写实例。

    //SPI状态机状态
    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设备结构体
    typedef struct SpiDevice_s {
    	SPI_TypeDef *spiHandle;//SPI物理属性
    	uint8_t *pTxBuffer;//异步发送缓存
    	uint32_t uTxDstAddr;//异步发送目地地址
    	uint16_t wTxLen;//异步发送长度
    	uint16_t wTxOffset; //异步当前缓存已发送偏移 
    	uint8_t *pRxBuffer;
    	uint32_t uRxSrcAddr;
    	uint16_t wRxLen;
    	uint16_t wRxOffset; 
    	void (*pWriteAsyncNotifyCallback)(); //异步写完成回调通知
    	void (*pEraseChipAsyncNotifyCallback)();//异不擦除回调通知
    	struct {
    		FlashState_e eStage;//当前状态机状态
    		//BOOL bTxBusy:1;   //发送忙
    		BOOL bTxReq:1;     //发送请求
    		BOOL bTxCompleted:1;//发送完成
    		//BOOL bRxBusy:1;  //读忙
    		BOOL bRxReq:1;    //读请求
    		BOOL bEraseChipReq:1;//擦整片请求
    		BOOL bEraseSectorReq:1;//擦扇区请求
    		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);//同步写字节
    	uint32_t (*Write)(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite);//同步写
    	BOOL (*WriteAsync)(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite);//异步写
    	BOOL (*EraseChipAsync)(void);//异步整片擦
    	BOOL (*EraseAsync)(uint32_t uAddr, uint16_t wlen);//奶步擦
    	void (*WriteAsyncNotifyCallbackRegister)(void* pfn);//异步写完成回调注册
    	void (*EraseChipAsyncNotifyCallbackRegister)(void *pfn);//异步擦完成回调注册
    }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,	//ͬ²½ÕûƬ²Á
    	SPI_Flash_Read,				//ͬ²½¶Á
    	SPI_Flash_WriteByte,	//ͬ²½Ð´×Ö½Ú
    	SPI_Flash_Write,			//ͬ²½Ð´
    	SPI_FlashWriteAsync,	//Ò첽д
    	SPI_FlashEraseChipAsync,	//Òì²½ÕûƬ²Á³ý
    	SPI_FlashEraseAsync,
    	SPI_WriteAsyncNotifyCallbackRegister,//д״̬Ò첽֪ͨ»Øµ÷
    	SPI_EraseChipAsyncNotifyCallbackRegister,//²Á³ý״̬Ò첽֪ͨ»Øµ÷
    };


    //SPI同步操作
    /*****************
    ²Á³ýÒ»¸öÉÈÇø
    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¿Õ¼ä²Á³ý*/
    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;
    } 
    
    /*²Á³ýоƬ*/
    unsigned char SPI_Flash_Erase_Chip(void)  
    {   
    		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(CHIP_ERASE);        
        SPI_CS_HIGH();                                         
        SPI_Flash_Wait_Busy();  
    		return TRUE;
    }  
    
    /*Ö¸¶¨µØÖ·¶ÁÈ¡Ö¸¶¨³¤¶ÈÊý¾Ý*/
    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);         
        /*¸³ÖµµØÖ·*/
        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;   /*·µ»Øдʧ°Ü*/
    		} 
    		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);  /*¼ÆËã¸ÃÒ³Öл¹ÓжàÉÙÊ£Óà¿Õ¼ä*/
    	unsigned char cnt=0;
    	unsigned short int index;
    	unsigned int pagenum =WriteAddr/PAGE_SIZE;  /*±¾´ÎдÈëµÄÒ³Êý*/
    	unsigned int Addr;
    	
    	if(pageoffset >= NumByteToWrite)  //Ê£Óà¿Õ¼ä´óÓÚҪдµÄÊýÁ¿
    	{
        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(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
    	{
    		/*ÏȽ«¸ÃÒ³ÌîÂú*/
    		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(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;  /*³¤¶È¼õȥдÈëÊý¾Ý*/
    		pagenum++;
    		Addr = pagenum*PAGE_SIZE;  //»ñÈ¡ÏÂÒ»Ò³µÄÆðʼµØÖ·
    		
    		while(NumByteToWrite >0)
    		{
    			if(NumByteToWrite > PAGE_SIZE)  //ÈÔÈ»´óÓÚÒ»Ò³
    			{
    				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(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;  //»ñÈ¡ÏÂÒ»Ò³µÄÆðʼµØÖ·
    			}
    			else
    			{
    				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(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异步操作
     *************************************************************************************************/
    
    /*****************************************************************************************                    									       	
    º¯ÊýÃû³Æ:SPI_FlashWriteAsync异步写请求
    º¯ÊýÃèÊö:Ò첽д
    ÊäÈë²ÎÊý:                                  
    Êä³ö²ÎÊý:                                                        
    º¯Êý·µ»Ø: 
    ******************************************************************************************/
    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;
    }
    /*****************************************************************************************                    									       	
    º¯ÊýÃû³Æ:SPI_FlashWriteAsync
    º¯ÊýÃèÊö:Òì²½²ÁÕûƬ
    ÊäÈë²ÎÊý:                                  
    Êä³ö²ÎÊý:                                                        
    º¯Êý·µ»Ø: 
    ******************************************************************************************/
    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;	
    }
    /*****************************************************************************************                    									       	
    º¯ÊýÃû³Æ:异步擦除
    º¯ÊýÃèÊö:Òì²½²ÁÖ¸¶¨µØÖ·
    ÊäÈë²ÎÊý:                                  
    Êä³ö²ÎÊý:                                                        
    º¯Êý·µ»Ø: 
    ******************************************************************************************/
    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;
    }
    
    
    
    //ÅжÏSPI FLASH æ
    static BOOL SPI_FlashBusyCheck(void)
    {
    	if((SPI_Flash_Read_SR()&0x01)==0x01)
    	{
    		return TRUE;
    	} 
    	else 
    	{
    		return FALSE;
    	}
    }
    //дһҳ
    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;   /*·µ»Øдʧ°Ü*/
    	} 
    	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;
    }
    //Ò첽д´¦Àí×ÓÈÎÎñ
    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);
    
    	//ÅжÏдÍê³É
    	if(wWriteRemainNum == 0)
    	{
    		//дÍê³É
    		g_tSpiDevice.tState.bTxCompleted = TRUE;
    		//g_tSpiDevice.tState.bRxBusy = FALSE;
    		g_tSpiDevice.tState.bTxReq = FALSE;
    		g_tSpiDevice.tState.eStage = eFLASH_STATE_IDLE; //дÍê³É ת¿ÕÏÐ
    		if(g_tSpiDevice.pWriteAsyncNotifyCallback)
    		{
    			//TODO Ò첽֪ͨ»Øµ÷ ¹©µ÷ÓÃÕßʵÏÖ
    			g_tSpiDevice.pWriteAsyncNotifyCallback();
    		}
    		return eSUCCESS;
    	}		
    
    	
    	//СÓÚһҳʣÓà¿Éд×Ö½Ú
    	if(wWriteRemainNum <= wPageRemain)
    	{
    		__SPI_FlashWritePage(uWriteAddr, pData, wWriteRemainNum);
    		g_tSpiDevice.wTxOffset += wWriteRemainNum;
    		//дÍêÊ£Óà
    	}
    	else 
    	{
    		__SPI_FlashWritePage(uWriteAddr, pData, wPageRemain);
    		g_tSpiDevice.wTxOffset += wPageRemain;
    		//дһÕûÒ³£¬
    	}
    	//Òì²½¶Áæ
    	g_tSpiDevice.tState.eStage = eFLASH_STATE_BUSY;
    	return eSUCCESS;
    }
    //Òì²½¶Áæ×ÓÈÎÎñ
    static void __SPI_FlashBusy(void)
    {
    	//¶Áæ ·Ç×èÈû
    	if(SPI_FlashBusyCheck())
    	{
    		return ;
    	}
    	//SPIÉϴβÙ×÷ÒÑÍê³É
    	//TX process
    	if(g_tSpiDevice.tState.bTxReq == TRUE)
    	{
    		g_tSpiDevice.tState.eStage = eFLASH_STATE_WRITE;
    	}
    	//RX process
    	// TODO ²Á³ýÒÑÍê³É
    	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;
    	}
    }
    //Òì²½²Á³ý×ÓÈÎÎñ ÕûƬ
    static int32_t __SPI_FlashEraseChip(void)
    {
    	uint8_t cnt = 0;
    	SPI_FLASH_Write_Enable();                  //SET WEL
    	if(g_tSpiDevice.tState.bEraseSuccess == TRUE)
    	{
    		g_tSpiDevice.tState.bEraseSuccess = FALSE;
    		g_tSpiDevice.tState.bEraseChipReq = FALSE;
    		g_tSpiDevice.tState.eStage = eFLASH_STATE_IDLE;//дÍê³É ת¿ÕÏÐ
    		if(g_tSpiDevice.pEraseChipAsyncNotifyCallback)
    		{
    			TODO Ò첽֪ͨ»Øµ÷ ¹©µ÷ÓÃÕßʵÏÖ
    			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;//Òì²½¶Áæ
    	return TRUE;
    }
    //Òì²½²Á³ý×ÓÈÎÎñ 
    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;//дÍê³É ת¿ÕÏÐ
    		if(g_tSpiDevice.pEraseChipAsyncNotifyCallback)
    		{
    			TODO Ò첽֪ͨ»Øµ÷ ¹©µ÷ÓÃÕßʵÏÖ
    			g_tSpiDevice.pEraseChipAsyncNotifyCallback();
    		}
    		return TRUE;
    	}
    	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)((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;//Òì²½¶Áæ
    	return TRUE;
    }
    //¿ÕÏд¦Àí×ÓÈÎÎñ
    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Òì²½²Ù×÷´¦Àí×ÜÈÎÎñ
    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:
    			//TODO
    			break;
    		case eFLASH_STATE_BUSY:
    			__SPI_FlashBusy();
    			break;
    		case eFLASH_STATE_ERASE_CHIP:
    			__SPI_FlashEraseChip();
    			break;
    		case eFLASH_STATE_ERASE:
    			__SPI_FlashErase();
    			break;
    		default:
    			break;
    	}
    	
    }
    	
    

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    展开全文
  • flash 歌词同步播放

    2008-08-30 23:33:08
    flash 歌词同步播放源文件,用 actionscript 3.0 编写,附源文件、歌词和歌曲
  • 同步Nand与异步Nand Flash 我们在浏览Nand Flash的数据手册时,一般可以看到如下的描述,有同步和非同步(异步)之分。 Asynchronous:非同步/异步 Synchronous:同步 芯片引脚 同步与异步的引脚差异:...

    同步Nand与异步Nand Flash

    我们在浏览Nand Flash的数据手册时,一般可以看到如下的描述,有同步和非同步(异步)之分。

    • Asynchronous:非同步/异步
    • Synchronous:同步

    芯片引脚

    在这里插入图片描述

    同步与异步的引脚差异:

    • 同步下PIN8为W/R#引脚,非同步下为RE#引脚;
    • 同步下PIN18为CLK引脚,非同步下为WE#引脚;
    • 同步下PIN35引脚不使用,非同步下为DQS信号。

    同步/异步

    简单说,需要时钟的就是同步Nand Flash,不需要时钟的就是异步/非同步Nand Flash。

    同步

    Sync模式是指Flash操作时需要一个源时钟来对锁存信号进行同步,提高信号采集的准确性。

    因为另外一个源时钟信号来进行同步,所以对Flash的品质要求较高,如果信号不稳定,很稳定导致源时钟信号与锁存信息不对应,导致数据采样不准确。

    异步

    Async,即不需要时钟信号来进行同步,数据通过WEN/REN来锁存。

    在未使用DDR的时候,Async方式的操作效率是比Sync效率低。因为Sync模式有时钟同步,信号较准确,所以可以提高采样率。Async模式为了提高效率,所以必须采用某种方式提升信号准确性。这 个时候,采用了差分信号,大幅提升了信号的准确性,为此采用了DDR模式采样数据。

    注:Sync模式的Flash一般支持Async,当品质不达标时,便采用Async模式操作。

    镁光NandFlash芯片资料参考:

    https://t-electrons.ru/wp-content/uploads/2019/09/MT29F64G08CBAA.pdf

    其他

    关于其他的Flash知识,可以看一下我之前的相关的技术博文,具体的如下所示。

    1.NAND Flash系列之NAND与NOR Flash

    2.SD卡和TF卡的区别/差异

    3.NandFlash的位反转

    4.NAND Flash控制器功能

    5.EEPROM介绍及与Flash区别

    6.UFS存储介绍

    7.Nand Flash之并行与串行

    8.NAND Flash标准之ONFI VS TOGGLE

    2019-12-24

    展开全文
  • flash实现歌词同步

    千次阅读 2010-05-01 08:32:00
    那时想弄一个FLASH音乐播放器,放在QQ空间里,音乐播放部份比较简单,很快就完成了,但歌词同步部份没有一点头绪,所以就上网搜索了一下,发现关于FLASH歌词同步的文章少之又少,开头一大堆无聊话,代码只给出了一小...

    代码很早就写好了,现在才发布出来。那时想弄一个FLASH音乐播放器,放在QQ空间里,音乐播放部份比较简单,很快就完成了,但歌词同步部份没有一点头绪,所以就上网搜索了一下,发现关于FLASH歌词同步的文章少之又少,开头一大堆无聊话,代码只给出了一小部份,根本无法正确运行,所以我只好自己写一个歌词同步功能了,这里给出全部源码。

    关于歌曲播放部份就不说了,重点讲一下歌词同步。


    先看看LRC歌词

    [ti:海阔天空]
    [ar:BEYOND]
    [al:乐与怒 ]
    [by:水天一色]
    [00:03.59]海阔天空
    [00:09.47]歌手:BETYOND(主唱:黄家驹)
    [00:16.90]专辑:乐与怒
    [00:17.83]今天我
    [00:21.65]寒夜里看雪飘过
    [00:25.03]怀着冷却了的心窝飘远方
    [00:31.47]风雨里追赶
    [00:34.46]雾里分不清影踪
    [00:37.72]天空海阔你与我
    [00:40.03]可会变(谁没在变)
    [00:44.79]多少次
    [00:46.78]迎着冷眼与嘲笑
    [00:50.28]从没有放弃过心中的理想
    [00:56.03]一刹那恍惚
    [00:59.21]若有所失的感觉
    [01:02.15]不知不觉已变淡
    [01:05.40]心里爱(谁明白我)
    [01:09.28]原谅我这一生不羁放纵爱自由
    [01:16.15]也会怕有一天会跌倒
    [01:22.21]被弃了理想谁人都可以
    [01:28.29]那会怕有一天只你共我

    可以看到LRC歌词的基本形式是[分:秒.毫秒]

    现在来写代码

    function LoadLrc(sUrl:String):Void//加载并分析歌词
    {
     //定义两个数组,mylrc用过分析过程使用.newlrc为最终保存歌词的数组
     newlrc = new Array();
     mylrc = new Array();
      var lrc:LoadVars = new LoadVars();
      lrc.load(sUrl);
      lrc.onLoad=function(success:Boolean):Void
      {
        if(success)//判断是否加载成功
        {
       var str:String;
       str=unescape(lrc.toString());
          mylrc = str.split("/n");
       for (i=0; i<mylrc.length; i++)
          {
        if (mylrc[i].substr(0, 3) == "[ti"){}//歌名标签
        else if (mylrc[i].substr(0, 3) == "[ar"){}//乐队标签
        else if (mylrc[i].substr(0, 3) == "[al"){}//专辑标签
        else if (mylrc[i].substr(0, 3) == "[by"){}//
        else if (mylrc[i].substr(0, 1) == "[")//歌词时间戳
        { 
             var temp:Array = mylrc[i].split("]");
         //判断是不是同时有两个或以上的时间(有时候一句歌词出现几次就会有这种情况)
             if(temp.length == 2)//只有一句歌词
         {
               newlrc.push(deleteStr(temp[0])+"|"+temp[1]);//加入数组
             }
         else if (temp.length>2)//有两句以上的歌词
         {
               for(k=0; k<temp.length-1; k++)
          {
                 newlrc.push(deleteStr(temp[k])+"|"+temp[temp.length-1]);
               }
             }
           }
          }
        }
        if(newlrc.length<1)//加载不成功或分析不成功.
      {
          newlrc.push("1|找不到歌词 歌词文件:"+sUrl);
        }
      tmpLrc = new Array();
        newlrc.sort();//进行时间排序,如果只需要一条一条显示,不使用也可
        for (i=0; i<newlrc.length; i++)
      {
       tmpLrc=newlrc[i].split("|");
       Mianban.addCuePoint(tmpLrc[1],tmpLrc[0]);
        }
      };
    }

    重点代码就是这些,详细的可以下载源码看一看

     

    FALSE实现歌词同步.rar

     

    展开全文
  • FlashMV 音乐画面同步

    2006-02-23 09:05:59
    制作 Flash Music Video 的时候怎样让音乐和画面同步的一个非常好的例子,您如果有兴趣,不妨分析分析。
  • FLASH动画制作,MTV作品中实现声音与歌词同步的三种方法
  • flash java 制作一个实时同步的时钟
  • 很多Flash学习者在制作Flash MTV时,除了需要做到歌词与场景内容美妙融合外,时常还会遇到声音与歌词很难精确同步的烦琐难题,以参加省级动漫大赛获奖的原创《白狐》、《我与祖国共奋进,我为崛起献青春》等Flash MTV...
  • 只需要将资源发布为exe文件便能播放本地和网络歌词和mp3。
  • 先对ONFI标准进行了介绍,然后再设计了一种支持ONFI2.1标准源同步高速模式的NAND Flash控制器,包括状态机的设计,接口的设计等。对设计中遇到的源同步模式下,信号的对齐问题进行了说明,并提出了一种解决方法。...
  • flash制作DJ舞蹈!声音动画代码相结合!
  • Nand Flash同步、异步、ONFI、Toggle

    万次阅读 多人点赞 2018-07-02 16:55:15
    DDR(Double Data Rate),写数据时通过MCU来控制DQS信号跳变沿来触发(即上升沿和下降沿均触发),所以对信号的准确性要求较高,可以通过增加同步时钟信号来提高信号的准确性,如ONFI2.0时的DDR就是使用此方式。...
    

    1. SDR和DDR

    1. SDR(Single Data Rate),写读数据使用上升沿或下降沿来触发。因为只用上升沿或下降沿,对信号准确性要求较低。
    2. DDR(Double Data Rate),写数据时通过MCU来控制DQS信号跳变沿来触发(即上升沿和下降沿均触发),所以对信号的准确性要求较高,(同步)可以通过增加同步时钟信号来提高信号的准确性,如ONFI2.0时的DDR就是使用此方式。(异步)另外还可以通过差分信号来提高信号准确性,Toggle下的DDR,ONFI3.0/ONFI4.0下的DDR也都支持DQS差分信号来进行DDR操作。

    2. Sync和Async

    1. Sync模式是指Flash操作时需要一个源时钟来对锁存信号进行同步,提高信号采集的准确性。因为另外一个源时钟信号来进行同步,所以对Flash的品质要求较高,如果信号不稳定,很容易导致源时钟信号与锁存信息不对应,导致数据采样不准确。Sync模式的Flash一般支持Async,当品质不达标时,便采用Async模式操作。
    2. Async,即不需要时钟信号来进行同步,数据通过WEN/REN来锁存。在未使用DDR的时候,Async方式的操作效率是比Sync效率低。因为Sync模式有时钟同步,信号较准确,所以可以提高采样率。Async模式为了提高效率,所以必须采用某种方式提升信号准确性。这 个时候,采用了差分信号,大幅提升了信号的准确性,为此采用了DDR模式采样数据。

    3. ONFI和Toggle

    1. ONFI(Open Nand Flash Interface),由Hynix、Inter、Micron、Phison、Sony、Spansion于2006年共同创建的一个Nand Flash的接口标准,并于当年发布了ONFI1.0标准,支持SDR。ONFI2.0时增加NV-DDR,支持DDR操作,不过是使用同步时钟来控制的。ONFI3.0时,增加NV-DDR2,ONFI4.0时增加了NV-DDR3。NV-DDR2和NV-DDR3都是支持DQS差分信号而不用同步时钟的。并且ONFI接口都是同步向前兼容的。但是接口间的转换只支持如下几种:(详见ONFI Spec)
      • SDR to NV-DDR
      • SDR to NV-DDR2
      • NV-DDR to SDR
      • NV-DDR2 to SDR
    2. Toggle,是Samsung和Toshiba以DDR为基础制定的Flash接口标准,是为了对抗ONFI的标准。Toggle1.0对应DDR1,Toggle2.0对应DDR2。Toggle接口的Flash一般也支持切换到Legacy接口(即SDR,和ONFI1.0是相同的)。Toggle接口Flash一般启动时是Legacy Mode,需要设置才能进入Toggle Mode(DDR1/DDR2),同样在Toggle模式下也可以设置命令序列进入Legacy Mode(SDR)。
    3. 除了ONFI2.0时的NV-DDR1是需要同步时钟外,其他接口下都是Async模式。所以我们常说从DDR模式切换到Async模式是不太准确的说法。应该说切换到Legacy Async、Traditinal Async或是SDR模式。

    ONFI接口标准

      ONFI(Open NAND Flash Interface)标准是由英特尔,镁光,海力士,台湾群联电子,SanDisk, 索尼,飞索半导体为首宣布统一制定的连接NAND闪存和控制芯片的接口标准,当初制定ONFI标准的主要目的是统一当时混乱的闪存标准。

      2006年,随着手机、MP3播放器、U盘的需求量逐渐增大,以及开始步入消费市场的SSD,市场对NAND闪存的需求也增加不少,而当时各个闪存制造厂所用的设计标准各有不同,这样导致闪存控制器厂商和下游产品制造厂在制作产品时碰到各种麻烦,业界迫切需求一个统一的标准,这就是ONFI的诞生背景。

      ONFI 1.0制定于2006年12月,内容主要是制定闪存的物理接口、封装、工作机制、控制指令、寄存器等规范,增加对ECC的支持,传输带宽从传统的Legacy接口的40MB/s提升到50MB/s,性能提升幅度不大,不过其主要目的还是统一闪存接口规范,减轻产品厂商的开发压力。

      ONFI 2.0标准诞生于2008年2月,2.0标准将带宽速度提高到133MB/s以满足高速设备对闪存性能的需求,在该版本中,主要是通过两项技术来提高传输速度。第一项就是在DRAM领域里常用的DDR(Double Data Rate,双倍数据率)信号技术。第二项是使用源同步时钟来精确控制锁存信号,使其能够达到更高的工作频率。

      ONFI 2.1标准于2009年1月发布,带宽提升到166MB/s和200MB/s(工作模式不同速度不同),8KB page数据传输延时降低,改良电源管理降低写入操作能耗,加强ECC纠错能力,新增“Small Data Move”与“Change Row Address”指令。

      ONFI 2.2发表于2009年10月,增加了LUN(逻辑单元号)重置、增强页编程寄存器的清除和新的ICC测量和规范。LUN重置和页编程寄存器清除提升了拥有多个NAND闪存芯片设备的处理效率,ICC规范则简化了下游厂家的测试程序。

      ONFI 2.3在2010年8月的闪存峰会上发布,在2.2标准的基础上加入了EZ-NAND协议。EZ-NAND是Error Zero NAND的简写,这一协议将NAND闪存的纠错码管理由主控芯片中转移到闪存自身,以减轻主控芯片负担。

      今年3月ONFI 3.0规范发布,接口带宽提升到400MB/s,需求的针脚数更少让PCB走线更加方便,从目前披露的资料来看,ONFI 3.0采用更短的信道、更宽的信号间距,并加入片内终止技术,使其传输带宽能够达到400MB/s。

    三星与东芝的ToggleDDR阵营

      面对ONFI组织的攻势,占有全球70% NAND产能的两大闪存生产巨头三星与东芝决定携手对抗,2007年12月,三星与东芝联合通过了一项关于闪存专利技术互换授权协议,根据这项协议,三星电子和东芝在闪存规格和技术上将完全共享。

      根据项协议规定,三星将允许东芝生产和制造自己旗下的OneNAND和Flex-OneNAND闪存芯片,而东芝公司则将以自己的LBA-NAND和mobileLBA-NAND闪存芯片技术作为条件与三星电子进行交换,这些闪存芯片生产技术都是三星电子和东芝的核心技术,但是新的合作协议让双方在闪存芯片制造技术实力上都取得了进一步的增强,此外他们将一同合作研发新一代闪存产品,也就是后来的Toggle DDR NAND闪存。

      2010年6月三星与东芝开始投产符合Toggle DDR 1.0接口标准的NAND闪存,Toggle DDR NAND采用双向DQS信号控制读写操作,信号的上升与下降沿都可以进行资料的传输,能使传输速度翻倍,接口带宽为133MB/s,而且没有内置同步时钟发生器(即NAND还是异步设计),因此其功耗会比同步NAND更低。

      2010年8月,最新的Toggle DDR 2.0接口标准发布,传输带宽上升到400MB/s,目前网上关于此标准的详细消息还不多,不过可以可以确定的是技术指标与ONFI 3.0是类似的。

    闪存的同步与异步

      我们经常说闪存的同步与异步模式,其实是在ONFI 2.0标准中新加入的特性(ToggleDDR不存在同步闪存的情况,均为异步设计,但性能仍然强悍),ONFI 2.0标准在NAND中加入了同步时钟发生器,主控可以通过发送同步指令激活闪存上的同步时钟信号,使闪存工作在同步模式 ,此时闪存的数据传输速率会大幅度提升,异步模式相当于ONFI 1.0,闪存的带宽为50MB/s,而同步模式下闪存至少也符合ONFI 2.0,闪存带宽可达到133MB/s以上。

      实际上同步与异步闪存都是同一生产线上下来的,颗粒品质的优劣才产生了这样的区别。比如英特尔29F64G08AAME1颗粒属于异步闪存,而英特尔29F32B08JCME2则支持同步/异步模式,又如镁光的29F64G08CBAAA是异步闪存,而29F64G08CBAAB颗粒支持同步/异步模式。

      下面是镁光NAND在异步与同步模式下的部分针脚定义:

      开机时SSD是运行在异步模式的,只有当主控发送同步指令给闪存后,才激活闪存上的源同步时钟,然后针脚定义发生改变,激活DQS信号, 让其工作在同步模式,并将异步模式下的WE#信号变为CLK信号,RE#变为W/R信号,同步模式下DQS信号的上升沿与下级沿都能控制信号的传输,使传输速度翻倍。


    异步模式的数据相位


    同步模式的数据相位

      市面上有少数SSD使用异步闪存,但强制运行在同步模式,性能是上来了,稳定性存在隐患。

    闪存类型对SSD速度的影响

      上面的图左边是OCZ Agility 3 60GB,右边的是Vertex 3 60GB,这两个SSD都是用SandForce SF-2281主控,差别就是Agility 3用的是异步的闪存而Vertex 3用的是同步的闪存,SF-2281主控共有8条通道,如果使用8颗异步模式闪存的话理论内部总带宽是400MB/s,如果用8颗同步模式闪存的话理论内部总带宽则达到1333MB/s,当然这是理论上的,实际上还受着主控性能和各种延迟的影响,异步闪存与同步闪存的差别看上面两个OCZ SSD的读取速度就知道了。

    展开全文
  • (1)在操作文件的地方,调用具有同步功能的函数,如fsync函数,这样只在操作对应文件时才会写入。 (2)修改../x80文件,将  mount -t ubifs ubi1_0 /xxx  修改为:  mount -t ubifs -o sync ubi1_0 /...
  • 最大的特色是可以同时上传所选择的图片,不需要一张上传完毕之后在上传下一张
  • Flash CS4学习笔记3-同步问题 Flash的异步机制,有时候异常DT,总出现意想不到的难题。总结几个问题如下。 1.跳帧时,元件实例异步加载延迟问题。例如某一帧放入了一个按钮元件后,使用实例名称去访问按钮...
  •  以下的代码实现了通常所见的进度条和播放暂停按钮同步响应的功能,在拖拉进度条滑块时主场景不播放,在进度条上点击时则继续播放,与此同时播放暂停按钮会根据目前视频的状况表现出该有的一面。 import flash....
  • 行业分类-嵌入式设备-嵌入式数据库同步flash数据库的方法和装置.zip
  • [转]FLASH的声音同步方式

    千次阅读 2010-05-14 20:47:00
    (1)以“事件”方式开始声音:独立于时间...(4)以“数据流”方式开始声音:“数据流”方式的声音将会严格与时间轴同步——如果影片在播放,就播放声音;如果影片暂停,声音就停止。这种方式主要用于MV和小品的制作。
  • 曾经在开发一个小型的flash网络游戏项目,采用FLASH + Struts + EJB开发的。具有一般网络游戏的聊天,买卖物品等功能。由于网上关于flash网络这方面的技术文章太少,我以前做的也大多是flashWEB方面的东东。所以现在...
  • 山东省邹平县实验中学九年级信息技术 FLASH和 PS 同步练习无答案 新人 教版 FLASH选择题 1下面不属于时间轴组件是 A帧 B 舞台 C 关键帧 D 图层 2为了将制作的 FLASH动画与他人分享就必须将文件导出为影片 FLASH输出...
  • msp430 同步通讯模块源程序,初学者可以作为参考
  • extra=page%3D1%26amp;orderby%3Ddateline%26amp;filter%3D86400[/url] 在设置一个关键帧后,只要你导入了声音文件,在帧属性面板都能进行该帧的声音设置。声音的同步属 ...性(Sync)主要有以下几种:...使用flash...
  • PAGE PAGE 1 山东省邹平县实验中学九年级信息技术 FLASH和PS同步练习无答案 新人教版 FLASH选择题 1下面不属于时间轴组件是 A帧 B舞台 C关键帧 D图层 2为了将制作的FLASH动画与他人分享就必须将文件导出为影片FLASH...
  • 上周接到了一个任务,说要基于Flash Media Server4.5来实现视频会议,白板共享和PPT文档浏览同步功能。 这周就开始着手这方面的研究和代码编写,现把中间经过的过程总结如下: 1、如何实现视频会议 基于Flash ...
  • ###About FlashSpan 是一个开源库,用于跨多个屏幕跨越 Flash 内容。 FlashSpan 依赖于这样一个事实,即在每台计算机上运行的代码应该在一定数量的帧上生成完全相同的视觉效果。 它的工作原理是跟踪每个客户端渲染...
  • FLASH

    千次阅读 2011-03-26 17:23:00
    Flash闪存是非易失性存储器,这是相对于SDRAM(同步动态随机存储器)等存储器所说的。即存储器断电后,内部的数据仍然可以保存。Flash根据技术方式分为Nand 、Nor Flash和AG-AND Flash,而升级。但是经过了十...
  • 前言: 在嵌入式开发中,如uboot的移植,kernel的移植都需要对Flash 有基本的了解。下面细说一下标题中的中Flash中的关系。 Flash Memory(闪存)是非易失性的存储器。一,Flash的内存存储结构flash按照内部存储结构...
  • 总线flash和spi flash

    千次阅读 2016-05-16 13:27:41
    SPI:serial peripheral interface串行外围设备接口,是一种常见的时钟同步串行通信接口。 外置flash按接口分有总线flash,SPI flash。 总线flash需要你的MCU上有外部总线接口,SPI flash就是通过SPI口对flash进行...
  • FlashStore是键值持久存储,具有易于使用的类似ES6 Map的API(同时支持异步和同步),由LevelDB和TypeScript支持。 要求 Node.js v10或更高版本 例子 尝试以下命令 npm install npm run demo 基本功能如下: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,464
精华内容 18,185
关键字:

flask同步