国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

STM32單片機初學8-SPI flash(W25Q128)數(shù)據(jù)讀寫

這篇具有很好參考價值的文章主要介紹了STM32單片機初學8-SPI flash(W25Q128)數(shù)據(jù)讀寫。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

????????當使用單片機進行項目開發(fā),涉及大量數(shù)據(jù)需要儲存時(例如使用了屏幕作為顯示設備,常常需要存儲圖片、動畫等數(shù)據(jù)),單靠單片機內(nèi)部的Flash往往是不夠用的。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

????????如STM32F103系列,內(nèi)部Flash最多只能達到512KByte,假設要儲存240*240分辨率、64K彩色圖片,只夠存儲4張左右。如果使用外置儲存器,將圖片等其他數(shù)據(jù)放置在外置儲存器,內(nèi)部Flash只儲存程序,就能減小內(nèi)部Flash的需求,降低成本。? ? ?w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32?????????Flash種類有很多,按其制程和制作工藝的不同可分為NOR Flash、NAND?Flash。NAND的串行結構使得其容量很容易做的很大(SD卡、U盤、硬盤大都采用該類Flash),但是其讀取速度卻比不上并行結構的NOR Flash,且可靠性要差些,一旦出現(xiàn)數(shù)據(jù)塊壞點,是不可逆、無法修復的。由于其數(shù)據(jù)存儲原理,F(xiàn)lash在寫入新的數(shù)據(jù)之前,都需要將數(shù)據(jù)地址所在的塊擦除,NOR Flash的擦除速度比NAND慢很多。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

? ? ? ? Flash按其數(shù)據(jù)傳輸方式的不同可分為并口傳輸與串口傳輸。STM32的并口傳輸需使用FSMC接口,雖然其讀寫速度很快,但對于100PIN腳以下的封裝是不帶FSMC功能的。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

?????????所以使用更多的是串口傳輸方式。串口方式一般采用的是SPI通訊。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

????????? W25Q系列Flash是Winbond(臺灣華邦科技)生產(chǎn)的SPI Flash系列,是單片機開發(fā)中比較常用的外置Flash。其支持標準四線SPI、Dual SPI、Quad SPI、QPI,其時鐘頻率分別可達到104MHz、208MHz、416MHz。對于STM32F103系列,其主頻最高72MHz(SPI通信速率最高18Mbps),所以標準SPI就已經(jīng)是足夠F103系列單片機使用了。這里我使用W25Q128FV來講解Flash的使用。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

????????先來了解其引腳定義,上面展示的是SOP8封裝,還有SOP16封裝的,功能都是差不多的。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32????????/CS: Flash的片選引腳。當/CS高時,F(xiàn)lash的串行數(shù)據(jù)輸出(DO或IO0、IO1、IO2、IO3)引腳處于高阻抗,此時設備功耗將處于待機水平(除非正在進行內(nèi)部擦除、程序或寫入狀態(tài)寄存器周期)。當/CS為低電平,F(xiàn)lash將被選中,功耗將增加到活動水平,并且可以向該設備寫入指令和從該設備讀取數(shù)據(jù)。啟動后,/CS必須從高電平轉換到低電平,才能接受新的指令。

????????DO(IO1):DO指數(shù)據(jù)輸出口(Data Out),一般連接到單片機SPI接口的數(shù)據(jù)輸入端,即MISO。IO1是其復用功能,當啟用SPI四位傳輸模式時,該引腳功能為IO1.

????????/WP:寫保護(WP)引腳。可以用來防止狀態(tài)寄存器被寫入。與狀態(tài)寄存器的塊保護(CMP, SEC, TB, BP2, BP1和BPO)位和狀態(tài)寄存器保護(SRP)位一起使用,小到4KB扇區(qū)或整個內(nèi)存陣列都可以被硬件保護。/WP引腳低電平有效。當狀態(tài)寄存器2的QE位設置為Quad I/O時,/WP引腳功能不可用,因為該引腳用于IO2。如果不想使用該功能,可以直接將該引腳接VCC。

????????GND:Flash的供電GND

????????DI:DI指數(shù)據(jù)輸入口(Data In),一般連接到單片機SPI接口的數(shù)據(jù)輸出端,即MOSI。IO0是其復用功能,當啟用SPI四位傳輸模式時,該引腳為IO0

????????CLK:SPI時鐘線。連接至單片機的SPI時鐘接口。

