单片机各参数冗余记忆防灾机制 ----防止记忆参数时擦除芯片数据时瞬间掉电而参数全丢失 -----阮丁远20240709

冗余原理:冗余备份10处,每次取重复值次数最多的那个值,比如备份了10处,8处的值都是各不相同,而2处的值都是123,则取123,但是有个问题:就是比如10份备份中只写入了3处最后保存时的值,这样最后的值不起作用,
也可以加时间挫的方法:读取10个备份中最大的时间挫,然后写入新数据时此挫加一后写入,
读取时,如果10份数据都一样,则读其中随便一份即可,
如果不一样,则读时间挫最大的那份(时间挫不一定读时钟芯片的值,可以从0开始计算,32位的值,每次加一,快到32位数的最大值时10份记录的时间挫全从0开始重新记录)

注意:初版源码,可能有bug,请测试和谨慎使用:




#include "../Middlewares/fatfs/w25q64.h" 
   #include "core/net.h"
	 
	 #define rongyu_bak_canshu_bak_count 4 //ÈßÓ౸·Ý4´¦£¬Ã¿´ÎÈ¡ÖØ¸´Öµ×î¶àÇÒʱ¼ä´Á×î´óµÄÄǸöÖµ
	 #define rongyu_bak_canshu_unit_size 4096*200  //ÿ¸öÈßÓ౸·Ýµ¥Î» µÄ×Ü´óС
	 //×ܹ²ÐèÒª800K*4=3.2MµÄ´æ´¢¿Õ¼ä
	 
	 //¼Ç¼¸ñʽ: 20×Ö½Úcanshu_Name£¬150×Ö½Úcanshu_str_value £¬1×Ö½Ú£º ÊÇ·ñÐèÒªÁ´±íʽÀ©Õ¹£¬4×Ö½Ú£ºÊ±¼ä´ì£¬4×Ö½Ú£ºÁ´±íÏÂÒ»ÔªËØµÄË÷Òý £¬1×Ö½Ú£ºÊÇ·ñ±»Á´±íÕ¼Ó㬱£ÁôÀ©Õ¹×Ö½Ú:20×Ö½Ú
	 	#define save_unit_length 200
		 	#define  max_time_value 9999999
	 u8 unit_buf1[save_unit_length*rongyu_bak_canshu_bak_count];
	 
	  u8 unit_buf1_for_write[save_unit_length];
		
		
		
		
void write_to_flash_do(int canshuo_index,u32 max_time_st,char* canshu_Name,char * canshu_value){
 unsigned char i;
		if(max_time_st>(max_time_value-3)){
			
			max_time_st=0;
			
		}
		
		memset(unit_buf1_for_write,0,save_unit_length);
		
		strcpy((char*)unit_buf1_for_write,canshu_Name);
		
		strcpy((char*)&unit_buf1_for_write[20],canshu_value);
		
		
		
		unit_buf1_for_write[170]=0;
		
		
		
		
		 unit_buf1_for_write[171]=max_time_st&0xff;
		
		 unit_buf1_for_write[172]=(max_time_st>>8)&0xff;
		
		 unit_buf1_for_write[173]=(max_time_st>>16)&0xff;
		
		 unit_buf1_for_write[174]=(max_time_st>>24)&0xff;
		
	  for(  i=0;i<rongyu_bak_canshu_bak_count;i++){
		   SPI_Flash_Write_by_earse_ok((u8*)unit_buf1_for_write,i*rongyu_bak_canshu_unit_size+ canshuo_index*save_unit_length,save_unit_length,1);
		
	   }
	



	 }		 
		
		
		
		
		
		
 //#include "lcd.h"
		
		
	
void save_a_canshu_with_bak(int canshuo_index,char* canshu_Name,char * canshu_value){
	
	u32 max_time_st=0;
 unsigned char i;
	u8 is_all_same=1;
	
	for(  i=0;i<rongyu_bak_canshu_bak_count;i++){
		 
		SPI_FLASH_BufferRead(&unit_buf1[save_unit_length*i] , i*rongyu_bak_canshu_unit_size+ canshuo_index*save_unit_length,save_unit_length,1,0);
		
	
	}
	
	for(  i=0;i<(rongyu_bak_canshu_bak_count-1);i++){//¶Ô±ÈÊÇ·ñ4´¦±¸·Ý¶¼Ò»Ñù£º
		
		if(memcmp(&unit_buf1[save_unit_length*i],&unit_buf1[save_unit_length*(i+1)],save_unit_length)!=0){
			
			is_all_same=0;
			break;
		}
		
		//Èç¹ûÊÇδ²Á³ý¹ýµÄ,È«ÊÇ0xffffffff
		if(unit_buf1[save_unit_length*i+171]==0xff && unit_buf1[save_unit_length*i+172]==0xff && unit_buf1[save_unit_length*i+173]==0xff && unit_buf1[save_unit_length*i+174]==0xff ){
			
		
		
			is_all_same=2;
				break;
		
		
	   }
		
						//Èç¹ûÊÇδ²Á³ý¹ýµÄ,È«ÊÇ0xffffffff
		if(unit_buf1[save_unit_length*(i+1)+171]==0xff && unit_buf1[save_unit_length*(i+1)+172]==0xff && unit_buf1[save_unit_length*(i+1)+173]==0xff && unit_buf1[save_unit_length*(i+1)+174]==0xff ){
			
		
		
			is_all_same=2;
				break;
		
		
	   }
		
	}
	
	if(is_all_same==2){	//Èç¹ûÊÇδ²Á³ý¹ýµÄ,È«ÊÇ0xffffffff
		
		
		
		
		write_to_flash_do(canshuo_index,1,canshu_Name,canshu_value);
		
		
	
		
		
		
	}
	else 
	if(is_all_same==1){	//Èç¹ûȫһÑù
		
		
		max_time_st=unit_buf1[171]+unit_buf1[171+1]*256+unit_buf1[171+2]*256*256+unit_buf1[171+3]*256*256*256;
		max_time_st=max_time_st+1;
		
		if(max_time_st>(max_time_value-3)){
			
			max_time_st=0;
			
		}
		
		
			//LCD_ShowNum(44,55,max_time_st,4,16,RED);
		
		write_to_flash_do(canshuo_index,max_time_st,canshu_Name,canshu_value);
		
	
	
	}else{
	
	for(  i=0;i<rongyu_bak_canshu_bak_count;i++){
		
		u32 cur_maxtime=0;
		SPI_FLASH_BufferRead((u8*)unit_buf1,i*rongyu_bak_canshu_unit_size+ canshuo_index*save_unit_length,save_unit_length,1,0);
		
		cur_maxtime=unit_buf1[171]+unit_buf1[171+1]*256+unit_buf1[171+2]*256*256+unit_buf1[171+3]*256*256*256;
				
				if(cur_maxtime < max_time_value ){//Åųýµô0xffffffff
					
							
						if(cur_maxtime>max_time_st){
							
							max_time_st=cur_maxtime;
							
							
						}
				
				}
		
	  }
			max_time_st=max_time_st+1;
		
		if(max_time_st>(max_time_value-3)){
			
			max_time_st=0;
			
		}
		
		
		write_to_flash_do(canshuo_index,max_time_st,canshu_Name,canshu_value);
		
		
		
		
		
		
 }

	
}
int is_all_digit(char* str)
{
    int i;
    for (i = 0; str[i] != '\0'; i++)
    {
        if (!isdigit(str[i]))
        {
            return 0;
        }
    }
    return 1;
}
 void beep_error();




