19、SPI 和 SST25VF016B
一、SPI總線
?
1、SPI簡介
SPI,是Serial Peripheral interface的縮寫,顧名思義就是串行外圍設備接口。是Motorola首先在其MC68HCXX系列處理器上定義的。SPI接口主要應用在 EEPROM,FLASH,實時時鐘,AD轉換器,還有數字信號處理器和數字信號解碼器之間。SPI,是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上只占用四根線,節約了芯片的管腳,同時為PCB的布局上節省空間,提供方便,正是出于這種簡單易用的特性,現在越來越多的芯片集成了這種通信協議。
?
2、SPI特征
● 3線全雙工同步傳輸
● 8或16位傳輸幀格式選擇
● 主或從操作,支持多主模式
● 8個主模式波特率預分頻系數(最大為fPCLK/2)
● 主模式和從模式下均可以由軟件或硬件進行NSS管理:主/從操作模式的動態改變
● 可編程的時鐘極性和相位
● 可編程的數據順序,MSB在前或LSB在前
● 可觸發中斷的專用發送和接收標志
● SPI總線忙狀態標志
● 支持可靠通信的硬件CRC
● 可觸發中斷的主模式故障、過載以及CRC錯誤標志
● 支持DMA功能的1字節發送和接收緩沖器:產生發送和接受請求
?
3、SPI工作模式
SPI通信中可作為從機也可以作為主機,這取決于硬件設計和軟件設置。
當器件作為主機時,使用一個IO引腳拉低相應從機的選擇引腳(NSS),傳輸的起始由主機發送數據來啟動,時鐘(SCK)信號由主機產生。通過MOSI發送數據,同時通過MISO引腳接收從機發出的數據。
?當器件作為從機時,傳輸在從機選擇引腳(NSS)被主機拉低后開始,接收主機輸出的時鐘信號,在讀取主機數據的同時通過MISO引腳輸出數據。
?
?
4、SPI框圖
?
?
?
5、通常SPI通過4個引腳與外部器件相連:
● MISO:主設備輸入/從設備輸出引腳。該引腳在從模式下發送數據,在主模式下接收數據。
● MOSI:主設備輸出/從設備輸入引腳。該引腳在主模式下發送數據,在從模式下接收數據。
● SCK: 串口時鐘,作為主設備的輸出,從設備的輸入。
● NSS: 從設備選擇。這是一個可選的引腳,用來選擇主/從設備。它的功能是用來作為“片選引腳”,讓主設備可以單獨地與特定從設備通訊,避免???????? 數據線上的沖突。從設備的NSS引腳可以由主設備的一個標準I/O引腳來驅動。
?
6、(NSS)輸出管理
? 對于每個SPI的NSS可以輸入,也可以輸出。所謂輸入,就是NSS的電平信號給自己,所謂輸出,就是將NSS的電平信號發送出去,給從機。配置為輸出,還是不輸出,我們可以通過SPI_CR2寄存器的SSOE位。當SSOE=1時,并且SPI處于主模式控制時(MSTR=1),NSS就輸出低電平,也就是拉低,因此當其他SPI設備的NSS引腳與它相連,必然接收到低電平,則片選成功,都成為從設備了。
?
?
7、?(NSS)輸入管理
NSS軟件模式:?
?1.SPI主機:
???? 需要設置SPI_CR1寄存器的SSM=1和SSI=1,SSM=1是為了使能軟件管理,NSS有內部和外部引腳。這時候外部引腳留作他用(可以用來作為GPIO驅動從設備的片選信號)。內部NSS引腳電平則通過SPI_CRL寄存器的SSI位來驅動。SSI=1是為了使NSS內電平為高電平。為什么主設備的內部NSS電平要為1呢?
??? STM32手冊上說,要保持MSTR=1和SPE=1,也就是說要保持主機模式,只有NSS接到高電平信號時,這兩位才能保持置‘1’。
2.SPI從機:?????? NSS引腳在完成字節傳輸之前必須連接到一個低電平信號。在軟件模式下,則需要設置SPI_CR1寄存器的SSM=1(軟件管理使能)和SSI=0.
?NSS硬件模式:
??? 對于主機,我們的NSS可以直接接到高電平.對于從機,NSS接低就可以。
?
?
8、單主和單從應用
?
?
9、時鐘信號的相位和極性
?SPI_CR寄存器的CPOL和CPHA位,能夠組合成四種可能的時序關系。CPOL(時鐘極性)位控制在沒有數據傳輸時時鐘的空閑狀態電平,此位對主模式和從模式下的設備都有效。如果CPOL被清’0’,SCK引腳在空閑狀態保持低電平;如果CPOL被置’1’,SCK引腳在空閑狀態保持高電平。如果CPHA(時鐘相位)位被置’1’,SCK時鐘的第二個邊沿(CPOL位為0時就是下降沿,CPOL位為’1’時就是上升沿)進行數據位的采樣,數據在第二個時鐘邊沿被鎖存。如果CPHA位被清’0’,SCK時鐘的第一邊沿(CPOL位為’0’時就是下降沿,CPOL位為’1’時就是上升沿)進行數據位采樣,數據在第一個時鐘邊沿被鎖存。
??? CPOL時鐘極性和CPHA時鐘相位的組合選擇數據捕捉的時鐘邊沿。
(1)數據時鐘時序圖
(2).數據時鐘時序圖
?
?
10、數據幀格式
? 根據SPI_CR1寄存器中的LSBFIRST位,輸出數據位時可以MSB在先也可以LSB在先。根據SPI_CR1寄存器的DFF位,每個數據幀可以是8位或是16位。所選擇的數據幀格式對發送和/或接收都有效。
?
?
11、SPI主模式工作原理
配置SPI主模式的步驟如下:
設置SPI_CR1寄存器的BR[2:0]位,來定義串行時鐘波特率。
選擇CPOL和CPHA位,定義數據傳輸和串行時鐘間的相位關系。
設置DFF位來定義8或16位數據幀格式。
配置SPI_CR1寄存器的LSBFIRST位定義幀格式。
如果NSS引腳需要工作在輸入模式,硬件模式中在整個數據幀傳輸期間應把NSS引腳連接到高電平;在軟件模式中,需設置SPI_CR1寄存器的SSM=1和SSI=1。如果NSS引腳工作在輸出模式,則只需設置SSOE=1位。
設置MSTR=1和SPE=1,只當NSS引腳被連到高電平,這些位才能保持置位。
?
?
12、SPI從模式工作原理
配置SPI從模式的步驟如下:
設置DFF位以定義數據幀格式為8位或16位。
定義數據傳輸和串行時鐘之間的相位關系。
幀格式必須和主設備相同,MSB在前還是LSB在前取決于SPI_CR1寄存器中的LSBFIRST位。
硬件模式下,在完整的數據幀(8位或16位)發送過程中,NSS引腳必須為低電平。軟件模式下,設置SPI_CR1寄存器中的SSM=1,SSI=0。
MSTR=0位,設置SPE=1,使相應引腳工作于SPI模式下。
?
13、狀態標志
應用程序通過3個狀態標志可以完全監控SPI總線的狀態。
1.發送緩沖器空閑標志(TXE)
??? 此標志為’1’時表明發送緩沖器為空,可以寫下一個待發送的數據進入緩沖器中。當寫入SPI_DR時,TXE標志被清除。
2.接收緩沖器非空(RXNE)
??? 此標志為’1’時表明在接收緩沖器中包含有效的接收數據。讀SPI數據寄存器可以清除此標志。
3.忙(Busy)標志
??? BSY標志由硬件設置與清除(寫入此位無效果),此標志表明SPI通信層的狀態。
?
?
14、SPI中斷
?
?
?
?
?
?
?
二、SST25VF016B工作原理
?
1、特性
?
2、框圖
?
3、引腳說明
?
?
5、器件操作
SST25VF016B 支持 SPI 總線操作的模式 0(0,0)和模式 3(1,1)。兩種模式之間的差異在于當總線主器件處于待機模式并且沒有數據傳送時的SCK信號狀態。SCK信號在模式 0 時為低電平,在模式 3 時為高電平。對于這兩種模式,串行數據輸入 (SI)在 SCK 時鐘信號的上升沿被采樣,串行數據輸出 (SO)在 SCK 時鐘信號的下降沿之后被驅動。
?
6、寫保護引腳 (WP#)
寫保護 (WP#)引腳用于使能狀態寄存器的 BPL 位 (bit 7)的鎖定功能。當 WP# 驅動為低電平時,是否執行寫狀態寄存器 (WRSR)指令由 BPL 位的值 (見表 2)決定。當 WP# 為高電平時, BPL 位的鎖定功能被禁止。
?
?
7、狀態寄存器
軟件狀態寄存器提供有關閃存存儲器陣列是否可進行任何讀或寫操作的狀態、器件是否寫使能以及存儲器寫保護的狀態。在內部擦除或編程操作期間,可對狀態寄存器只進行讀操作,以確定正在進行的操作的完成狀態。
?
?
8、寫使能鎖存器 (WEL)
寫使能鎖存器 (Write-Enable Latch, WEL)位表示內部寄存器的寫使能鎖存器狀態。如果寫使能鎖存器位置 “1”,則表示器件寫使能。如果該位置 “0”(復位),則表示器件未寫使能,并且不接受任何存儲器寫 (編程 / 擦除)命令。在下列條件下,寫使能鎖存器位自動復位:
?上電
?寫禁止 (WRDI)指令完成
?字節編程指令完成
?自動地址遞增 (AAI)編程完成或達到其最高的不受保護的存儲器地址
?扇區擦除指令完成
?塊擦除指令完成
?全片擦除指令完成
?寫狀態寄存器指令
?
?
9、塊保護 (BP3、 BP2、 BP1 和 BP0)
塊保護(BP3、BP2、BP1 和 BP0)位定義了要通過軟件保護方式防止任何存儲器寫(編程或擦除)操作的存儲器區域的大小,如表 4 中定義。只要 WP# 為高電平或塊保護鎖定(Block-Protect-Lock,BPL)位為 0,就可以使用寫狀態寄存器(WRSR)指令編程 BP3、 BP2、 BP1 和 BP0 位。僅當塊保護位全部為 0 時,才能執行全片擦除。上電后, BP3、 BP2、 BP1 和 BP0 置為 1。
?
?
10、塊保護鎖定 (BPL)
?WP# 引腳驅動為低電平 (VIL)時,將使能塊保護鎖定 (BPL)位。當 BPL 置 1 時,將阻止對 BPL、BP3、BP2、BP1 和 BP0 位的任何進一步修改。當 WP# 引腳驅動為高電平(VIH) 時,BPL 位沒有任何作用,其值為 “無關”。上電后, BPL 位復位為 0。
?
?
11、指令
指令用于讀、寫 (擦除和編程)和配置 SST25VF016B。指令總線周期是 8 個表示命令 (操作碼)、數據和地址的位。在執行任何字節編程、自動地址遞增 (AAI)編程、扇區擦除、塊擦除、寫狀態寄存器或全片擦除指令之前,必須先執行寫使能 (WREN)指令。表 5 提供了完整的指令列表。所有指令在CE# 從高電平轉換到低電平時同步。在 SCK 的上升沿從最高有效位開始接受輸入。在輸入指令之前,CE# 必須驅動為低電平,而在輸入指令的最后一位后,CE# 必須驅動為高電平(讀、讀 ID 和讀狀態寄存器指令除外)。在接收到指令總線周期的最后一位之前,CE# 上任何低電平到高電平的轉換都將終止正在進行的指令,并將器件恢復為待機模式。指令命令(操作碼)、地址和數據都先從最高有效位(MostSignificant Bit, MSb)輸入。
?
?
12、讀 (25 MHz)
讀指令 (03H)支持最高為 25 MHz 的讀操作。器件從指定的地址單元開始輸出數據。數據輸出流連續遍歷所有地址,直到被 CE# 上低電平到高電平的轉換終止。內部地址指針將自動遞增,直到達到最高的存儲器地址為止。達到最高的存儲器地址后,地址指針將自動遞增到地址空間的開始位置 (回繞)。從地址單元 1FFFFFH 讀取數據之后,下一次輸出將來自地址單元 000000H。通過執行 8 位命令 03H(后面緊跟地址位 [A23-A0])來啟動讀指令。在讀周期的持續時間內,CE# 必須保持有效低電平。
?
?
13、高速讀 (80 MHz)
高速讀指令支持最高為 80 MHz 的讀操作,通過執行 8 位命令 0BH(后面緊跟地址位 [A23-A0] 和一個空字節)來啟動。在高速讀周期的持續時間內,CE# 必須保持有效低電平。有關高速讀序列,請參見圖 6。在一個空周期之后,高速讀指令從指定的地址單元開始輸出數據。數據輸出流連續遍歷所有地址,直到被 CE# 上低電平到高電平的轉換終止。內部地址指針將自動遞增,直到達到最高的存儲器地址為止。達到最高的存儲器地址后,地址指針將自動遞增到地址空間的開始位置 (回繞)。從地址單元 1FFFFFH讀取數據之后,下一次輸出將來自地址單元 000000H。
?
?
14、字節編程
字節編程指令用于將所選字節中的位編程為所需數據。當啟動編程操作時,所選字節必須處于擦除狀態(FFH)。應用到受保護存儲器區域的字節編程指令將被忽略。在執行任何寫操作之前,必須先執行寫使能(WREN)指令。在字節編程指令的持續時間內,CE# 必須保持有效低電平。通過執行 8 位命令 02H (后面緊跟地址位 [A23-A0])來啟動字節編程指令。在地址后面,按照從 MSb(bit 7)到 LSb(bit 0)的順序輸入數據。在執行指令之前,CE# 必須驅動為高電平。用戶可以輪詢軟件狀態寄存器中的 BUSY 位,或等待 TBP(10μs)時間讓內部自定時字節編程操作完成。
?
?
15、自動地址遞增 (AAI)字編程
????? AAI 編程指令允許對多個字節的數據進行編程,無需再次發出下一連續地址單元。當要對多個字節或整個存儲器陣列編程時,該特性可減少總編程時間。指向受保護存儲器區域的 AAI 字編程指令將被忽略。當啟動 AAI 字編程操作時,所選地址范圍必須處于已擦除狀態(FFH)。
??? 當處于 AAI 字編程序列中時,僅下列指令有效: 1 軟件寫操作結束檢測指令 AAI 字(ADH)、寫禁止WRDI(04H)、讀取狀態寄存器RDSR(05H)。 2.硬件寫操作結束檢測指令 AAI 字(ADH)、寫禁止 WRDI(04H)。
????? 在執行任何寫操作之前,必須先執行寫使能(WREN)指令。通過執行 8 位命令 ADH(后面緊跟地址位[A23-A0])來啟動 AAI 字編程指令。在地址后面,連續輸入兩個字節的數據,每個字節都從 MSb(Bit 7)到 LSb (Bit 0)。 在執行 AAI 字編程指令之前, CE# 必須驅動為高電平。在輸入下一個有效命令之前,請檢查 BUSY 狀態。一旦器件指示不再忙,就可以對下兩個連續地址的數據進行編程,然后對再下兩個連續地址的數據進行編程,依此類推。
當編程最后一個所需字或最高的不受保護存儲器地址時,通過硬件或軟件(RDSR 指令)方法檢查忙狀態,以確定編程是否完成。編程完成之后,使用適用的方法終止 AAI。如果器件處于軟件寫操作結束檢測模式,則執行寫禁止 (WRDI)指令 04H。如果器件處于 AAI 硬件寫操作結束檢測模式,則執行寫禁止(WRDI)指令 04H,再執行 8 位 DBSY 命令 80H。在達到最高的不受保護的存儲器地址之后,AAI編程期間不存在回繞模式。
(1)使用硬件寫操作結束檢測時的自動地址遞增 (AAI)字編程序列
(2)使用軟件寫操作結束檢測時的自動地址遞增 (AAI)字編程序列
?
?
?
16、4 KB 扇區擦除
扇區擦除指令會將所選 4 KB 扇區中的所有位清除為 FFH。應用到受保護存儲器區域的扇區擦除指令將被忽略。在執行任何寫操作之前,必須先執行寫使能 (WREN)指令。在任何命令序列的持續時間內,CE# 都必須保持有效低電平。通過執行 8 位命令 20H (后面緊跟地址位 [A23-A0])來啟動扇區擦除指令。在執行指令之前,CE#必須驅動為高電平。用戶可以輪詢軟件狀態寄存器中的 BUSY 位,或等待 TSE(25ms)時間讓內部自定時扇區擦除周期完成。
?
?
?
17、32 KB 和 64 KB 塊擦除
?
?
17、全片擦除
全片擦除指令會將器件中的所有位清除為 FFH。如果有任何存儲器區域受到保護,全片擦除指令將被忽略。在執行任何寫操作之前,必須先執行寫使能 (WREN)指令。在全片擦除指令序列的持續時間內,CE# 必須保持有效低電平。通過執行 8 位命令 60H 或 C7H 來啟動全片擦除指令。在執行指令之前,CE#必須驅動為高電平。用戶可以輪詢軟件狀態寄存器中的 BUSY 位,或等待 TCE(50ms)時間讓內部自定時全片擦除周期完成。
?
?
18、讀取狀態寄存器 (RDSR)
讀取狀態寄存器(RDSR)指令允許讀取狀態寄存器。可在任何時間讀取狀態寄存器,甚至是在寫(編程 / 擦除)操作期間。當進行寫操作時,應在發送任何新命令前檢查 BUSY 位,以確保新命令會被器件正確接收。在輸入 RDSR 指令之前,CE# 必須驅動為低電平,并保持低電平直到狀態數據被讀取為止。讀狀態寄存器繼續使用當前時鐘周期,直到被 CE# 上低電平到高電平的轉換終止。
?
?
19、使能寫狀態寄存器 EWSR、寫狀態寄存器WRSR
寫狀態寄存器指令將新值寫入狀態寄存器的 BP3、BP2、BP1、BP0 和 BPL 位。在輸入 WRSR(0x01) 指令的命令序列之前,需先輸入EWSR(0x50)使能寫狀態寄存器。
?
?
20、寫使能 (WREN)
寫使能 (WREN)指令可將狀態寄存器中的寫使能鎖存器位設置為 “1”,以允許進行寫操作。在執行任何寫 (編程 / 擦除)操作之前,都必須先執行 WREN 指令。 在執行 WREN 指令之前, CE# 必須驅動為高電平。
?
?
21、寫禁止 (WRDI)
寫禁止 (WRDI)指令將寫使能鎖存器位和 AAI 位復位為 0,以禁止任何新的寫操作發生。 WRDI 指令不會終止任何正在進行的編程操作。執行WRDI指令之后,所有正在進行的編程操作都可以持續到TBP。在執行 WRDI 指令之前, CE# 必須驅動為高電平。
?
?
22、讀 ID (RDID)
讀ID指令(RDID)將器件標識為SST25VF016B,將制造商標識為SST。此命令向后兼容所有SST25xFxxxA器件,當在一個設計中使用多個版本的 SPI 串行閃存器件時,應將此命令用作默認器件標識命令。通過執行 8 位命令 90H 或 ABH(后面緊跟地址位 [A23-A0])來讀取器件信息。執行讀 ID 指令之后,制造商ID 位于地址 00000H,器件 ID 位于地址 00001H。器件處于讀 ID 模式之后,制造商 ID 和器件 ID 輸出數據在地址 00000H 和 00001H 之間翻轉,直到被 CE# 上低電平到高電平的轉換終止。
?
?
?
23、產品訂購信息
?
?
?
?
?
?
?
?
三、例程:用SPI讀取?SST25VF016Bflash
1、例程代碼
1 /************************************************************************************************************************************* 2 * 3 * 文件名稱:main.c 4 * 文件功能:主函數文件 5 * 6 ***************************************************************************************************************************************/ 7 8 #include "pbdata.h"//調用自定義公共函數庫 9 10 11 /********************************************************************************* 12 * 13 * 初始化操作 14 * 15 *********************************************************************************/ 16 void RCC_Configuration(void);//系統時鐘初始化函數聲明 17 void GPIO_Configuration(void);//GPIO初始化函數聲明 18 void NVIC_Configuration(void);//中斷優先級配置函數聲明 19 void USART_Configuration(void);//串口配置函數聲明 20 21 22 23 24 /******************************************************************************** 25 * 26 * 函數名稱:main(void) 27 * 函數功能:主函數 28 * 函數說明:不能用void定義主函數 29 * 30 ********************************************************************************/ 31 int main(void) 32 { 33 34 u16 id=0; //ID 35 u16 TxSize1=0; //發送字符的大小 36 u16 i=0; //用于循環 37 38 u8 TxBuffer1[]="liubo tobebest"; //發送的字符 39 TxSize1=sizeof(TxBuffer1)/sizeof(TxBuffer1[0]); //獲取發送的字符的大小 40 41 RCC_Configuration(); //系統時鐘高初始化 42 GPIO_Configuration(); //GPIO初始化 43 USART_Configuration();//串口初始化 44 NVIC_Configuration();//串口優先級初始化 45 SPI_Configuration();//SPI初始化 46 47 id=RDID();//獲取ID 48 printf("%X\r\n",id);//串口打印 49 50 /*把TxBuffer1數組中的數放入TxBuffer2數組中*/ 51 for(i=0;i<TxSize1;i++) 52 { 53 TxBuffer2[i]=TxBuffer1[i]; 54 } 55 56 57 Section_Write(0,TxBuffer2,4096);//寫入Flash 58 memset(TxBuffer2,0,sizeof(TxBuffer2));//把TXBuffer2中前n個字節清0 59 60 delay_ms(100);//延時等待 61 Section_Read(0,TxBuffer2,4096);//?讀出Flash到TxBuffer2 62 printf("%s\r\n",TxBuffer2);//串口打印出讀出的數 63 64 while(1) 65 { 66 delay_ms(1000); 67 } 68 } 69 70 71 72 73 /******************************************************************************** 74 * 75 * 函數名稱:RCC_Configuration(void) 76 * 函數功能:系統時鐘高初始化函數 77 * 78 ********************************************************************************/ 79 void RCC_Configuration(void)//系統時鐘高初始化函數 80 { 81 82 SystemInit();//系統初始化 83 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//串口對應GPIO時鐘使能 84 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//SPI對應GPIO時鐘使能 85 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//SPI對應GPIO時鐘使能 86 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//SPI對應GPIO時鐘使能 87 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口時鐘使能 88 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//引腳復用 89 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);//SPI1時鐘使能 90 91 } 92 93 94 95 /******************************************************************************* 96 * 97 * 函數名稱:GPIO_Configuration(void) 98 * 函數功能:GPIO初始化函數 99 * 100 ********************************************************************************/ 101 102 void GPIO_Configuration(void)//GPIO初始化函數 103 { 104 105 106 /*串口引腳配置*/ 107 GPIO_InitTypeDef GPIO_InitStructure;//定義一個GPIO設置的結構體變量 108 109 /*輸出引腳配置*/ 110 /*結構體變量賦值*/ 111 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;////引腳配置TX 112 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置頻率 113 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//發送要配置成復用推挽輸出 114 /*對應的GPIO初始化*/ 115 GPIO_Init(GPIOA,&GPIO_InitStructure); 116 117 118 /*輸入引腳配置*/ 119 /*結構體變量賦值*/ 120 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;////引腳配置RX 121 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//接收引腳配置成浮空輸入 122 /*對應的GPIO初始化*/ 123 GPIO_Init(GPIOA,&GPIO_InitStructure); 124 125 126 } 127 128 129 /**************************************************************************** 130 * 131 * 函數名稱:NVIC_Configuration(void) 132 * 函數功能:配置中斷優先級 133 * 134 ****************************************************************************/ 135 136 void NVIC_Configuration(void) 137 { 138 NVIC_InitTypeDef NVIC_InitStructure; //定義一個優先級配置結構體變量 139 140 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//分組 141 142 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 143 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//搶斷優先級 144 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//響應優先級 145 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能 146 147 NVIC_Init(&NVIC_InitStructure);//初始化 148 } 149 150 151 /********************************************************************************* 152 * 153 * 函數名稱: 154 * 函數功能:串口配置函數 155 * 156 *********************************************************************************/ 157 void USART_Configuration(void) 158 { 159 /*定義串口配置結構體變量*/ 160 USART_InitTypeDef USART_InitStructure;//定義一個串口配置結構體變量 161 162 163 /*結構體變量賦值*/ 164 USART_InitStructure.USART_BaudRate = 9600;//波特率9600 165 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//位寬,8位 166 USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位1 167 USART_InitStructure.USART_Parity = USART_Parity_No;//不奇偶校驗 168 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//流控禁止 169 USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//發送使能 170 171 172 /*發送串口配置初始化*/ 173 USART_Init(USART1, &USART_InitStructure); 174 175 176 /*打開串口接收中斷*/ 177 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//當接收到數據時,會產生中斷 178 179 180 /*打開串口*/ 181 USART_Cmd(USART1,ENABLE);//串口使能,打開 182 183 /*清空中斷標志位*/ 184 USART_ClearFlag(USART1,USART_FLAG_TC); 185 } 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 View Code 1 /************************************************************************************************************************************* 2 * 3 * 文件名稱:stm32_spi.c 4 * 文件功能:SPI相關函數 5 * 6 ***************************************************************************************************************************************/ 7 8 9 10 #include "pbdata.h" 11 12 13 14 15 /********************************************************************************* 16 * 17 * 函數名稱:void SPI_Configuration(void) 18 * 函數功能:SPI配置函數 19 * 20 *********************************************************************************/ 21 22 void SPI_Configuration(void) 23 { 24 25 /*定義一個SPI配置結構體變量*/ 26 SPI_InitTypeDef SPI_InitStructure; 27 28 /*定義一個SPI的GPIO配置結構體變量*/ 29 GPIO_InitTypeDef GPIO_InitStructure; 30 31 /*配置GPIO*/ 32 /*GPIO配置結構體變量賦值*/ 33 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;////引腳配置 34 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置頻率 35 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//發送要配置成復用推挽輸出 36 /*對應的GPIO初始化*/ 37 GPIO_Init(GPIOA,&GPIO_InitStructure); 38 39 40 /*以太網片選配置*/ 41 /*以太網GPIO配置結構體變量賦值*/ 42 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;//以太網引腳配置 43 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置頻率 44 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//發送配置 45 /*對應的GPIO初始化*/ 46 GPIO_Init(GPIOB,&GPIO_InitStructure); 47 48 49 /*觸摸屏片選配置*/ 50 /*以太網GPIO配置結構體變量賦值*/ 51 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;//觸摸屏引腳配置 52 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置頻率 53 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//發送配置 54 /*對應的GPIO初始化*/ 55 GPIO_Init(GPIOC,&GPIO_InitStructure); 56 57 58 59 /*Flash片選配置*/ 60 /*FlashGPIO配置結構體變量賦值*/ 61 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;//flash引腳配置 62 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置頻率 63 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//發送配置 64 /*對應的GPIO初始化*/ 65 GPIO_Init(GPIOE,&GPIO_InitStructure); 66 67 68 69 /*SPI1配置*/ 70 /*SPI1配置結構體變量賦值*/ 71 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//雙線雙向全雙工 72 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//CPU主模式 73 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8位發送 74 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//懸空時為高 75 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//第二個時鐘沿捕獲 76 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//內部管理 77 SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_8;//8分頻 78 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位開始發送 79 SPI_InitStructure.SPI_CRCPolynomial = 7; 80 /*SPI1初始化*/ 81 SPI_Init(SPI1, &SPI_InitStructure); 82 83 SPI_Cmd(SPI1,ENABLE); //使能SPI 84 85 86 87 /*禁止片選*/ 88 GPIO_SetBits(GPIOB,GPIO_Pin_7);//禁止以太網 89 GPIO_SetBits(GPIOC,GPIO_Pin_4);//禁止觸摸屏 90 GPIO_SetBits(GPIOE,GPIO_Pin_6);//禁止flash 91 92 } 93 94 95 96 97 98 99 100 101 /********************************************************************************* 102 * 103 * 函數名稱:u8 SPI_SendByte(u8 byte) 104 * 函數功能:SPI發送數據函數 105 * 106 *********************************************************************************/ 107 108 u8 SPI_SendByte(u8 byte) 109 { 110 while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);//判斷是否忙 111 112 SPI_I2S_SendData(SPI1,byte);//發送 113 114 while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET);//判斷是否忙 115 116 return SPI_I2S_ReceiveData(SPI1); 117 118 } View Code 1 #ifndef _STM32_SPI_H 2 #define _STM32_SPI_H 3 4 void SPI_Configuration(void);//SPI????oˉêy 5 u8 SPI_SendByte(u8 byte);//SPI·¢?íêy?Yoˉêy 6 7 #endif View Code 1 /************************************************************************************************************************************* 2 * 3 * 文件名稱:SST25V016B.c 4 * 文件功能:SST25V016BFlash相關函數定義 5 * 6 ***************************************************************************************************************************************/ 7 8 #include "pbdata.h" 9 10 11 12 13 14 15 16 17 18 /******************************************************************************************** 19 * 20 * 函數名稱:u8 RDSR(void) 21 * 函數功能:讀取狀態寄存器的值 22 * 23 ********************************************************************************************/ 24 u8 RDSR(void) 25 { 26 u8 dt; 27 SPI_FLASH_L;//平常為高,進入拉低 28 SPI_SendByte(0x05);//發送05 29 dt=SPI_SendByte(0);//讀取數據 30 SPI_FLASH_H;//拉高 31 return dt; 32 } 33 34 35 36 37 /******************************************************************************************** 38 * 39 * 函數名稱:void EWSR(void) 40 * 函數功能:使能狀態寄存器EWSR 41 * 42 ********************************************************************************************/ 43 void EWSR(void) 44 { 45 SPI_FLASH_L;//拉低 46 SPI_SendByte(0x50);//發送50 47 SPI_FLASH_H;//拉高 48 SPI_FLASH_L;//拉低 49 SPI_SendByte(0x01);//發送01 50 SPI_SendByte(0);//清0 51 SPI_FLASH_H;//拉高 52 BUSY(); 53 } 54 55 56 57 58 59 60 /******************************************************************************************** 61 * 62 * 函數名稱:void WREN(void) 63 * 函數功能:寫使能 64 * 65 ********************************************************************************************/ 66 void WREN(void) 67 { 68 SPI_FLASH_L;//拉低 69 SPI_SendByte(0x06);//發送06 70 SPI_FLASH_H;//拉高 71 } 72 73 74 75 76 77 /******************************************************************************************** 78 * 79 * 函數名稱:void WRDI(void) 80 * 函數功能:寫禁止 81 * 82 ********************************************************************************************/ 83 84 void WRDI(void) 85 { 86 SPI_FLASH_L;//拉低 87 SPI_SendByte(0x04);//發送04 88 SPI_FLASH_H;//拉高 89 BUSY(); 90 } 91 92 93 94 95 96 97 /******************************************************************************************** 98 * 99 * 函數名稱:void BUSY(void) 100 * 函數功能:忙檢查 101 ********************************************************************************************/ 102 void BUSY(void) 103 { 104 u8 a=1; 105 while((a&0x01)==1) a=RDSR(); 106 } 107 108 109 110 111 112 /******************************************************************************************** 113 * 114 * 函數名稱:u16 RDID(void) 115 * 函數功能:讀ID 116 ********************************************************************************************/ 117 u16 RDID(void) 118 { 119 u16 id=0; 120 121 SPI_FLASH_L;//拉低 122 123 SPI_SendByte(0x90);//發送90 124 SPI_SendByte(0);//發送0 125 SPI_SendByte(0);//發送0 126 SPI_SendByte(0);//發送0 127 128 id=SPI_SendByte(0);//讀ID 129 id=id<<8; 130 id=id+SPI_SendByte(0); 131 SPI_FLASH_H;//拉高 132 133 return id; 134 } 135 136 137 138 139 140 /******************************************************************************************** 141 * 142 * 函數名稱:void Section_Dell(u32 addr) 143 * 函數功能:扇區擦除 144 ********************************************************************************************/ 145 void Section_Dell(u32 addr) 146 { 147 EWSR();//使能寄存器 148 WREN();//寫使能 149 150 SPI_FLASH_L;//拉低 151 SPI_SendByte(0x20);//發送20 152 SPI_SendByte((addr&0xffffff)>>16);//發送地址 153 SPI_SendByte((addr&0xffff)>>8);//發送地址 154 SPI_SendByte(addr&0xff);//發送地址 155 SPI_FLASH_H;//拉高 156 BUSY(); //忙檢測 157 } 158 159 160 161 162 163 164 /******************************************************************************************** 165 * 166 * 函數名稱:void Section_Read(u32 addr, u8 *buffer,u16 size) 167 * 函數功能:扇區讀 168 ********************************************************************************************/ 169 void Section_Read(u32 addr, u8 *buffer,u16 size) 170 { 171 u16 i=0; 172 173 SPI_FLASH_L;//拉低 174 SPI_SendByte(0x0B);//發送0B 175 SPI_SendByte((addr&0xffffff)>>16);//發送地址 176 SPI_SendByte((addr&0xffff)>>8);//發送地址 177 SPI_SendByte(addr&0xff);//發送地址 178 SPI_SendByte(0);//發送0 179 180 while(i<size) 181 { 182 buffer[i]=SPI_SendByte(0);//讀數據 183 i++; 184 } 185 186 SPI_FLASH_H;//拉高 187 } 188 189 190 191 192 /******************************************************************************************** 193 * 194 * 函數名稱:void Section_Write(u32 addr,u8 *buffer,u16 Size) 195 * 函數功能:寫扇區 196 ********************************************************************************************/ 197 void Section_Write(u32 addr,u8 *buffer,u16 Size) 198 { 199 u16 i=0; 200 201 Section_Dell(addr);//先擦除 202 203 EWSR();//使能寫狀態寄存器 204 WREN();//寫使能 205 206 SPI_FLASH_L;//拉低 207 SPI_SendByte(0xAD);//發送AD 208 SPI_SendByte((addr&0xffffff)>>16);//發送地址 209 SPI_SendByte((addr&0xffff)>>8);//發送地址 210 SPI_SendByte(addr&0xff);//發送地址 211 SPI_SendByte(buffer[0]);//發送buffer[0] 212 SPI_SendByte(buffer[1]);//發送buffer[1] 213 SPI_FLASH_H;//拉高 214 215 i=2; 216 while(i<Size) 217 { 218 delay_us(10);//寫之前先延時 219 SPI_FLASH_L; 220 SPI_SendByte(0xAD);//發送0xAD 221 SPI_SendByte(buffer[i++]);//發送buffer[i++] 222 SPI_SendByte(buffer[i++]);//發送buffer[i++] 223 SPI_FLASH_H;//拉高 224 } 225 226 delay_us(10); 227 WRDI();//退出AAI模式 228 BUSY();//忙檢測 229 230 } 231 232 233 234 235 236 /******************************************************************************************** 237 * 238 * 函數名稱:void Section_ALL_dell(void) 239 * 函數功能:全芯片擦除 240 ********************************************************************************************/ 241 void Section_ALL_dell(void) 242 { 243 244 EWSR();//使能寫狀態寄存器 245 WREN();//寫使能 246 247 SPI_FLASH_L;//拉低 248 SPI_SendByte(0x60);//發送60 249 SPI_FLASH_H;//拉高 250 BUSY();//忙檢測 251 252 253 } View Code 1 /************************************************************************************************************************************* 2 * 3 * 文件名稱:SST25V016B.h 4 * 文件功能:SST25V016BFlash相關函數聲明 5 * 6 ***************************************************************************************************************************************/ 7 8 9 10 #ifndef _SST25VF016B_H 11 #define _SST25VF016B_H 12 13 #define SPI_FLASH_L GPIO_ResetBits(GPIOE,GPIO_Pin_6);//falsh拉低 14 #define SPI_FLASH_H GPIO_SetBits(GPIOE,GPIO_Pin_6);//flash拉高 15 16 17 18 19 u8 RDSR(void);//讀取狀態寄存器的值 20 void EWSR(void);//使能狀態寄存器EWSR 21 void WREN(void);//寫使能 22 void WRDI(void);//寫禁止 23 void BUSY(void);//忙檢查 24 u16 RDID(void);//讀ID 25 void Section_Dell(u32 addr);//扇區擦除 26 void Section_Read(u32 addr,u8 *buffer,u16 Size);//讀扇區 27 void Section_Write(u32 addr,u8 *buffer,u16 Size);//寫扇區 28 void Section_All_dell(void);//全芯片擦除 29 30 31 32 33 #endif View Code 1 /**************************************************************************************************************** 2 * 3 * 文件名稱:pbdata.c 4 * 文件功能:自定義函數或者全局變量的初始化 5 * 6 ****************************************************************************************************************/ 7 8 /*頭文件聲明*/ 9 #include "pbdata.h" 10 11 12 13 14 /******************************************************************************************** 15 * 16 * 自定義全局變量 17 * 18 ********************************************************************************************/ 19 u8 dt=0; 20 21 u8 TxBuffer2[4096];//用作讀寫Flash的緩沖器數組 22 23 24 25 /****************************************************************************************** 26 * 27 * 自定義函數 28 * 29 ******************************************************************************************/ 30 31 32 33 /************************************************** 34 * 35 * 函數名稱:delay_us(u32 nus) 36 * 函數功能:微秒延時函數 37 * 輸入參數:輸入值為延時us 38 * 39 ***************************************************/ 40 void delay_us(u32 nus) 41 { 42 u32 temp; 43 SysTick->LOAD = 9*nus;//載入初值,72M/8=9M,也就是1/9us,9*1/9us,所以是執行9次 44 SysTick->VAL=0X00;//清空計數器,清空后,就自動設置自己設定的計數器的值 45 SysTick->CTRL=0X01;//使能,減到零動作(不發生中斷),采用外部時鐘 46 47 do 48 { 49 temp=SysTick->CTRL;//標志位,等到一直減到0 50 }while((temp&0x01)&&(!(temp&(1<<16))));//等待時間到達 51 52 SysTick->CTRL=0x00; //關閉計數器 53 SysTick->VAL =0X00; //清空計數器 54 } 55 56 57 58 59 60 61 62 /*************************************************** 63 * 64 * 函數名稱:delay_ms(u16 nms) 65 * 函數功能:毫秒級延時 66 * 輸入參數:輸入值位延時ms 67 * 68 ****************************************************/ 69 void delay_ms(u16 nms) 70 { 71 u32 temp; 72 SysTick->LOAD = 9000*nms;//載入初值,72M/8=9M,也就是1/9us,9*1/9us,所以是執行9000次 73 SysTick->VAL=0X00;//清空計數器,清空后,就自動設置自己設定的計數器的值 74 SysTick->CTRL=0X01;//使能,減到零動作(不發生中斷),采用外部時鐘 75 76 do 77 { 78 temp=SysTick->CTRL;//標志位,等到一直減到0 79 }while((temp&0x01)&&(!(temp&(1<<16))));//等待時間到達 80 81 SysTick->CTRL=0x00; //關閉計數器 82 SysTick->VAL =0X00; //清空計數器 83 } 84 85 86 87 /**************************************************** 88 * 89 * 重定義printf函數部分 90 * 91 ****************************************************/ 92 int fputc(int ch,FILE *F) 93 { 94 95 USART_SendData(USART1,(u8)ch); 96 97 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//等待發送完成,判斷標志位 98 99 return ch; 100 } View Code 1 /*pbdata.h*/ 2 /*************************************************************************************************** 3 * 4 * 文件名稱:pbdata.h 5 * 文件功能:自定義的函數和全局變量的聲明頭文件 6 * 7 ***************************************************************************************************/ 8 9 #ifndef _pbdata_H 10 #define _pbdata_H 11 12 13 14 15 16 /******************************************************************** 17 * 18 * 調用的頭文件放在這里 19 * 20 ********************************************************************/ 21 #include "stm32f10x.h" 22 #include "misc.h" 23 #include "stm32f10x_exti.h" 24 #include "stm32f10x_tim.h" 25 #include "stm32f10x_usart.h" 26 #include "stm32f10x_spi.h" 27 #include "stdio.h" 28 #include <string.h> 29 30 #include "stm32_spi.h" 31 #include "SST25VF016B.h" 32 33 34 35 /******************************************************************** 36 * 37 * 自定義全局變量聲明 38 * 39 ********************************************************************/ 40 extern u8 dt; 41 42 extern u8 TxBuffer2[4096];//讀寫Flash的緩沖器數組聲明 43 44 45 46 /******************************************************************** 47 * 48 * 自定義全函數聲明 49 * 50 ********************************************************************/ 51 void delay(u32 nCount); 52 void delay_us(u32 nus); 53 void delay_ms(u16 nms); 54 int fputc(int ch,FILE *F); 55 56 57 58 #endif View Code?
?
2、工程下載
?http://download.csdn.net/detail/a1181803348/8779957
轉載于:https://www.cnblogs.com/STM32bo/p/4557301.html
總結
以上是生活随笔為你收集整理的19、SPI 和 SST25VF016B的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 8构建项目组
- 下一篇: html:(25):选择器定义和标签选择