????????/HOLD,/RESET:/HOLD能讓設備主動暫停數(shù)據(jù)傳輸。當/HOLD低時,而/CS低時,DO引腳將處于高阻抗,Dl和CLK引腳上的信號將被忽略。當/HOLD調(diào)高時,設備可以恢復運行。當多個設備共享相同的SPl信號時,/HOLD就能發(fā)揮作用。?/RESET引腳用于設備復位。注意,如果在寫入數(shù)據(jù)時復位,可能會造成數(shù)據(jù)丟失。所以如果不需要給Flash復位,該引腳常常直接與VCC相接。

????????VCC:Flash供電電源3.3V。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

?????????不管何種存儲器,在進行數(shù)據(jù)讀寫時都需要知道數(shù)據(jù)的地址。數(shù)據(jù)存儲在寄存器中,所以數(shù)據(jù)的地址即寄存器地址。我們來看看W25Q128的內(nèi)部原理圖。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

????????其內(nèi)部是由數(shù)據(jù)存儲單元和各種控制器組成。

????????存儲單元的最小單位為一個寄存器,每個寄存器可存儲1個字節(jié)的數(shù)據(jù)。

????????每256個寄存器組成一頁(Page),也就是一頁能存儲256Byte數(shù)據(jù),

????????每16頁組成一個扇區(qū)(Sector),一個扇區(qū)能儲存16x256=4096Byte數(shù)據(jù)(近似4KB)。比如扇區(qū)0的數(shù)據(jù)地址范圍為000000 h-000FFF h。

????????每16個扇區(qū)又組成一個塊(Block),一個塊能儲存4096x16=65536Byte數(shù)據(jù)(近似64K)。例如塊0的數(shù)據(jù)地址范圍為000000 h-00FFFF h 。

?????????整個存儲單元共256個塊,所以其總存儲容量為256x65536=16777216Byte數(shù)據(jù),近似為16MByte。數(shù)據(jù)地址范圍為000000 h-FFFFFF h。


????????不管何種外設,都是通過發(fā)送命令與數(shù)據(jù)來控制的。Flash也不例外,所以需要知道如何使用Flash,只需在其技術手冊上找到其命令表即可。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

?????????可用的命令有很多,但常用的就一部分。

????????現(xiàn)在我們來講解程序里如何實現(xiàn)STM32F103讀寫SPI Flash的數(shù)據(jù)。

????????這里我使用的是SPI2,硬件連接如下。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

????????再來看程序部分:

1.SPI2初始化。為了將讀出來的數(shù)據(jù)顯示出來,這里我使用串口將數(shù)據(jù)傳輸?shù)诫娔X上。所以對usart1也初始化。

void SPI2_UserInit(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能GPIOB的時鐘

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;    //PA13為SCK時鐘,PA15為MISO
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			//速度50MHz
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;			//復用推挽輸出
  GPIO_Init(GPIOB, &GPIO_InitStructure);
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;					//PA14為MISO
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			    //速度50MHz
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;			//浮空輸入
  GPIO_Init(GPIOB, &GPIO_InitStructure);
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;					//PA12為片選
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			    //速度50MHz
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;				//復用推挽輸出
  GPIO_Init(GPIOB, &GPIO_InitStructure);
 
  SPI_InitTypeDef SPI_InitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);		     //使能SPI時鐘
	
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//設置雙向雙線全雙工
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;						//設置為SPI主站
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;					//設置為8位幀結構
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;					//串行時鐘的穩(wěn)態(tài)為時鐘高
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;		//位捕獲的時鐘活動沿為第1個時鐘沿
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;					//指定NSS信號由軟件控制
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;    //波特率預分頻值
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;					//數(shù)據(jù)位從MSB開始
  SPI_InitStructure.SPI_CRCPolynomial = 7;								//CRC檢驗
  SPI_Init(SPI2, &SPI_InitStructure);							//按以上設置初始化SPI2
 
  SPI_Cmd(SPI2, ENABLE);							//使能SPI2
  GPIO_SetBits(GPIOB,GPIO_Pin_12);	            	//CS置高
}