void test_destory_a_canshu(int canshuo_index){
	

		
		
		    memset(unit_buf1_for_write,0xff,save_unit_length);
		
	
		   SPI_Flash_Write_by_earse_ok((u8*)unit_buf1_for_write,1*rongyu_bak_canshu_unit_size+ canshuo_index*save_unit_length,save_unit_length,1);
		
	   




}

void read_a_canshu_with_bak(int canshuo_index,char* canshu_Name,char * out_canshu_str_value,unsigned int * out_value){
	
	
	
	
	
	
	u32 max_time_st=0;
 unsigned char i;
	u8 is_all_same=1;
	
	for(  i=0;i<rongyu_bak_canshu_bak_count;i++){
		 
		SPI_FLASH_BufferRead(&unit_buf1[save_unit_length*i] , i*rongyu_bak_canshu_unit_size+ canshuo_index*save_unit_length,save_unit_length,1,0);
		
	
	}
	
	for(  i=0;i<(rongyu_bak_canshu_bak_count-1);i++){//¶Ô±ÈÊÇ·ñ4´¦±¸·Ý¶¼Ò»Ñù£º
		
		if(memcmp(&unit_buf1[save_unit_length*i],&unit_buf1[save_unit_length*(i+1)],save_unit_length)!=0){
			
			is_all_same=0;
			break;
		}
		
		//Èç¹ûÊÇδ²Á³ý¹ýµÄ,È«ÊÇ0xffffffff
		if(unit_buf1[save_unit_length*i+171]==0xff && unit_buf1[save_unit_length*i+172]==0xff && unit_buf1[save_unit_length*i+173]==0xff && unit_buf1[save_unit_length*i+174]==0xff ){
			
		
		
			is_all_same=2;
				break;
		
		
	   }
		
						//Èç¹ûÊÇδ²Á³ý¹ýµÄ,È«ÊÇ0xffffffff
		if(unit_buf1[save_unit_length*(i+1)+171]==0xff && unit_buf1[save_unit_length*(i+1)+172]==0xff && unit_buf1[save_unit_length*(i+1)+173]==0xff && unit_buf1[save_unit_length*(i+1)+174]==0xff ){
			
		
		
			is_all_same=2;
				break;
		
		
	   }
		
	}
	
	
	
	
	if(is_all_same==2){	//Èç¹ûÊÇδ²Á³ý¹ýµÄ,È«ÊÇ0xffffffff
		
		
	out_canshu_str_value[0]=0;
		
		*out_value=0;
		
		
		
	}
	else 
	if(is_all_same==1){	//Èç¹ûȫһÑù
		

		
		memset(unit_buf1_for_write,0,save_unit_length);
		
		
		strcpy((char*)unit_buf1_for_write,(char*)&unit_buf1[20]);
		
		
		 memcpy((char*)out_canshu_str_value,(char*)unit_buf1_for_write,strlen((char*)unit_buf1_for_write));
		
		 out_canshu_str_value[strlen((char*)unit_buf1_for_write)]=0;
		
		if(is_all_digit(out_canshu_str_value)){
			
					*out_value=atoi(out_canshu_str_value);
			
			
			
		}
		
	
	}else{
	
		
		u8 i_at_max_time_st=0;
		
		
	for(  i=0;i<rongyu_bak_canshu_bak_count;i++){
		
		u32 cur_maxtime=0;
		SPI_FLASH_BufferRead((u8*)unit_buf1,i*rongyu_bak_canshu_unit_size+ canshuo_index*save_unit_length,save_unit_length,1,0);
		
		cur_maxtime=unit_buf1[171]+unit_buf1[171+1]*256+unit_buf1[171+2]*256*256+unit_buf1[171+3]*256*256*256;
				
				if(cur_maxtime < max_time_value ){//Åųýµô0xffffffff
					
							
						if(cur_maxtime>max_time_st){
							
							max_time_st=cur_maxtime;
							
							i_at_max_time_st=i;
						}
				
				}
		
	  }
	
		SPI_FLASH_BufferRead((u8*)unit_buf1,i_at_max_time_st*rongyu_bak_canshu_unit_size+ canshuo_index*save_unit_length,save_unit_length,1,0);
		
		
		
		memset(unit_buf1_for_write,0,save_unit_length);
		
		
		strcpy((char*)unit_buf1_for_write,(char*)&unit_buf1[20]);
		
		
		 memcpy((char*)out_canshu_str_value,(char*)unit_buf1_for_write,strlen((char*)unit_buf1_for_write));
		
		 out_canshu_str_value[strlen((char*)unit_buf1_for_write)]=0;
		
			if(is_all_digit(out_canshu_str_value)){
			
					*out_value=atoi(out_canshu_str_value);
			
			
			
		}
		
		
		
		
 }

	
	
	
	
	
	
	
	
	
}
#include "w25q64.h" 
   #include "core/net.h"
	 
	 
	 
	 SemaphoreHandle_t read_write_locker;  
    u8 writing_or_reading=0;
	  

static SPI_HandleTypeDef  hspi;   


u8 SPIx_ReadWriteByte(u8 txData)
{       
 

uint8_t Rxdata;
	HAL_SPI_TransmitReceive(&hspi,&txData,&Rxdata,1, 1000);       
	return Rxdata;
	
}