void USART1_Userinit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;    //PA9為USART1_TX將這個GPIO初始化
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			//速度50MHz
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;				//復用推挽輸出
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;	//PA10為USART_RX,將這個GPIO初始化
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			//速度50MHz
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;		//浮空輸入
	GPIO_Init(GPIOA, &GPIO_InitStructure);
		
	USART_InitTypeDef USART_InitStructure;						//定義USART配置結構體
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);		//打開USART1時鐘
	
	USART_InitStructure.USART_BaudRate = 115200; 					//波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;		//數(shù)據(jù)幀位數(shù) 
	USART_InitStructure.USART_StopBits = USART_StopBits_1; 			//停止位數(shù)目
	USART_InitStructure.USART_Parity = USART_Parity_No; 			//奇偶模式(USART_Parity_No 無,USART_Parity_Even 偶SART_Parity_Odd奇)
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 	//硬件流控制模式
	USART_InitStructure.USART_Mode = USART_Mode_Tx| USART_Mode_Rx; 									//發(fā)送、接收使能
	USART_Init(USART1, &USART_InitStructure);											//初始化
	USART_Cmd(USART1,ENABLE);																			//使能USART1串口	
	
	USART_ITConfig(USART1,USART_IT_RXNE, ENABLE);		//使能USART1接收中斷
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;				//中斷通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;	//搶占優(yōu)先級
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;				//子優(yōu)先級
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能中斷
	NVIC_Init(&NVIC_InitStructure);									//初始化中斷
	
}

2.發(fā)送命令或者讀寫數(shù)據(jù)都是通過最基本的發(fā)送數(shù)據(jù)、接受數(shù)據(jù)函數(shù)來實現(xiàn)。為了不出現(xiàn)數(shù)據(jù)丟失,每次發(fā)送數(shù)據(jù)前都需要判斷上次發(fā)送的數(shù)據(jù)是否已經(jīng)發(fā)送玩,這可以通過相關標志位來判斷;同樣,為了不出現(xiàn)數(shù)據(jù)重復,每次接收數(shù)據(jù)前都要判斷接收緩存區(qū)是否為空。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

void Flash_WriteData8(u8 Data)	//寫8位數(shù)據(jù)(1個字節(jié))
{
	u8 Wait=0;	
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET&&Wait<20) //檢查指定的SPI標志位設置與否:發(fā)送緩存空標志位,RESET表示正在發(fā)送數(shù)據(jù)
	{
		Wait++;//循環(huán)計數(shù)200,計數(shù)200此(大概20us),不管是否標志位為空,都退出等待
	}
	SPI_I2S_ClearFlag(SPI2, SPI_I2S_FLAG_TXE);    //清除發(fā)送完成標志位
	SPI_I2S_SendData(SPI2,Data);				//發(fā)送Data
	
}

u8 Flash_ReadData( )														//讀一個字節(jié)
{		
	u8 Wait=0;
	SPI_I2S_SendData(SPI2,0xff);									//發(fā)送0x00,產(chǎn)生時鐘信號,用來接收數(shù)據(jù),也可以發(fā)送其他無響應的命令
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET&&Wait<200) //檢查指定的SPI標志位設置與否:接受緩存非空標志位
	{
		Wait++;	
	}	
	SPI_I2S_ClearFlag(SPI2, SPI_I2S_FLAG_RXNE);	//清除標志位
	return SPI_I2S_ReceiveData(SPI2);						 //返回通過SPI2最近接收的數(shù)據(jù)			
}

u8 Flash_WriteReadByte(u8 Data)		//讀寫函數(shù)
{
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //檢查指定的SPI標志位設置與否:發(fā)送緩存空標志位,RESET表示正在發(fā)送數(shù)據(jù)
	{

	}
	SPI_I2S_SendData(SPI2,Data);				//發(fā)送Data
	
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //檢查指定的SPI標志位設置與否:接受緩存非空標志位
	{

	}	
	return SPI_I2S_ReceiveData(SPI2);						 //返回通過SPIx最近接收的數(shù)據(jù)	
}

????????需要注意:在接受數(shù)據(jù)的函數(shù)中,之所以在SPI_I2S_ReceiveData(SPI2)函數(shù)之前要使用SPI_I2S_SendData(SPI2,0xff)函數(shù),是為了產(chǎn)生時鐘信號。

????????SPI采用的是主從通信結構,時鐘信號只能由主設備產(chǎn)生,主設備發(fā)送數(shù)據(jù)的過程中會產(chǎn)生時鐘信號,但是從設備發(fā)送數(shù)據(jù)時并不能自己產(chǎn)生時鐘信號,所以就無法將數(shù)據(jù)一位一位發(fā)送出去(同步通信必須依靠時鐘信號保持時序一致),那就只能依靠主設備產(chǎn)生時鐘信號。主設備發(fā)送的0xFF,對從設備來說,是無效的數(shù)據(jù),不會對該數(shù)據(jù)做出響應,但是主設備發(fā)送0xFF這個數(shù)據(jù)的時候,產(chǎn)生了時鐘信號,所以從設備就依靠這段時鐘信號,將數(shù)據(jù)發(fā)送給了主設備,主設備接受會暫存在接收緩存寄存器中,等接受到新的數(shù)據(jù)自動更新緩存器。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32