void SPI_FLASH_CS_LOW(unsigned char index_chip){
	
	
	if(index_chip==0){//w25q128 for ftp file´æ´¢ºÍweb server ¸ùĿ¼(CS=PI9)
		 HAL_GPIO_WritePin(GPIOI, GPIO_PIN_7, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_9, GPIO_PIN_RESET);
		
	}
	
	if(index_chip==1){//²ÎÊýÅäÖô洢ÓÃ(¶àÉÈÇøÈßÓ౸·Ý£¬·ÇfatÎļþϵͳ)
		
		  HAL_GPIO_WritePin(GPIOI, GPIO_PIN_7, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_9, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_RESET);

		
	}
		
	
	if(index_chip==2){//TF¿¨´¢´æÀúÊ·ÇúÏßÓ㬷ÇfatÎļþϵͳ£¬
		
		  HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_9, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_7, GPIO_PIN_RESET);

		
	}
	
}
void SPI_FLASH_CS_HIGH(unsigned char  index_chip){
	
	
	if(index_chip==0){//w25q128 for ftp file´æ´¢ºÍweb server ¸ùĿ¼(CS=PI9)
		
		  HAL_GPIO_WritePin(GPIOI, GPIO_PIN_7, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_9, GPIO_PIN_SET);

		
	}
	
		if(index_chip==1){//²ÎÊýÅäÖô洢ÓÃ(¶àÉÈÇøÈßÓ౸·Ý£¬·ÇfatÎļþϵͳ)
		
		  HAL_GPIO_WritePin(GPIOI, GPIO_PIN_7, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_9, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET);

		
	}
		if(index_chip==2){//TF¿¨´¢´æÀúÊ·ÇúÏßÓ㬷ÇfatÎļþϵͳ£¬
		
		  HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_9, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOI, GPIO_PIN_7, GPIO_PIN_SET);

		
	}
		
	
}


DMA_HandleTypeDef hdma_spi6_rx;



void HAL_SPI_6_MspInit()
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	
	
  //if(hspi->Instance==SPI2)
  {

		
		
		
  /* USER CODE BEGIN SPI2_MspInit 0 */
 
  /* USER CODE END SPI2_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI6_CLK_ENABLE();
 
		
   __HAL_RCC_BDMA_CLK_ENABLE();
    //__HAL_RCC_DMA2_CLK_ENABLE();
 
     hdma_spi6_rx.Instance = BDMA_Channel0;
    hdma_spi6_rx.Init.Request = BDMA_REQUEST_SPI6_RX;
    hdma_spi6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi6_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi6_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi6_rx.Init.Mode = DMA_NORMAL;
    hdma_spi6_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_spi6_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi6_rx) != HAL_OK)
    {
      
    }
 
    __HAL_LINKDMA(&hspi,hdmarx,hdma_spi6_rx);
 
    /* SPI2 interrupt Init */
    HAL_NVIC_SetPriority(SPI6_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(SPI6_IRQn);
		
  HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
		
		
		 HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams ={0};
		
dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_SPI6_IT;   
dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING_FALLING; 
		 
		 
    dmamux_ReqGenParams.RequestNumber = 1;                             /* ???,????1?DMA?? */
    HAL_DMAEx_ConfigMuxRequestGenerator(&hdma_spi6_rx, &dmamux_ReqGenParams); /* ??DMAMUX */
    HAL_DMAEx_EnableMuxRequestGenerator (&hdma_spi6_rx);                /* ??DMAMUX????? */   
		
		
		
		 __HAL_SPI_ENABLE(&hspi);
  }
 
}

u8 oked_recved=0;


void BDMA_Channel0_IRQHandler(void)
{
	
				HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
	
  HAL_DMA_IRQHandler(&hdma_spi6_rx);
 SPI_FLASH_CS_HIGH(0);
	
	oked_recved=1;
}
 



void SPI6_IRQHandler(){
	
	
	 
	
				HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
	
	
     HAL_SPI_IRQHandler(&hspi);
	
	 SPI_FLASH_CS_HIGH(0);
	
	oked_recved=1;
	
}
































/*
*********************************************************************************************************
*    ? ? ?: bsp_InitSPIBus
*    ????: ??SPI???
*    ?    ?: ?
*    ? ? ?: ?
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*    ? ? ?: bsp_InitSPIParam
*    ????: ??SPI????,????,??????????
*    ?    ?: _BaudRatePrescaler  SPI????????,???????:
*                                 SPI_BAUDRATEPRESCALER_2    2??
*                                 SPI_BAUDRATEPRESCALER_4    4??
*                                 SPI_BAUDRATEPRESCALER_8    8??
*                                 SPI_BAUDRATEPRESCALER_16   16??
*                                 SPI_BAUDRATEPRESCALER_32   32??
*                                 SPI_BAUDRATEPRESCALER_64   64??
*                                 SPI_BAUDRATEPRESCALER_128  128??
*                                 SPI_BAUDRATEPRESCALER_256  256??
*                                                        
*             _CLKPhase           ????,???????:
*                                 SPI_PHASE_1EDGE     SCK????1?????????1???
*                                 SPI_PHASE_2EDGE     SCK????2?????????1???
*                                 
*             _CLKPolarity        ????,???????:
*                                 SPI_POLARITY_LOW    SCK????????????
*                                 SPI_POLARITY_HIGH   SCK????????????
*
*    ? ? ?: ?
*********************************************************************************************************
*/
void bsp_InitSPIParam(uint32_t _BaudRatePrescaler, uint32_t _CLKPhase, uint32_t _CLKPolarity)
{
   
	
	
    
    
    /* ??SPI?? */
    hspi.Instance               = SPI6;                   /* ??SPI */
    hspi.Init.BaudRatePrescaler = _BaudRatePrescaler;     /* ????? */
    hspi.Init.Direction         = SPI_DIRECTION_2LINES;   /* ??? */
    hspi.Init.CLKPhase          = _CLKPhase;              /* ?????? */
    hspi.Init.CLKPolarity       = _CLKPolarity;           /* ?????? */
    hspi.Init.DataSize          = SPI_DATASIZE_8BIT;      /* ?????? */
    hspi.Init.FirstBit          = SPI_FIRSTBIT_MSB;       /* ???????? */
    hspi.Init.TIMode            = SPI_TIMODE_DISABLE;     /* ??TI??  */
    hspi.Init.CRCCalculation    = SPI_CRCCALCULATION_DISABLE; /* ??CRC */
    hspi.Init.CRCPolynomial     = 7;                       /* ??CRC?,???? */
    hspi.Init.CRCLength         = SPI_CRC_LENGTH_8BIT;     /* ??CRC?,???? */
    hspi.Init.NSS               = SPI_NSS_SOFT;               /* ???????????? */
    hspi.Init.FifoThreshold     = SPI_FIFO_THRESHOLD_01DATA;  /* ??FIFO???????? */
    hspi.Init.NSSPMode          = SPI_NSS_PULSE_DISABLE;      /* ?????? */
    hspi.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; /* ??SPI?,SPI?????????? */  
    hspi.Init.Mode             = SPI_MODE_MASTER;            /* SPI??????? */

    /* ???? */
    //if (HAL_SPI_DeInit(&hspi) != HAL_OK)
    {
        //Error_Handler(__FILE__, __LINE__);
    }    

    /* ????? */
    if (HAL_SPI_Init(&hspi) != HAL_OK)
    {
        //Error_Handler(__FILE__, __LINE__);
    }    
		
		
		SPIx_ReadWriteByte(0xff);
		
		HAL_SPI_6_MspInit();
		
}