?????????具體的通信時序可查閱W25Q128的技術手冊(W25Q128FV_PDF_數(shù)據(jù)手冊_Datasheet),這里就不一一列舉了。

3.把W25Q128常用的命令封裝成函數(shù),只要調(diào)用對應的函數(shù),就能實現(xiàn)命令的發(fā)送與數(shù)據(jù)的讀寫

#define Flash_CS_H() GPIO_SetBits(GPIOB,GPIO_Pin_12)		//Flash 片選信號
#define Flash_CS_L() GPIO_ResetBits(GPIOB,GPIO_Pin_12)      //低電平選中,高電平取消選中

/*****W25Q128常用命令定義*****/
#define W25X_WriteEnable		0x06 		//寫使能
#define W25X_WriteDisable		0x04 		//寫失能
#define W25X_ReadStatusReg		0x05 		//讀控制寄存器
#define W25X_WriteStatusReg		0x01 		//寫控制寄存器
#define W25X_ReadData			0x03 		//寫數(shù)據(jù)
#define W25X_FastReadData		0x0B 		//快速寫數(shù)據(jù)
#define W25X_FastReadDual		0x3B 		//
#define W25X_PageProgram		0x02 		//頁編程
#define W25X_BlockErase32		0x52 		//32K塊擦除
#define W25X_BlockErase64		0xD8 		//64K塊擦除
#define W25X_SectorErase		0x20 		//4k扇區(qū)擦除
#define W25X_ChipErase			0xC7 		//整片擦除
#define W25X_PowerDown			0xB9 		//
#define W25X_ReleasePowerDown	0xAB 	
#define W25X_DeviceID			0xAB 		//讀設備ID
#define W25X_ManufactDeviceID	0x90 
#define W25X_JedecDeviceID		0x9F		//讀取JEDECID

void Flash_WriteEnable(void)   				//使能寫入
{ 
	Flash_CS_L();
	Flash_WriteReadByte(W25X_WriteEnable); 		//發(fā)送寫使能
	Flash_CS_H();
} 
 

void Flash_WriteDisable(void)  		 		//禁止寫入
{  	
	Flash_CS_L();
	Flash_WriteReadByte(W25X_WriteDisable); 	 //發(fā)送寫禁止指令  
	Flash_CS_H();	
}


 /**
  * @brief  等待WIP(BUSY)標志被置0,即等待到FLASH內(nèi)部數(shù)據(jù)寫入完畢
  * @param  none
  * @retval none
  */
void SPI_FLASH_WaitBusy(void)
{
	u8 FLASH_Status = 0;
  
	Flash_CS_L();		
	Flash_WriteReadByte(W25X_ReadStatusReg1); 	//發(fā)送讀取狀態(tài)寄存器命令  
	do
	{
		FLASH_Status=Flash_WriteReadByte(0xff); 		
	}
	while ((FLASH_Status & 0x01) == 1);  		//判斷是否正忙
	Flash_CS_H();		
}


/******************基本功能*****************/
/************讀Flash狀態(tài)寄存器1************/

u8 Flash_ReadSR1(void)   					//讀狀態(tài)寄存器1(busy時也可讀)
{  
	u8 Byte;
	Flash_CS_L();								//CS選中
	Flash_WriteReadByte(W25X_ReadStatusReg1); 	//發(fā)送讀取狀態(tài)寄存器命令    
	Byte=Flash_WriteReadByte(0xff); 			//讀取一個字節(jié) 
	Flash_CS_H();								//CS取消選中
	return Byte;   
} 

u8 Flash_ReadSR2(void)   					//讀狀態(tài)寄存器2(busy時也可讀)
{  
	u8 Byte;
	Flash_CS_L();							//CS選中
	Flash_WriteReadByte(W25X_ReadStatusReg2); 	//發(fā)送讀取狀態(tài)寄存器命令    
	Byte=Flash_WriteReadByte(0xff); 					//讀取一個字節(jié) 
	Flash_CS_H();
	return Byte;   
}

u8 Flash_ReadSR3(void)   					//讀狀態(tài)寄存器3(busy時也可讀)
{  
	u8 Byte;
	Flash_CS_L();							//CS選中
	Flash_WriteReadByte(W25X_ReadStatusReg3); 	//發(fā)送讀取狀態(tài)寄存器命令    
	Byte=Flash_WriteReadByte(0xff); 					//讀取一個字節(jié) 
	Flash_CS_H();
	return Byte;   
}

void Flash_WriteSR1(u8 Sr)   	//寫入
{   
	Flash_WriteEnable();
	Flash_CS_L();
	Flash_WriteReadByte(W25X_WriteStatusReg);	//發(fā)送寫狀態(tài)寄存器命令    
	Flash_WriteReadByte(Sr);               		//寫入一個字節(jié) 
	Flash_CS_H();
}   

void Flash_WriteSR2(u8 Sr)   
{   
	Flash_WriteEnable();
	Flash_CS_L();	
	Flash_WriteReadByte(W25X_WriteStatusReg2);	//發(fā)送寫狀態(tài)寄存器命令    
	Flash_WriteReadByte(Sr);               		//寫入一個字節(jié) 	
	Flash_CS_H();
}   

void Flash_WriteSR3(u8 Sr)   
{   
	Flash_WriteEnable();
	Flash_CS_L();
	Flash_WriteReadByte(W25X_WriteStatusReg3);	//發(fā)送寫狀態(tài)寄存器命令    
	Flash_WriteReadByte(Sr);               		//寫入一個字節(jié) 
	Flash_CS_H();	
}   



u16 Flash_ReadID(void)				//讀取設備ID(16位JEDEC assigned Manufacturer ID )
{
	u16 Temp ;	 
	u8 TempL,TempH;	
	Flash_CS_L();
	Flash_WriteReadByte(W25X_ManufactDeviceID);	//發(fā)送讀取ID命令
	Flash_WriteReadByte(0x00);					//指令通過將/CS引腳壓低并移動指令代碼“90h”和24位地址000000h來啟動。			
	Flash_WriteReadByte(0x00);							
	Flash_WriteReadByte(0x00);								
	TempH=Flash_WriteReadByte(0xff);			//接收高8位
	TempL=Flash_WriteReadByte(0xff);			//接收高8位
	Flash_CS_H();
	Temp=TempH;
	Temp<<=8;									//左移8位
	Temp|=TempL;								//高8位與低8位合并成16位(與運算后賦值)
	return Temp;
}


void Flash_ReadSector(u32 ReadAddr)  //讀一個扇區(qū)
{
	u16 i; 
	Flash_CS_L();	
	Flash_WriteReadByte(W25X_ReadData);         //發(fā)送讀取命令 
	while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET)//判斷發(fā)送緩存區(qū)是否為空
	{
		
	}
	Flash_WriteReadByte((u8)((ReadAddr)>>16));  	//發(fā)送24bit地址  
	while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET)//判斷發(fā)送緩存區(qū)是否為空
	{
		
	}	
	Flash_WriteReadByte((u8)((ReadAddr)>>8));
	while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET)//判斷發(fā)送緩存區(qū)是否為空
	{
		
	}	
	Flash_WriteReadByte((u8)ReadAddr);   
	for(i=0;i<4096;i++)						//一個扇區(qū)4096個Byte
	{ 
		FlashSector_Buffer[i]=Flash_WriteReadByte(0xff);   	//循環(huán)讀取每個字節(jié)存在 扇區(qū)緩存中
	}	
	Flash_CS_H();
}

void Flash_ReadPage(u32 ReadAddr)  //讀一頁
{
	u16 i; 
	while((Flash_ReadSR1()&0x00)==0x01);  	// 等待BUSY位清空(等待擦除完成)
	{
		
	}
	Flash_CS_L();	
	Flash_WriteReadByte(W25X_ReadData);         	//發(fā)送讀取命令   
	Flash_WriteReadByte((u8)((ReadAddr)>>16));  	//發(fā)送24bit地址    
	Flash_WriteReadByte((u8)((ReadAddr)>>8));   
	Flash_WriteReadByte((u8)ReadAddr);   
	for(i=0;i<256;i++)				//一個頁256個Byte
	{ 
     FlashPage_Buffer[i]=Flash_WriteReadByte(0xff);   	//循環(huán)讀取每個字節(jié)存在 扇區(qū)緩存中
	}	
	Flash_CS_H();
}