void bsp_InitSPIBus(void)
{    
    //g_spi_busy = 0;
	
	
	
	
	

    GPIO_InitTypeDef GPIO_InitStruct = {0};



    __HAL_RCC_GPIOI_CLK_ENABLE();
     __HAL_RCC_SPI6_CLK_ENABLE();            // ??SPI1??

    GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Pin = GPIO_PIN_7| GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;   // CS
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);

	
	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_7, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_9, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET);
	
	
	
	 GPIO_InitTypeDef GPIO_Initure;
    RCC_PeriphCLKInitTypeDef SPI2ClkInit;
	
    __HAL_RCC_GPIOG_CLK_ENABLE();                   //ʹÄÜGPIOFʱÖÓ
      //__HAL_RCC_SPI6_CLK_ENABLE();                    //ʹÄÜSPI2ʱÖÓ
    
	//ÉèÖÃSPI2µÄʱÖÓÔ´ 
	SPI2ClkInit.PeriphClockSelection=RCC_PERIPHCLK_SPI6;	    //ÉèÖÃSPI6ʱÖÓÔ´
	SPI2ClkInit.Spi123ClockSelection=RCC_SPI123CLKSOURCE_PLL;	//SPI2ʱÖÓԴʹÓÃPLL1Q
	HAL_RCCEx_PeriphCLKConfig(&SPI2ClkInit);
	
    //PB13,14,15
    GPIO_Initure.Pin=GPIO_PIN_13|GPIO_PIN_14;
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;              //¸´ÓÃÍÆÍìÊä³ö
    GPIO_Initure.Pull=GPIO_NOPULL;//old=GPIO_PULLUP;                  //ÉÏÀ­
    GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;   //GPIO_SPEED_FREQ_VERY_HIGH;   //¿ìËÙ    
    GPIO_Initure.Alternate=GPIO_AF5_SPI6;           //¸´ÓÃΪSPI2
    HAL_GPIO_Init(GPIOG,&GPIO_Initure);             //³õʼ»¯
	
	
	    GPIO_Initure.Pin=GPIO_PIN_12;  //MISO
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;              
    GPIO_Initure.Pull=GPIO_NOPULL;  
  GPIO_Initure.Alternate=GPIO_AF5_SPI6;   		//ÉÏÀ­
    GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH ; //GPIO_SPEED_FREQ_VERY_HIGH;   //¿ìËÙ    
   
    HAL_GPIO_Init(GPIOG,&GPIO_Initure);             //³õʼ»¯
		
		
		
		
		
		
  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_SET);//MISO
	 
  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET);//
  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_12, GPIO_PIN_SET);//
	
	
	
	
	
	
	
	 read_write_locker = xSemaphoreCreateBinary();

	
			 xSemaphoreGive(read_write_locker);
	
	
    
    bsp_InitSPIParam(SPI_BAUDRATEPRESCALER_16, SPI_PHASE_1EDGE, SPI_POLARITY_LOW); //old=SPI_PHASE_1EDGE ,SPI_POLARITY_LOW
}



 


/******************** (C) COPYRIGHT ********************
 * ÎļþÃû  £ºspi_flash.c
 * ÃèÊö    £ºspi µ×²ãÓ¦Óú¯Êý¿â      
 * Ó²¼þÁ¬½Ó ----------------------------
 *         | PC8-SPI2-NSS  : W25X40-CS  |
 *         | PD14-SPI2-SCK  : W25X40-CLK |
 *         | PC7-SPI2-MISO : W25X40-DO  |
 *         | PD13-SPI2-MOSI : W25X40-DIO |
 *         | PC6-WRITE    : W25X40-DIO |
 *         | PD15-HOLD    : W25X40-DIO |
 *          ----------------------------
 * ¿â°æ±¾  £ºST3.0.0
 *
 * ×÷Õß    £º
 * ²©¿Í    £º
**********************************************************************************/



/* Private typedef -----------------------------------------------------------*/
//#define SPI_FLASH_PageSize      4096
#define SPI_FLASH_PageSize      256
#define SPI_FLASH_PerWritePageSize      256

/* Private define ------------------------------------------------------------*/
#define W25X_WriteEnable		      0x06 
#define W25X_WriteDisable		      0x04 
#define W25X_ReadStatusReg		    0x05 
#define W25X_WriteStatusReg		    0x01 
#define W25X_ReadData			        0x03 
#define W25X_FastReadData		      0x0B 
#define W25X_FastReadDual		      0x3B 
#define W25X_PageProgram		      0x02 
#define W25X_BlockErase			      0xD8 
#define W25X_SectorErase		      0x20 
#define W25X_ChipErase			      0xC7 
#define W25X_PowerDown			      0xB9 
#define W25X_ReleasePowerDown	    0xAB 
#define W25X_DeviceID			        0xAB 
#define W25X_ManufactDeviceID   	0x90 
#define W25X_JedecDeviceID		    0x9F 

#define WIP_Flag                  0x01  /* Write In Progress (WIP) flag */

#define Dummy_Byte                0xFF



void SPI_FLASH_Write_Protect_ENABLE(void)//flash ´ò¿ªÐ´±£»¤
{
  SPI_FLASH_Write_Protect_Assert();
}
void SPI_FLASH_Write_Protect_DISABLE(void)//flash ¹Ø±Õд±£»¤
{
  SPI_FLASH_Write_Protect_Deassert();
}

void SPI_FLASH_Hold_ENABLE(void)//flash HOLD ENABLE
{
  SPI_FLASH_Hold_Assert();
}
void SPI_FLASH_Hold_DISABLE(void)//flash HOLD DISABLE
{
  SPI_FLASH_Hold_Deassert();
}