void Flash_EraseSector(u32 Dst_Addr)   		//擦除扇區(qū)(150ms左右)
{  
	Flash_WriteEnable();          //在設備接受扇區(qū)擦除指令(狀態(tài)寄存器位WEL必須等于1)之前,必須執(zhí)行Write Enable指令。	
	while((Flash_ReadSR1()&0x02)==0x00);  	// 等待BUSY位清空(等待擦除完成)
	{
		
	}
	Flash_CS_L();
	Flash_WriteReadByte(W25X_SectorErase);      	//發(fā)送扇區(qū)擦除指令 
	Flash_WriteReadByte((u8)((Dst_Addr)>>16));  	//發(fā)送24bit地址    
	Flash_WriteReadByte((u8)((Dst_Addr)>>8));   
	Flash_WriteReadByte((u8)Dst_Addr);
	Delay_us(1);
	Flash_CS_H();							//在最后一個字節(jié)的第8位被鎖存之后,/CS引腳必須置高。否則扇區(qū)擦除指令不執(zhí)行
	while((Flash_ReadSR1()&0x01)==0x01);  	// 等待BUSY位清空(等待擦除完成)
	{
		Delay_us(1);
	}
} 

void Flash_EraseChip(void)   		//整片擦除(4s左右)
{  
	Flash_WriteEnable();          //在設備接受扇區(qū)擦除指令(狀態(tài)寄存器位WEL必須等于1)之前,必須執(zhí)行Write Enable指令。	
	Delay_us(10);
	Flash_CS_L();
	Flash_WriteReadByte(W25X_ChipErase);      	//發(fā)送整片擦除指令 
	Flash_CS_H();							//在最后一個字節(jié)的第8位被鎖存之后,/CS引腳必須置高。否則擦除指令不執(zhí)行
	while((Flash_ReadSR1()&0x01)==0x01);  	// 等待BUSY位清空(等待擦除完成)
	{
		//Sr=Flash_ReadSR1();
		Delay_us(1);
	}
}

void Flash_WritePage(u32 WriteAddr)					//寫一頁(每次寫入的最大數(shù)量為1頁)
{
	u16 i; 
	Flash_WriteEnable(); 
	while((Flash_ReadSR1()&0x01)==0x01);  	// 等待BUSY位清空(等待擦除完成)
	{
	
	}
	Flash_CS_L();
	Flash_WriteReadByte(W25X_PageProgram);      	//發(fā)送寫頁命令   
	Flash_WriteReadByte((u8)((WriteAddr)>>16)); 	//發(fā)送24bit地址    
	Flash_WriteReadByte((u8)((WriteAddr)>>8));   
	Flash_WriteReadByte((u8)WriteAddr);   
	for(i=0;i<256;i++)
	{
		Flash_WriteReadByte(FlashPage_Buffer[i]);
	} 	
	Flash_CS_H();
	while((Flash_ReadSR1()&0x01)==0x01);  	// 等待BUSY位清空(等待擦除完成)
	{
	
	}
}


void Flash_WriteReadBytes(u32 WriteAddr,u8 NumByte)		//寫入多個字節(jié)(不大于256)
{
	u8 i;
	Flash_CS_L();
	Flash_WriteReadByte(W25X_PageProgram);      	//發(fā)送寫頁命令   
	Flash_WriteReadByte((u8)((WriteAddr)>>16)); 	//發(fā)送24bit地址    
	Flash_WriteReadByte((u8)((WriteAddr)>>8));   
	Flash_WriteReadByte((u8)WriteAddr);   
	for(i=0;i<NumByte;i++)
	{
		Flash_WriteReadByte(FlashPage_Buffer[i]);
	} 
	Flash_CS_H();
}


u16 Flash_Init(void)			//SPI Flash初始化
{
	u16 ID;
	Flash_CS_L();
	Flash_WriteReadByte(W25X_ReleasePowerDown);	//退出休眠
	Flash_CS_H();
	ID=Flash_ReadID();
	return ID;
}

4.主函數(shù)。先讀取設備ID,然后將數(shù)組ARR1的數(shù)據(jù)寫入Flash的扇區(qū)0,再將扇區(qū)0的數(shù)據(jù)讀取出來放在數(shù)組ARR2中,通過串口將ARR2的數(shù)據(jù)顯示到電腦(串口調(diào)試助手)。

#include<stm32f10x.h>

u8 ARR1[10]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A};//隨意填入幾個元素,后面將其元素寫入Flash中
u8 ARR2[10];    //后面將Flash的數(shù)據(jù)讀出來,復制到該數(shù)組中