/*******************************************************************************
* Function Name  : SPI_FLASH_Init
* Description    : Initializes the peripherals used by the SPI FLASH driver.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_Init(void)
{

	
        
}
/*******************************************************************************
* Function Name  : SPI_FLASH_SectorErase
* Description    : Erases the specified FLASH sector.
* Input          : SectorAddr: address of the sector to erase.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_SectorErase(u32 SectorAddr,unsigned char  index_chip)
{
  /* Send write enable instruction */
  SPI_FLASH_WriteEnable(index_chip);
  SPI_FLASH_WaitForWriteEnd(index_chip);
  /* Sector Erase */
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);
  /* Send Sector Erase instruction */
  SPI_FLASH_SendByte(W25X_SectorErase);
  /* Send SectorAddr high nibble address byte */
  SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
  /* Send SectorAddr medium nibble address byte */
  SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
  /* Send SectorAddr low nibble address byte */
  SPI_FLASH_SendByte(SectorAddr & 0xFF);
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);
  /* Wait the end of Flash writing */
  SPI_FLASH_WaitForWriteEnd(index_chip);
}


void SPI_Flash_Erase_SectorOK(u32 Dst_Addr,unsigned char  index_chip)   
{   
	Dst_Addr*=4096;
    SPI_FLASH_WriteEnable(index_chip);                  //SET WEL 	 
    SPI_FLASH_WaitForWriteEnd(index_chip);   
  	 SPI_FLASH_CS_LOW(index_chip);                          //ʹÄÜÆ÷¼þ   
    SPI_FLASH_SendByte(W25X_SectorErase);      //·¢ËÍÉÈÇø²Á³ýÖ¸Áî 
    SPI_FLASH_SendByte((u8)((Dst_Addr)>>16));  //·¢ËÍ24bitµØÖ·    
    SPI_FLASH_SendByte((u8)((Dst_Addr)>>8));   
    SPI_FLASH_SendByte((u8)Dst_Addr);  
  SPI_FLASH_CS_HIGH(index_chip);                          //È¡ÏûƬѡ     	      
    SPI_FLASH_WaitForWriteEnd(index_chip);   				   //µÈ´ý²Á³ýÍê³É
}  

/*******************************************************************************
* Function Name  : SPI_FLASH_BulkErase
* Description    : Erases the entire FLASH.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_BulkErase(unsigned char  index_chip)
{
  /* Send write enable instruction */
  SPI_FLASH_WriteEnable(index_chip);

  /* Bulk Erase */
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);
  /* Send Bulk Erase instruction  */
  SPI_FLASH_SendByte(W25X_ChipErase);
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);

  /* Wait the end of Flash writing */
  SPI_FLASH_WaitForWriteEnd(index_chip);
}

/*******************************************************************************
* Function Name  : SPI_FLASH_PageWrite
* Description    : Writes more than one byte to the FLASH with a single WRITE
*                  cycle(Page WRITE sequence). The number of byte can't exceed
*                  the FLASH page size.
* Input          : - pBuffer : pointer to the buffer  containing the data to be
*                    written to the FLASH.
*                  - WriteAddr : FLASH's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the FLASH,
*                    must be equal or less than "SPI_FLASH_PageSize" value.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite,unsigned char  index_chip)
{
  /* Enable the write access to the FLASH */
  SPI_FLASH_WriteEnable(index_chip);

  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);
  /* Send "Write to Memory " instruction */
  SPI_FLASH_SendByte(W25X_PageProgram);
  /* Send WriteAddr high nibble address byte to write to */
  SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
  /* Send WriteAddr medium nibble address byte to write to */
  SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
  /* Send WriteAddr low nibble address byte to write to */
  SPI_FLASH_SendByte(WriteAddr & 0xFF);

  if(NumByteToWrite > SPI_FLASH_PerWritePageSize)
  {
     NumByteToWrite = SPI_FLASH_PerWritePageSize;
     //printf("\n\r Err: SPI_FLASH_PageWrite too large!");
  }

  /* while there is data to be written on the FLASH */
  while (NumByteToWrite--)
  {
    /* Send the current byte */
    SPI_FLASH_SendByte(*pBuffer);
    /* Point on the next byte to be written */
    pBuffer++;
  }

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);

  /* Wait the end of Flash writing */
  SPI_FLASH_WaitForWriteEnd(index_chip);
}

/*******************************************************************************
* Function Name  : SPI_FLASH_BufferWrite
* Description    : Writes block of data to the FLASH. In this function, the
*                  number of WRITE cycles are reduced, using Page WRITE sequence.
* Input          : - pBuffer : pointer to the buffer  containing the data to be
*                    written to the FLASH.
*                  - WriteAddr : FLASH's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the FLASH.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite,unsigned char  index_chip)
{
  u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;

  Addr = WriteAddr % SPI_FLASH_PageSize;
  count = SPI_FLASH_PageSize - Addr;
  NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
  NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;

  if (Addr == 0) /* WriteAddr is SPI_FLASH_PageSize aligned  */
  {
    if (NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
    {
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite,index_chip);
    }
    else /* NumByteToWrite > SPI_FLASH_PageSize */
    {
      while (NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize,index_chip);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;
      }

      SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle,index_chip);
    }
  }
  else /* WriteAddr is not SPI_FLASH_PageSize aligned  */
  {
    if (NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
    {
      if (NumOfSingle > count) /* (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize */
      {
        temp = NumOfSingle - count;

        SPI_FLASH_PageWrite(pBuffer, WriteAddr, count,index_chip);
        WriteAddr +=  count;
        pBuffer += count;

        SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp,index_chip);
      }
      else
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite,index_chip);
      }
    }
    else /* NumByteToWrite > SPI_FLASH_PageSize */
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
      NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;

      SPI_FLASH_PageWrite(pBuffer, WriteAddr, count,index_chip);
      WriteAddr +=  count;
      pBuffer += count;

      while (NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize,index_chip);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;
      }

      if (NumOfSingle != 0)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle,index_chip);
      }
    }
  }
}