void USART_SendDatatoUSB( char ASCII[])    //串口發(fā)送字符串函數(shù)
{
	u8 i,j,Wait;
	for(i=0;i<12;i++)
	{
		u8 Wait=0;				 	
		while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET&&Wait<200) 
		{
			Wait++;//循環(huán)計數(shù)200,計數(shù)200此(大概20us),不管是否標志位為空,都退出等待
		}
		USART_ClearFlag(USART1,USART_FLAG_TC);
		j=ASCII[i];
		USART_SendData(USART1,j);
	}
	Wait=0;
	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET&&Wait<200) 
	{
		Wait++;//循環(huán)計數(shù)200,計數(shù)200此(大概20us),不管是否標志位為空,都退出等待
	}
	USART_ClearFlag(USART1,USART_FLAG_TC);
	USART_SendData(USART1,10);	//換行	
}

int main()
{
    SPI2_UserInit();			//SPI2初始化----控制SPI Flash
    USART1_Userinit();			//USART1初始化--控制串口CH340
    
    Flash_Write_Enable();    //Flash寫使能
    USART_SendDatatoUSB( "Flash:ID")
	
	Data=Flash_ReadID();    //讀取ID(16位)
	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
    {

     }
	USART_SendData(USART1,(Data>>16)&0xFF);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
    {

     }
	USART_SendData(USART1,(Data>>8)&0xFF);

	Flash_EraseSector(0x000000);        //擦除扇區(qū)
    USART_SendDatatoUSB( "扇區(qū)擦除完成");
    Flash_WritePage(0x000000,10);        //寫入數(shù)據(jù)
    USART_SendDatatoUSB( "數(shù)據(jù)寫入成功");
    
    Flash_ReadSector(0x000000)  //讀數(shù)據(jù)
    USART_SendDatatoUSB( "數(shù)據(jù)讀取成功");
    

	for(i=0;i<10;i++)
	{
		u8 Wait=0;				 	
		while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET&&Wait<200) //檢查指定的SPI標志位設置與否:發(fā)送緩存空標志位,RESET表示正在發(fā)送數(shù)據(jù)
		{
			Wait++;//循環(huán)計數(shù)200,計數(shù)200此(大概20us),不管是否標志位為空,都退出等待
		}
		USART_ClearFlag(USART1,USART_FLAG_TC);
		j=ARR2[i];
		USART_SendData(USART1,j);
	}
}

最后接收到數(shù)據(jù)如下。

w25q128寫保護功能是控制wp電平實現(xiàn)嗎,單片機,stm32,嵌入式硬件,單片機,stm32文章來源地址http://www.zghlxwxcb.cn/news/detail-780357.html