void SPI_Flash_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite,unsigned char  index_chip)
{
 	u16 i;  
  SPI_FLASH_WriteEnable(index_chip);                 //SET WEL 
	SPI_FLASH_CS_LOW(index_chip);                           //ʹÄÜÆ÷¼þ   
    SPI_FLASH_SendByte(W25X_PageProgram);      //·¢ËÍдҳÃüÁî   
    SPI_FLASH_SendByte((u8)((WriteAddr)>>16)); //·¢ËÍ24bitµØÖ·    
    SPI_FLASH_SendByte((u8)((WriteAddr)>>8));   
    SPI_FLASH_SendByte((u8)WriteAddr);   
    for(i=0;i<NumByteToWrite;i++){SPI_FLASH_SendByte(pBuffer[i]);}//Ñ­»·Ð´Êý  
SPI_FLASH_CS_HIGH(index_chip);                            //È¡ÏûƬѡ 
	SPI_FLASH_WaitForWriteEnd(index_chip);					   //µÈ´ýдÈë½áÊø
} 
//ÎÞ¼ìÑéдSPI FLASH 
//±ØÐëÈ·±£ËùдµÄµØÖ··¶Î§ÄÚµÄÊý¾ÝÈ«²¿Îª0XFF,·ñÔòÔÚ·Ç0XFF´¦Ð´ÈëµÄÊý¾Ý½«Ê§°Ü!
//¾ßÓÐ×Ô¶¯»»Ò³¹¦ÄÜ 
//ÔÚÖ¸¶¨µØÖ·¿ªÊ¼Ð´ÈëÖ¸¶¨³¤¶ÈµÄÊý¾Ý,µ«ÊÇҪȷ±£µØÖ·²»Ô½½ç!
//pBuffer:Êý¾Ý´æ´¢Çø
//WriteAddr:¿ªÊ¼Ð´ÈëµÄµØÖ·(24bit)
//NumByteToWrite:ҪдÈëµÄ×Ö½ÚÊý(×î´ó65535)
//CHECK OK
void SPI_Flash_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite,unsigned char  index_chip)   
{ 			 		 
	u16 pageremain;	   
	pageremain=256-WriteAddr%256; //µ¥Ò³Ê£ÓàµÄ×Ö½ÚÊý		 	    
	if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//²»´óÓÚ256¸ö×Ö½Ú
	while(1)
	{	   

		
		SPI_Flash_Write_Page(pBuffer,WriteAddr,pageremain,index_chip);
		if(NumByteToWrite==pageremain)break;//дÈë½áÊøÁË
	 	else //NumByteToWrite>pageremain
		{
			pBuffer+=pageremain;
			WriteAddr+=pageremain;	

			NumByteToWrite-=pageremain;			  //¼õÈ¥ÒѾ­Ð´ÈëÁ˵Ä×Ö½ÚÊý
			if(NumByteToWrite>256)pageremain=256; //Ò»´Î¿ÉÒÔдÈë256¸ö×Ö½Ú
			else pageremain=NumByteToWrite; 	  //²»¹»256¸ö×Ö½ÚÁË
		}
	};	    
} 














//дSPI FLASH  
//ÔÚÖ¸¶¨µØÖ·¿ªÊ¼Ð´ÈëÖ¸¶¨³¤¶ÈµÄÊý¾Ý
//¸Ãº¯Êý´ø²Á³ý²Ù×÷!
//pBuffer:Êý¾Ý´æ´¢Çø
//WriteAddr:¿ªÊ¼Ð´ÈëµÄµØÖ·(24bit)
//NumByteToWrite:ҪдÈëµÄ×Ö½ÚÊý(×î´ó65535) £¬Ò»°ãÒ»¸öÇø512Byte,ÕýºÃСÓÚ2¸öSPI_FLASH_BUFµÄ³¤¶È£¬ËùÒÔÎȶ¨£¿£º 		   
u8 SPI_FLASH_BUF[4096];
void SPI_Flash_Write_by_earse_ok(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite,unsigned char  index_chip)   
{ 
	u32 secpos;
	u16 secoff;
	u16 secremain;	   
 	u16 i;  
	
	
	xSemaphoreTake(read_write_locker , portTICK_PERIOD_MS*4000);//·ÀÖ¹¶àÏ̶߳Áд³åÍ»

	writing_or_reading=1;
	
	
	
	
	secpos=WriteAddr/4096;//ÉÈÇøµØÖ· 0~511 for w25x16
	secoff=WriteAddr%4096;//ÔÚÉÈÇøÄ򵀮«ÒÆ
	secremain=4096-secoff;//ÉÈÇøÊ£Óà¿Õ¼ä´óС   
	if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//²»´óÓÚ4096¸ö×Ö½Ú
	while(1) 
	{	
		SPI_FLASH_BufferRead(SPI_FLASH_BUF,secpos*4096,4096,index_chip,1);//¶Á³öÕû¸öÉÈÇøµÄÄÚÈÝ
		for(i=0;i<secremain;i++)//УÑéÊý¾Ý
		{
			if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//ÐèÒª²Á³ý  	  
		}
		if(i<secremain)//ÐèÒª²Á³ý
		{
			SPI_Flash_Erase_SectorOK(secpos,index_chip);//²Á³ýÕâ¸öÉÈÇø
			for(i=0;i<secremain;i++)	   //¸´ÖÆ
			{  
				SPI_FLASH_BUF[i+secoff]=pBuffer[i];	  
			}
			SPI_Flash_Write_NoCheck(SPI_FLASH_BUF,secpos*4096,4096,index_chip);//дÈëÕû¸öÉÈÇø  

		}else SPI_Flash_Write_NoCheck(pBuffer,WriteAddr,secremain,index_chip);//дÒѾ­²Á³ýÁ˵Ä,Ö±½ÓдÈëÉÈÇøÊ£ÓàÇø¼ä. 				   
		if(NumByteToWrite==secremain)break;//дÈë½áÊøÁË
		else//дÈëδ½áÊø
		{
			secpos++;//ÉÈÇøµØÖ·Ôö1
			secoff=0;//Æ«ÒÆÎ»ÖÃΪ0 	 

		   	pBuffer+=secremain;  //Ö¸ÕëÆ«ÒÆ
			WriteAddr+=secremain;//дµØÖ·Æ«ÒÆ	   
		   	NumByteToWrite-=secremain;				//×Ö½ÚÊýµÝ¼õ
			if(NumByteToWrite>4096)secremain=4096;	//ÏÂÒ»¸öÉÈÇø»¹ÊÇд²»Íê
			else secremain=NumByteToWrite;			//ÏÂÒ»¸öÉÈÇø¿ÉÒÔдÍêÁË
		}	 
	};	 


			 xSemaphoreGive(read_write_locker);

	writing_or_reading=0;
	
}




#define W25X_ReadData			0x03 
#define W25X_PageProgram		0x02 
#define FLASH_PAGE_SIZE		256
#define FLASH_SECTOR_SIZE	4096
#define FLASH_SECTOR_COUNT	512
#define FLASH_BLOCK_SIZE	65536
#define FLASH_PAGES_PER_SECTOR	FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE

//Sector Read
 void W25X_Read_Sector(uint32_t nSector, u8* pBuffer,unsigned char  index_chip)
{	
    uint16_t i;
	//ÉÈÇøºÅתΪµØÖ·
	nSector *= FLASH_SECTOR_SIZE;

  SPI_FLASH_CS_LOW(index_chip); 
	SPIx_ReadWriteByte(W25X_ReadData);
	SPIx_ReadWriteByte(((nSector & 0xFFFFFF) >> 16));
	SPIx_ReadWriteByte(((nSector & 0xFFFF) >> 8));
	SPIx_ReadWriteByte(nSector & 0xFF);
	
	for(i=0;i<FLASH_SECTOR_SIZE;i++)
	{	
	  pBuffer[i] = SPIx_ReadWriteByte(0xFF);
	}
  SPI_FLASH_CS_HIGH(index_chip);
	  SPI_FLASH_WaitForWriteEnd(index_chip);
}

//Sector Write
void W25X_Write_Sector(uint32_t nSector, u8* pBuffer,unsigned char  index_chip)
{	
	int i,j;
	//ÉÈÇøºÅתΪµØÖ·
	nSector *= FLASH_SECTOR_SIZE;

	//Ò»¸öÉÈÇøÐèÒª¼¸¸öÒ³
	for(j=0;j<FLASH_PAGES_PER_SECTOR;j++)
	{
		  SPI_FLASH_WriteEnable(index_chip);                  //SET WEL
		 
  SPI_FLASH_CS_LOW(index_chip); 
		SPIx_ReadWriteByte(W25X_PageProgram);
	    SPIx_ReadWriteByte(((nSector & 0xFFFFFF) >> 16));
	    SPIx_ReadWriteByte(((nSector & 0xFFFF) >> 8));
	    SPIx_ReadWriteByte(nSector & 0xFF);
		
		for(i=0;i<FLASH_PAGE_SIZE;i++)								
		SPIx_ReadWriteByte(pBuffer[i]);
				
		pBuffer += FLASH_PAGE_SIZE;
		nSector += FLASH_PAGE_SIZE;

  SPI_FLASH_CS_HIGH(index_chip);
		  SPI_FLASH_WaitForWriteEnd(index_chip);
	}
}



/*

void SPI_FLASH_BufferRead_Piliang(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead,unsigned char  index_chip)
{

  SPI_FLASH_CS_LOW(index_chip);

 
  SPI_FLASH_SendByte(W25X_ReadData);


  SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
 
  SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);

  SPI_FLASH_SendByte(ReadAddr & 0xFF);

	


	
	for(u32 ii=0;ii<NumByteToRead;ii++){
	
	
	SPI_FLASH_BUF[ii]=0xff;

	
	}
	oked_recved=0;
	
	HAL_SPI_TransmitReceive(&hspi,SPI_FLASH_BUF,pBuffer,NumByteToRead, 100);
	
   //HAL_DMA_Start_IT(&hdma_spi6_rx, (uint32_t)SPI6->RXDR, (uint32_t)pBuffer, NumByteToRead);
	
	
	  //HAL_SPI_TransmitReceive_DMA(&hspi,SPI_FLASH_BUF,(u8*) pBuffer, NumByteToRead);

	
	
	//while(oked_recved==0)
		{
		
		
	}

	
  SPI_FLASH_CS_HIGH(index_chip);
}

*/











/*******************************************************************************
* Function Name  : SPI_FLASH_BufferRead
* Description    : Reads a block of data from the FLASH.
* Input          : - pBuffer : pointer to the buffer that receives the data read
*                    from the FLASH.
*                  - ReadAddr : FLASH's internal address to read from.
*                  - NumByteToRead : number of bytes to read from the FLASH.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead,unsigned char  index_chip,u8 inner_read_write_locker)
{
	
	
	if(inner_read_write_locker==0){
	xSemaphoreTake(read_write_locker , portTICK_PERIOD_MS*4000);//·ÀÖ¹¶àÏ̶߳Áд³åÍ»
	}
	
	
	writing_or_reading=1;
	
	
	
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);

  /* Send "Read from Memory " instruction */
  SPI_FLASH_SendByte(W25X_ReadData);

  /* Send ReadAddr high nibble address byte to read from */
  SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
  /* Send ReadAddr medium nibble address byte to read from */
  SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
  /* Send ReadAddr low nibble address byte to read from */
  SPI_FLASH_SendByte(ReadAddr & 0xFF);

  while (NumByteToRead--) /* while there is data to be read */
  {
#ifdef SPI_FLASH_ANALOG
    //SPI_FLASH_SendByte(Dummy_Byte);
    *pBuffer = SPI_FLASH_ReadByte();//Ä£ÄâSPI ¶ÁÈ¡
#else
    /* Read a byte from the FLASH */
    *pBuffer = SPI_FLASH_SendByte(Dummy_Byte);
#endif
    /* Point to the next location where the byte read will be saved */
    pBuffer++;
  }

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);
	
	
	
	if(inner_read_write_locker==0){
			 xSemaphoreGive(read_write_locker);
	}
	writing_or_reading=0;
}

/*******************************************************************************
* Function Name  : SPI_FLASH_ReadID
* Description    : Reads FLASH identification.
* Input          : None
* Output         : None
* Return         : FLASH identification
*******************************************************************************/
u32 SPI_FLASH_ReadID(unsigned char  index_chip)
{
  u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;

  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);

  /* Send "RDID " instruction */
  SPI_FLASH_SendByte(W25X_JedecDeviceID);

  
#ifdef SPI_FLASH_ANALOG
      /* Read a byte from the FLASH */
    //SPI_FLASH_SendByte(Dummy_Byte);
    Temp0 = SPI_FLASH_ReadByte();//Ä£ÄâSPI ¶ÁÈ¡
  
  /* Read a byte from the FLASH */
    //SPI_FLASH_SendByte(Dummy_Byte);
    Temp1 = SPI_FLASH_ReadByte();//Ä£ÄâSPI ¶ÁÈ¡
    
  /* Read a byte from the FLASH */
    //SPI_FLASH_SendByte(Dummy_Byte);
    Temp2 = SPI_FLASH_ReadByte();//Ä£ÄâSPI ¶ÁÈ¡
#else    
  /* Read a byte from the FLASH */
  Temp0 = SPI_FLASH_SendByte(Dummy_Byte);

  
  /* Read a byte from the FLASH */
  Temp1 = SPI_FLASH_SendByte(Dummy_Byte);

    
  /* Read a byte from the FLASH */
  Temp2 = SPI_FLASH_SendByte(Dummy_Byte);
#endif

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);

  Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

  return Temp;
}
/*******************************************************************************
* Function Name  : SPI_FLASH_ReadID
* Description    : Reads FLASH identification.
* Input          : None
* Output         : None
* Return         : FLASH identification
*******************************************************************************/
u32 SPI_FLASH_ReadDeviceID(unsigned char  index_chip)
{
  u32 Temp = 0;

  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);

  /* Send "RDID " instruction */
  SPI_FLASH_SendByte(W25X_DeviceID);
  SPI_FLASH_SendByte(Dummy_Byte);
  SPI_FLASH_SendByte(Dummy_Byte);
  SPI_FLASH_SendByte(Dummy_Byte);