到了這里,關于STM32單片機初學8-SPI flash(W25Q128)數(shù)據(jù)讀寫的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • STM32—SPI詳解入門(使用SPI通訊讀寫W25Q128模塊)

    STM32—SPI詳解入門(使用SPI通訊讀寫W25Q128模塊)

    目錄 一、SPI是什么 二、SPI物理架構 三、SPI工作原理 四、SPI工作模式 五、SPI相關寄存器介紹 六、SPI用到的結構體與函數(shù) 1.結構體 2.函數(shù) 七、W25Q128芯片 1.W25Q128介紹 2.W25Q128存儲架構 3.W25Q128常用指令 4.W25Q128狀態(tài)寄存器 5.W25Q128常見操作流程 八、實驗(使用SPI通訊讀寫W25Q128模塊

    2024年02月14日
    瀏覽(16)
  • 初學者入門:認識STM32單片機

    初學者入門:認識STM32單片機

    本教程含有較多專業(yè)詞匯,大部分時候,不完全理解并不影響繼續(xù)往下閱讀,大家只需要了解大致的概念即可。當然,也鼓勵大家多查百度和多問chatgpt,讓自己學會的更多。 什么是單片機? 單片機,就是把中央處理器CPU、存儲器、等計算機的功能部件,和定時器、I/0(輸入

    2024年02月07日
    瀏覽(27)
  • STM32F4單片機內(nèi)部FLASH編程時間

    STM32F4單片機內(nèi)部FLASH編程時間

    單片機內(nèi)部的flash除了存儲固件以外,經(jīng)常將其分為多個區(qū)域,用來存儲一些參數(shù)或存儲OTA升級等待更新的固件,這時就會涉及單片機內(nèi)部flash的編程和擦除操作。STM32同系列的單片機內(nèi)部flash特性和扇區(qū)大小都不太一樣,以下基于STM32F407VET6此型號進行簡單介紹。 STM32F4xx中文參

    2024年02月03日
    瀏覽(30)
  • 使用stm32的模擬spi讀取w25q128讀取設備ID時一直出現(xiàn)0xFF

    使用stm32的模擬spi讀取w25q128讀取設備ID時一直出現(xiàn)0xFF

    由于公司的電路是前輩畫的,只能使用模擬spi中如圖所示 ? 上圖是stm32所對應的引腳 ?上圖是w25q128的引腳 當讀取的時候ID號一直是0xffff,在網(wǎng)上查了各種方法都試過了都不行,我這個情況稍微特殊,就是使用了PB3、PB4這兩個引腳上電復位默認是作為調(diào)試端口使用的。所以得先

    2024年02月04日
    瀏覽(27)
  • STM32單片機初學4-IIC通信(軟件模擬)

    STM32單片機初學4-IIC通信(軟件模擬)

    IIC ( Inter-Integrated Circuit )又稱I2C(習慣讀“I方C”),是 IIC Bus簡稱,中文名為 集成電路總線 ,它是一種串行通信總線,使用多主從架構,由飛利浦公司在1980年代為了讓主板、嵌入式系統(tǒng)或手機用以連接低速周邊設備而發(fā)展。適用于IC間的短距離數(shù)據(jù)傳輸。 最初的IIC通信速

    2024年02月05日
    瀏覽(102)
  • 使用STM32CubeProgrammer工具讀取單片機Flash數(shù)據(jù)讀取

    使用STM32CubeProgrammer工具讀取單片機Flash數(shù)據(jù)讀取

    本文主要介紹,如何使用STM32CubeProgrammer工具讀取和寫入單片機Flash內(nèi)部的數(shù)據(jù),方便調(diào)試使用。 2.1 連接Stlink和單片機,點擊“connect”進行連接 2.2 讀取固定長度的數(shù)據(jù) 根據(jù)程序的大小,設置需要讀取的字節(jié)數(shù),如下圖所示。點擊“read”將單片機Flash中的數(shù)據(jù)讀取到STM32Cube

    2024年02月12日
    瀏覽(81)
  • STM32單片機Flash不擦除直寫案例分析

    STM32單片機Flash不擦除直寫案例分析

    產(chǎn)品跳閘前需保存致使產(chǎn)品動作的故障類型和具體的故障分析數(shù)據(jù),并在產(chǎn)品二次上電后讀取故障類型,進行相應指示;之后清除故障類型的相關Flash,但故障分析數(shù)據(jù)仍保存,以便后續(xù)讀出分析。然而,F(xiàn)lash扇區(qū)擦除時間較長,會影響程序正常運行、判斷。 Flash的編程原理都

    2024年02月16日
    瀏覽(24)
  • STM32單片機初學5-IIC通信驅動OLED屏幕

    STM32單片機初學5-IIC通信驅動OLED屏幕

    在我上篇文章(STM32-軟件模擬IIC通信)講解了軟件模擬IIC通信。這篇文章詳將細講解利用軟件模擬IIC來控制0.96寸的OLED屏幕(如下圖),使其顯示字符串。本文將不再對IIC通信原理做詳細講解,所以對IIC通信原理不熟悉的話可以參考我上篇文章(點擊上面的鏈接直接跳轉)。

    2023年04月10日
    瀏覽(90)
  • 初學stm32單片機可以做什么簡單的小作品?

    初學stm32單片機可以做什么簡單的小作品?

    已從事單片機開發(fā)十幾年,剛開始接觸單片機時,感覺挺有意思。 可以用自己的思維寫程序,控制硬件去實現(xiàn)一些智能化的操作。 剛點亮第一個LED,就開始幻想以后能做任何自己想要的產(chǎn)品,那感覺多爽! 但是你會發(fā)現(xiàn)學完51單片機、或者STM32單片機以后,還是啥也做不出來

    2024年02月02日
    瀏覽(19)
  • 【STM32】SPI初步使用 讀寫FLASH W25Q64

    【STM32】SPI初步使用 讀寫FLASH W25Q64

    (1) SS( Slave Select):從設備選擇信號線,常稱為片選信號線,每個從設備都有獨立的這一條 NSS 信號線,當主機要選擇從設備時,把該從設備的 NSS 信號線設置為低電平,該從設備即被選中,即片選有效,接著主機開始與被選中的從設備進行 SPI通訊。所以 SPI通訊以 NSS 線置低電

    2024年02月10日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包