#ifdef  SPI_FLASH_ANALOG
    //SPI_FLASH_SendByte(Dummy_Byte);
    Temp = SPI_FLASH_ReadByte();//Ä£ÄâSPI ¶ÁÈ¡
#else    
  /* Read a byte from the FLASH */
  Temp = SPI_FLASH_SendByte(Dummy_Byte);
#endif
    
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);

  return Temp;
}
/*******************************************************************************
* Function Name  : SPI_FLASH_StartReadSequence
* Description    : Initiates a read data byte (READ) sequence from the Flash.
*                  This is done by driving the /CS line low to select the device,
*                  then the READ instruction is transmitted followed by 3 bytes
*                  address. This function exit and keep the /CS line low, so the
*                  Flash still being selected. With this technique the whole
*                  content of the Flash is read with a single READ instruction.
* Input          : - ReadAddr : FLASH's internal address to read from.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_StartReadSequence(u32 ReadAddr,unsigned char  index_chip)
{
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);

  /* Send "Read from Memory " instruction */
  SPI_FLASH_SendByte(W25X_ReadData);

  /* Send the 24-bit address of the address to read from -----------------------*/
  /* Send ReadAddr high nibble address byte */
  SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
  /* Send ReadAddr medium nibble address byte */
  SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
  /* Send ReadAddr low nibble address byte */
  SPI_FLASH_SendByte(ReadAddr & 0xFF);
}



#ifdef SPI_FLASH_HAL
/*******************************************************************************
* Function Name  : SPI_FLASH_ReadByte
* Description    : Reads a byte from the SPI Flash.
*                  This function must be used only if the Start_Read_Sequence
*                  function has been previously called.
* Input          : None
* Output         : None
* Return         : Byte Read from the SPI Flash.
*******************************************************************************/
u8 SPI_FLASH_ReadByte(void)
{
  return (SPI_FLASH_SendByte(Dummy_Byte));
}

/*******************************************************************************
* Function Name  : SPI_FLASH_SendByte
* Description    : Sends a byte through the SPI interface and return the byte
*                  received from the SPI bus.
* Input          : byte : byte to send.
* Output         : None
* Return         : The value of the received byte.
*******************************************************************************/
u8 SPI_FLASH_SendByte(u8 byte)
{
  /* Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);

  /* Send byte through the SPI1 peripheral */
  SPI_I2S_SendData(SPI2, byte);

  /* Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

  /* Return the byte read from the SPI bus */
  return SPI_I2S_ReceiveData(SPI2);
  
/*
    while(SPI_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
    SPI_SendData(SPI2, byte);
    
    while(SPI_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_ReceiveData(SPI2);
*/  
}

/*******************************************************************************
* Function Name  : SPI_FLASH_SendHalfWord
* Description    : Sends a Half Word through the SPI interface and return the
*                  Half Word received from the SPI bus.
* Input          : Half Word : Half Word to send.
* Output         : None
* Return         : The value of the received Half Word.
*******************************************************************************/
u16 SPI_FLASH_SendHalfWord(u16 HalfWord)
{
  /* Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);

  /* Send Half Word through the SPI1 peripheral */
  SPI_I2S_SendData(SPI2, HalfWord);

  /* Wait to receive a Half Word */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

  /* Return the Half Word read from the SPI bus */
  return SPI_I2S_ReceiveData(SPI2);
}

#else
//Ä£ÄâSPI
/******************************************************************
 - ¹¦ÄÜÃèÊö£ºIOÄ£ÄâSPI£¬·¢ËÍÒ»¸ö×Ö½Ú
 - Á¥ÊôÄ£¿é£º
 - º¯ÊýÊôÐÔ£ºÄÚ²¿
 - ²ÎÊý˵Ã÷£ºdata ÊÇÒª·¢Ë͵Ä×Ö½Ú
 - ·µ»ØËµÃ÷£ºÎÞ·µ»Ø
 - //×¢£º
 ******************************************************************/

void SPI_FLASH_SendByte(u8 byt1e)
{
     SPIx_ReadWriteByte(byt1e);
}

/******************************************************************
 - ¹¦ÄÜÃèÊö£ºIOÄ£ÄâSPI£¬¶Áȡһ¸ö×Ö½Ú
 - Á¥ÊôÄ£¿é£º
 - º¯ÊýÊôÐÔ£ºÄÚ²¿
 - ²ÎÊý˵Ã÷£ºÎÞ
 - ·µ»ØËµÃ÷£º·µ»Ø¶Áµ½µÄ×Ö½Ú
 ******************************************************************/

u8 SPI_FLASH_ReadByte(void) //SPI¶ÁÒ»¸ö×Ö½Ú
{ 
  
	
    
    return  SPIx_ReadWriteByte(0xff);;

}
#endif

/*******************************************************************************
* Function Name  : SPI_FLASH_WriteEnable
* Description    : Enables the write access to the FLASH.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_WriteEnable(unsigned char  index_chip)
{
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);

  /* Send "Write Enable" instruction */
  SPI_FLASH_SendByte(W25X_WriteEnable);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);
}

/*******************************************************************************
* Function Name  : SPI_FLASH_WaitForWriteEnd
* Description    : Polls the status of the Write In Progress (WIP) flag in the
*                  FLASH's status  register  and  loop  until write  opertaion
*                  has completed.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_WaitForWriteEnd(unsigned char  index_chip)
{
  u8 FLASH_Status = 0;

  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);

  /* Send "Read Status Register" instruction */
  SPI_FLASH_SendByte(W25X_ReadStatusReg);

  /* Loop as long as the memory is busy with a write cycle */
  do
  {
	 
	  
#ifdef SPI_FLASH_ANALOG
    //SPI_FLASH_SendByte(Dummy_Byte);
    FLASH_Status = SPI_FLASH_ReadByte();//Ä£ÄâSPI ¶ÁÈ¡
#else
    /* Send a dummy byte to generate the clock needed by the FLASH
    and put the value of the status register in FLASH_Status variable */
    FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);    
#endif
  }
  while ((FLASH_Status & WIP_Flag) == SET); /* Write in progress */

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);
}


//½øÈëµôµçģʽ
void SPI_Flash_PowerDown(unsigned char  index_chip)   
{ 
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);

  /* Send "Power Down" instruction */
  SPI_FLASH_SendByte(W25X_PowerDown);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);
}   

//»½ÐÑ
void SPI_Flash_WAKEUP(unsigned char  index_chip)   
{
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW(index_chip);

  /* Send "Power Down" instruction */
  SPI_FLASH_SendByte(W25X_ReleasePowerDown);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH(index_chip);                   //µÈ´ýTRES1
}   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

net3m33

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值