單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網單片機
W55MH32是WIZnet重磅推出的高性能以太網單片機,它為用戶帶來前所未有的集成化體驗。這顆芯片將強大的組件集于一身,具體來說,一顆W55MH32內置高性能Arm? Cortex-M3核心,其主頻最高可達216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數據處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協議棧、內置MAC以及PHY,擁有獨立的32KB以太網收發緩存,可供8個獨立硬件socket使用。如此配置,真正實現了All-in-One解決方案,為開發者提供極大便利。
在封裝規格上,W55MH32 提供了兩種選擇:QFN68和QFN100。
W55MH32Q采用QFN68封裝版本,尺寸為8x8mm,它擁有36個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、3個串口、2個SPI接口(其中1個帶I2S接口復用)、1個CAN以及1個USB2.0。在保持與同系列其他版本一致的核心性能基礎上,僅減少了部分GPIO以及SDIO接口,其他參數保持一致,性價比優勢顯著,尤其適合網關模組等對空間布局要求較高的場景。緊湊的尺寸和精簡化外設配置,使其能夠在有限空間內實現高效的網絡連接與數據交互,成為物聯網網關、邊緣計算節點等緊湊型設備的理想選擇。 同系列還有QFN100封裝的W55MH32L版本,該版本擁有更豐富的外設資源,適用于需要多接口擴展的復雜工控場景,軟件使用方法一致。更多信息和資料請進入http://www.w5500.com/網站或者私信獲取。
此外,本W55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及MQTT SSL等,為網絡通信安全再添保障。
為助力開發者快速上手與深入開發,基于W55MH32Q這顆芯片,WIZnet精心打造了配套開發板。開發板集成WIZ-Link芯片,借助一根USB C口數據線,就能輕松實現調試、下載以及串口打印日志等功能。開發板將所有外設全部引出,拓展功能也大幅提升,便于開發者全面評估芯片性能。
若您想獲取芯片和開發板的更多詳細信息,包括產品特性、技術參數以及價格等,歡迎訪問官方網頁:http://www.w5500.com/,我們期待與您共同探索W55MH32的無限可能。

第十七章 SPI
1 SPI簡介
SPI 接口可以配置為支持 SPI 協議或者支持 I2S 音頻協議。SPI 接口默認工作在 SPI 方式,可以通過軟件把功能從 SPI 模式切換到 I2S 模式。
串行外設接口(SPI)允許芯片與外部設備以半/全雙工、同步、串行方式通信。此接口可以被配置成主模式,并為外部從設備提供通信時鐘(SCK)。接口還能以多主配置方式工作。
它可用于多種用途,包括使用一條雙向數據線的雙線單工同步傳輸,還可使用 CRC 校驗的可靠通信。
I2S 也是一種 3 引腳的同步串行接口通訊協議。它支持四種音頻標準,包括飛利浦 I2S 標準,MSB和 LSB 對齊標準,以及 PCM 標準。它在半雙工通訊中,可以工作在主和從 2 種模式下。當它作為主設備時,通過接口向外部的從設備提供時鐘信號。
警告:由于 SPI3/I2S3 的部分引腳與 JTAG 引腳共享(SPI3_NSS/I2S3_WS 與 JTDI,SPI3_SCK/I2S3_CK 與 JTDO),因此這些引腳不受 IO 控制器控制,他們(在每次復位后)被默認保留為 JTAG 用途。如果用戶想把引腳配置給 SPI3/I2S3,必須(在調試時)關閉 JTAG并切換至 SWD 接口,或者(在標準應用時)同時關閉 JTAG 和 SWD 接口。
JTAG/SWD 復用功能重映射。
2 SPI和I2S主要特征
2.1 SPI特征
?3 線全雙工同步傳輸
?帶或不帶第三根雙向數據線的雙線單工同步傳輸
?8 或 16 位傳輸幀格式選擇
?主或從操作
?支持多主模式
?8 個主模式波特率預分頻系數(最大為 fPCLK/2)
?從模式頻率(最大為 fPCLK/2)
?主模式和從模式的快速通信
?主模式和從模式下均可以由軟件或硬件進行 NSS 管理:主/從操作模式的動態改變
?可編程的時鐘極性和相位
?可編程的數據順序,MSB 在前或 LSB 在前
?可觸發中斷的專用發送和接收標志
?SPI 總線忙狀態標志
?支持可靠通信的硬件 CRC
······在發送模式下,CRC 值可以被作為最后一個字節發送
······在全雙工模式中對接收到的最后一個字節自動進行 CRC 校驗
?可觸發中斷的主模式故障、過載以及 CRC 錯誤標志
?支持 DMA 功能的 1 字節發送和接收緩沖器:產生發送和接受請求
2.2 I2S功能
?單工通信(僅發送或接收)
?主或者從操作
?8 位線性可編程預分頻器,獲得精確的音頻采樣頻率(8KHz 到 96kHz)
?數據格式可以是 16 位,24 位或者 32 位
?音頻信道固定數據包幀為 16 位(16 位數據幀)或 32 位(16、24 或 32 位數據幀)
?可編程的時鐘極性(穩定態)
?從發送模式下的下溢標志位和主/從接收模式下的溢出標志位
?16 位數據寄存器用來發送和接收,在通道兩端各有一個寄存器
?支持的 I2S 協議:
·······I2S 飛利浦標準
······MSB 對齊標準(左對齊)
······LSB 對齊標準(右對齊)
?PCM 標準(16 位通道幀上帶長或短幀同步或者 16 位數據幀擴展為 32 位通道幀)
?數據方向總是 MSB 在先
?發送和接收都具有 DMA 能力
?主時鐘可以輸出到外部音頻設備,比率固定為 256xFs(Fs 為音頻采樣頻率)
3 SPI功能描述
3.1 概述
SPI 的方框圖見下圖:

通常 SPI 通過 4 個引腳與外部器件相連:
?MISO:主設備輸入/從設備輸出引腳。該引腳在從模式下發送數據,在主模式下接收數據。
?MOSI:主設備輸出/從設備輸入引腳。該引腳在主模式下發送數據,在從模式下接收數據。
?SCK:串口時鐘,作為主設備的輸出,從設備的輸入
?NSS:從設備選擇。這是一個可選的引腳,用來選擇主/從設備。它的功能是用來作為“片選引腳”,讓主設備可以單獨地與特定從設備通訊,避免數據線上的沖突。從設備的 NSS 引腳可以由主設備的一個標準 I/O 引腳來驅動。一旦被使能(SSOE 位),NSS 引腳也可以作為輸出引腳,并在 SPI 處于主模式時拉低;此時,所有的 SPI 設備,如果它們的 NSS 引腳連接到主設備的 NSS 引腳,則會檢測到低電平,如果它們被設置為 NSS 硬件模式,就會自動進入從設備狀態。當配置為主設備、NSS 配置為輸入引腳(MSTR=1,SSOE=0)時,如果 NSS 被拉低,則這個 SPI 設備進入主模式失敗狀態:即 MSTR 位被自動清除,此設備進入從模式
下圖是一個單主和單從設備互連的例子:

單主和單從應用
1.這里 NSS 引腳設置為輸入
MOSI 腳相互連接,MISO 腳相互連接。這樣,數據在主和從之間串行地傳輸(MSB 位在前)。
通信總是由主設備發起。主設備通過 MOSI 腳把數據發送給從設備,從設備通過 MISO 引腳回傳數據。這意味全雙工通信的數據輸出和數據輸入是用同一個時鐘信號同步的;時鐘信號由主設備通過 SCK 腳提供。
從選擇(NSS)腳管理
有 2 種 NSS 模式:
?軟件 NSS 模式:可以通過設置 SPI_CR1 寄存器的 SSM 位來使能這種模式(見圖 212)。在這種模式下 NSS 引腳可以用作它用,而內部 NSS 信號電平可以通過寫 SPI_CR1 的 SSI 位來驅動。
?硬件 NSS 模式,分兩種情況:
·······NSS 輸出被使能:當 W55MH32 工作為主 SPI,并且 NSS 輸出已經通過 SPI_CR2 寄存器的SSOE 位使能,這時 NSS 引腳被拉低,所有 NSS 引腳與這個主 SPI 的 NSS 引腳相連并配置為硬件 NSS 的 SPI 設備,將自動變成從 SPI 設備。當一個 SPI 設備需要發送廣播數據,它必須拉低 NSS 信號,以通知所有其它的設備它是主設備;如果它不能拉低 NSS,這意味著總線上有另外一個主設備在通信,這時將產生一個硬件失敗錯誤(Hard Fault)。
······NSS 輸出被關閉:允許操作于多主環境。

硬件/軟件的從選擇管理
時鐘信號的相位和極性
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 時鐘相位的組合選擇數據捕捉的時鐘邊沿。
注意:
在改變 CPOL/CPHA 位之前,必須清除 SPE 位將 SPI 禁止。
主和從必須配置成相同的時序模式。
SCK 的空閑狀態必須和 SPI_CR1 寄存器指定的極性一致(CPOL 為'1'時,空閑時應上拉 SCK 為高電平;CPOL 為'0'時,空閑時應下拉 SCK 為低電平)。
數據幀格式(8 位或 16 位)由 SPI_CR1 寄存器的 DFF 位選擇,并且決定發送/接收的數據長度。

數據時鐘時序圖
數據幀格式
根據 SPI_CR1 寄存器中的 LSBFIRST 位,輸出數據位時可以 MSB 在先也可以 LSB 在先。
根據 SPI_CR1 寄存器的 DFF 位,每個數據幀可以是 8 位或是 16 位。所選擇的數據幀格式對發送和/或接收都有效。
3.2 配置SPI為從模式
在從模式下,SCK 引腳用于接收從主設備來的串行時鐘。SPI_CR1 寄存器中 BR[2:0]的設置不影響數據傳輸速率。
注: 建議在主設備發送時鐘之前使能 SPI 從設備,否則可能會發生意外的數據傳輸。在通信時鐘的第一個邊沿到來之前或正在進行的通信結束之前,從設備的數據寄存器必須就緒。在使能從設備和主設備之前,通信時鐘的極性必須處于穩定的數值。
請按照以下步驟配置 SPI 為從模式:
配置步驟
1. 設置 DFF 位以定義數據幀格式為 8 位或 16 位。
2. 選擇 CPOL 和 CPHA 位來定義數據傳輸和串行時鐘之間的相位關系(見圖 213)。為保證正確的數據傳輸,從設備和主設備的 CPOL 和 CPHA 位必須配置成相同的方式。
3. 幀格式(SPI_CR1 寄存器中的 LSBFIRST 位定義的”MSB 在前”還是”LSB 在前”)必須與主設備相同。
4. 硬件模式下(參考從選擇(NSS)腳管理部分),在完整的數據幀(8 位或 16 位)傳輸過程中,NSS引腳必須為低電平。在 NSS 軟件模式下,設置 SPI_CR1 寄存器中的 SSM 位并清除 SSI 位。
5. 清除 MSTR 位、設置 SPE 位(SPI_CR1 寄存器),使相應引腳工作于 SPI 模式下。在這個配置中,MOSI 引腳是數據輸入,MISO 引腳是數據輸出。
數據發送
過程在寫操作中,數據字被并行地寫入發送緩沖器。
當從設備收到時鐘信號,并且在 MOSI 引腳上出現第一個數據位時,發送過程開始(譯注:此時第一個位被發送出去)。余下的位(對于 8 位數據幀格式,還有 7 位;對于 16 位數據幀格式,還有 15位)被裝進移位寄存器。當發送緩沖器中的數據傳輸到移位寄存器時,SPI_SP 寄存器的 TXE 標志被設置,如果設置了 SPI_CR2 寄存器的 TXEIE 位,將會產生中斷。
數據接收過程
對于接收器,當數據接收完成時:
移位寄存器中的數據傳送到接收緩沖器,SPI_SR 寄存器中的 RXNE 標志被設置。
如果設置了 SPI_CR2 寄存器中的 RXNEIE 位,則產生中斷。
在最后一個采樣時鐘邊沿后,RXNE 位被置'1',移位寄存器中接收到的數據字節被傳送到接收緩沖器。當讀 SPI_DR 寄存器時,SPI 設備返回這個接收緩沖器的數值。讀 SPI_DR 寄存器時,RXNE 位被清除。
3.3 配置SPI為主模式
在主配置時,在 SCK 腳產生串行時鐘。
配置步驟
1. 通過 SPI_CR1 寄存器的 BR[2:0]位定義串行時鐘波特率。
2. 選擇 CPOL 和 CPHA 位,定義數據傳輸和串行時鐘間的相位關系(見圖 213)。
3. 設置 DFF 位來定義 8 位或 16 位數據幀格式。
4. 配置 SPI_CR1 寄存器的 LSBFIRST 位定義幀格式。
5. 如果需要 NSS 引腳工作在輸入模式,硬件模式下,在整個數據幀傳輸期間應把 NSS 腳連接到高電平;在軟件模式下,需設置 SPI_CR1 寄存器的 SSM 位和 SSI 位。如果 NSS 引腳工作在輸出模式,則只需設置 SSOE 位。
必須設置 MSTR 位和 SPE 位(只當 NSS 腳被連到高電平,這些位才能保持置位)。在這個配置中,MOSI 引腳是數據輸出,而 MISO 引腳是數據輸入。
數據發送過程
當寫入數據至發送緩沖器時,發送過程開始。
在發送第一個數據位時,數據字被并行地(通過內部總線)傳入移位寄存器,而后串行地移出到MOSI 腳上;MSB 在先還是 LSB 在先,取決于 SPI_CR1 寄存器中的 LSBFIRST 位的設置。數據從發送緩沖器傳輸到移位寄存器時 TXE 標志將被置位,如果設置了 SPI_CR1 寄存器中的 TXEIE位,將產生中斷。
數據接收過程
對于接收器來說,當數據傳輸完成時:
傳送移位寄存器里的數據到接收緩沖器,并且 RXNE 標志被置位。
如果設置了 SPI_CR2 寄存器中的 RXNEIE 位,則產生中斷。
在最后采樣時鐘沿,RXNE 位被設置,在移位寄存器中接收到的數據字被傳送到接收緩沖器。讀SPI_DR 寄存器時,SPI 設備返回接收緩沖器中的數據。讀 SPI_DR 寄存器將清除 RXNE 位。
一旦傳輸開始,如果下一個將發送的數據被放進了發送緩沖器,就可以維持一個連續的傳輸流。在試圖寫發送緩沖器之前,需確認 TXE 標志應該為'1'。
注: 在 NSS 硬件模式下,從設備的 NSS 輸入由 NSS 引腳控制或另一個由軟件驅動的 GPIO 引腳控制。
3.4 配置SPI為單工通信
SPI 模塊能夠以兩種配置工作于單工方式:
?1 條時鐘線和 1 條雙向數據線;
?1 條時鐘線和 1 條數據線(只接收或只發送);
1 條時鐘線和 1 條雙向數據線(BIDIMODE=1)
設置 SPI_CR1 寄存器中的 BIDIMODE 位而啟用此模式。在這個模式下,SCK 引腳作為時鐘,主設備使用 MOSI 引腳而從設備使用 MISO 引腳作為數據通信。傳輸的方向由 SPI_CR1 寄存器里的 BIDIOE控制,當這個位是'1'的時候,數據線是輸出,否則是輸入。
1 條時鐘和 1 條單向數據線(BIDIMODE=0)
?在這個模式下,SPI 模塊可以或者作為只發送,或者作為只接收。
?只發送模式類似于全雙工模式(BIDIMODE=0,RXONLY=0):數據在發送引腳(主模式時是 MOSI、從模式時是 MISO)上傳輸,而接收引腳(主模式時是 MISO、從模式時是 MOSI)可以作為通用的I/O 使用。此時,軟件不必理會接收緩沖器中的數據(如果讀出數據寄存器,它不包含任何接收數據)。
?在只接收模式,可以通過設置 SPI_CR2 寄存器的 RXONLY 位而關閉 SPI 的輸出功能;此時,發送引腳(主模式時是 MOSI、從模式時是 MISO)被釋放,可以作為其它功能使用。
配置并使能 SPI 模塊為只接收模式的方式是:
?在主模式時,一旦使能 SPI,通信立即啟動,當清除 SPE 位時立即停止當前的接收。在此模式下,不必讀取 BSY 標志,在 SPI 通信期間這個標志始終為'1'。
?在從模式時,只要 NSS 被拉低(或在 NSS 軟件模式時,SSI 位為'0')同時 SCK 有時鐘脈沖,SPI就一直在接收。
3.5 數據發送與接收過程
接收與發送緩沖器
在接收時,接收到的數據被存放在一個內部的接收緩沖器中;在發送時,在被發送之前,數據將首先被存放在一個內部的發送緩沖器中。對 SPI_DR 寄存器的讀操作,將返回接收緩沖器的內容;寫入 SPI_DR 寄存器的數據將被寫入發送緩沖器中。
主模式下開始傳輸
?全雙工模式(BIDIMODE=0 并且 RXONLY=0)
······當寫入數據到 SPI_DR 寄存器(發送緩沖器)后,傳輸開始;
······在傳送第一位數據的同時,數據被并行地從發送緩沖器傳送到 8 位的移位寄存器中,然后按順序被串行地移位送到 MOSI 引腳上;
······與此同時,在 MISO 引腳上接收到的數據,按順序被串行地移位進入 8 位的移位寄存器中,然后被并行地傳送到 SPI_DR 寄存器(接收緩沖器)中。
?單向的只接收模式(BIDIMODE=0 并且 RXONLY=1)
········SPE=1 時,傳輸開始;
······只有接收器被激活,在 MISO 引腳上接收到的數據,按順序被串行地移位進入 8 位的移位寄存器中,然后被并行地傳送到 SPI_DR 寄存器(接收緩沖器)中。
······雙向模式,發送時(BIDIMODE=1 并且 BIDIOE=1)
······當寫入數據到 SPI_DR 寄存器(發送緩沖器)后,傳輸開始;
·······在傳送第一位數據的同時,數據被并行地從發送緩沖器傳送到 8 位的移位寄存器中,然后按順序被串行地移位送到 MOSI 引腳上;
······不接收數據。
?雙向模式,接收時(BIDIMODE=1 并且 BIDIOE=0)
······SPE=1 并且 BIDIOE=0 時,傳輸開始;
······在 MOSI 引腳上接收到的數據,按順序被串行地移位進入 8 位的移位寄存器中,然后被并行地傳送到 SPI_DR 寄存器(接收緩沖器)中。
······不激活發送器,沒有數據被串行地送到 MOSI 引腳上。
從模式下開始傳輸
?全+雙工模式(BIDIMODE=0 并且 RXONLY=0)
······當從設備接收到時鐘信號并且第一個數據位出現在它的 MOSI 時,數據傳輸開始,隨后的數據位依次移動進入移位寄存器;
······與此同時,在傳輸第一個數據位時,發送緩沖器中的數據被并行地傳送到 8 位的移位寄存器,隨后被串行地發送到 MISO 引腳上。軟件必須保證在 SPI 主設備開始數據傳輸之前在發送寄存器中寫入要發送的數據。
?單向的只接收模式(BIDIMODE=0 并且 RXONLY=1)
·······當從設備接收到時鐘信號并且第一個數據位出現在它的 MOSI 時,數據傳輸開始,隨后數據位依次移動進入移位寄存器;
······不啟動發送器,沒有數據被串行地傳送到 MISO 引腳上。
?雙向模式,發送時(BIDIMODE=1 并且 BIDIOE=1)
······當從設備接收到時鐘信號并且發送緩沖器中的第一個數據位被傳送到MISO引腳上的時候,數據傳輸開始;
······在第一個數據位被傳送到 MISO 引腳上的同時,發送緩沖器中要發送的數據被平行地傳送到 8 位的移位寄存器中,隨后被串行地發送到 MISO 引腳上。軟件必須保證在 SPI 主設備開始數據傳輸之前在發送寄存器中寫入要發送的數據;
······不接收數據。
?雙向模式,接收時(BIDIMODE=1 并且 BIDIOE=0)
······當從設備接收到時鐘信號并且第一個數據位出現在它的 MOSI 時,數據傳輸開始;
······從 MISO 引腳上接收到的數據被串行地傳送到 8 位的移位寄存器中,然后被平行地傳送到SPI_DR 寄存器(接收緩沖器);
······不啟動發送器,沒有數據被串行地傳送到 MISO 引腳上。
處理數據的發送與接收
當數據從發送緩沖器傳送到移位寄存器時,設置 TXE 標志(發送緩沖器空),它表示內部的發送緩沖器可以接收下一個數據;如果在 SPI_CR2 寄存器中設置了 TXEIE 位,則此時會產生一個中斷;寫入 SPI_DR 寄存器即可清除 TXE 位。
注: 在寫入發送緩沖器之前,軟件必須確認 TXE 標志為'1',否則新的數據會覆蓋已經在發送緩沖器中的數據。
在采樣時鐘的最后一個邊沿,當數據被從移位寄存器傳送到接收緩沖器時,設置 RXNE 標志(接收緩沖器非空);它表示數據已經就緒,可以從 SPI_DR 寄存器讀出;如果在 SPI_CR2 寄存器中設置了 RXNEIE 位,則此時會產生一個中斷;讀出 SPI_DR 寄存器即可清除 RXNIE 標志位。
在一些配置中,傳輸最后一個數據時,可以使用 BSY 標志等待數據傳輸的結束。
主或從模式下(BIDIMODE=0 并且 RXONLY=0)全雙工發送和接收過程模式
1. 設置 SPE 位為'1',使能 SPI 模塊;
2. 在 SPI_DR 寄存器中寫入第一個要發送的數據,這個操作會清除 TXE 標志;
3. 等待 TXE=1,然后寫入第二個要發送的數據。等待 RXNE=1,然后讀出 SPI_DR 寄存器并獲得第一個接收到的數據,讀 SPI_DR 的同時清除了 RXNE 位。重復這些操作,發送后續的數據同時接收 n-1 個數據;
4. 等待 RXNE=1,然后接收最后一個數據;
5. 等待 TXE=1,在 BSY=0 之后關閉 SPI 模塊。
也可以在響應 RXNE 或 TXE 標志的上升沿產生的中斷的處理程序中實現這個過程。

主模式、全雙工模式下(BIDIMODE=0 并且 RXONLY=0)連續傳輸時,TXE/RXNE/BSY 的變化示意圖
從模式、全雙工模式下(BIDIMODE=0 并且 RXONLY=0)連續傳輸時,TXE/RXNE/BSY 的變化示意圖
只發送過程(BIDIMODE=0 并且 RXONLY=0)
在此模式下,傳輸過程可以簡要說明如下,使用 BSY 位等待傳輸的結束(見下兩圖):
1. 設置 SPE 位為'1',使能 SPI 模塊;
2. 在 SPI_DR 寄存器中寫入第一個要發送的數據,這個操作會清除 TXE 標志;
3. 等待 TXE=1,然后寫入第二個要發送的數據。重復這個操作,發送后續的數據;
4. 寫入最后一個數據到 SPI_DR 寄存器之后,等待 TXE=1;然后等待 BSY=0,這表示最后一個數據的傳輸已經完成。
也可以在響應 TXE 標志的上升沿產生的中斷的處理程序中實現這個過程。
注:
對于不連續的傳輸,在寫入 SPI_DR 寄存器的操作與設置 BSY 位之間有 2 個 APB 時鐘周期的延遲,因此在只發送模式下,寫入最后一個數據后,最好先等待 TXE=1,然后再等待 BSY=0。
只發送模式下,在傳輸 2 個數據之后,由于不會讀出接收到的數據,SPI_SR 寄存器中的 OVR位會變為'1'。軟件不必理會這個 OVR 標志位。

主設備只發送模式(BIDIMODE=0 并且 RXONLY=0)下連續傳輸時,,TXE/BSY 變化示意圖

從設備只發送模式(BIDIMODE=0 并且 RXONLY=0)下連續傳輸時,TXE/BSY 變化示意圖
雙向發送過程(BIDIMODE=1 并且 BIDIOE=1)
在此模式下,操作過程類似于只發送模式,不同的是:在使能 SPI 模塊之前,需要在 SPI_CR2 寄存器中同時設置 BIDIMODE 和 BIDIOE 位為'1'。
單向只接收模式(BIDIMODE=0 并且 RXONLY=1)在此模式下,傳輸過程可以簡要說明如下(見):
在 SPI_CR2 寄存器中,設置 RXONLY=1;
設置 SPE=1,使能 SPI 模塊:
主模式下,立刻產生 SCK 時鐘信號,在關閉 SPI(SPE=0)之前,不斷地接收串行數據;
從模式下,當 SPI 主設備拉低 NSS 信號并產生 SCK 時鐘時,接收串行數據。
等待 RXNE=1,然后讀出 SPI_DR 寄存器以獲得收到的數據(同時會清除 RXNE 位)。重復這個操作接收所有數據。也可以在響應 RXNE 標志的上升沿產生的中斷的處理程序中實現這個過程。
注: 如果在最后一個數據傳輸結束后關閉 SPI 模塊,請按照第 16.3.8 節的建議操作

只接收模式(BIDIMODE=0 并且 RXONLY=1)下連續傳輸時,RXNE 變化示意圖
單向接收過程(BIDIMODE=1 并且 BIDIOE=0)
在此模式下,操作過程類似于只接收模式,不同的是:在使能 SPI 模塊之前,需要在 SPI_CR2 寄存器中設置 BIDIMODE 為'1'并清除 BIDIOE 位為'0'。
連續和非連續傳輸
當在主模式下發送數據時,如果軟件足夠快,能夠在檢測到每次 TXE 的上升沿(或 TXE 中斷),并立即在正在進行的傳輸結束之前寫入 SPI_DR 寄存器,則能夠實現連續的通信;此時,在每個數據項的傳輸之間的 SPI 時鐘保持連續,同時 BSY 位不會被清除。
如果軟件不夠快,則會導致不連續的通信;這時,在每個數據傳輸之間會被清除(見下圖)。在主模式的只接收模式下(RXONLY=1),通信總是連續的,而且 BSY 標志始終為'1'。
在從模式下,通信的連續性由 SPI 主設備決定。不管怎樣,即使通信是連續的,BSY 標志會在每個數據項之間至少有一個 SPI 時鐘周期為低。

非連續傳輸發送(BIDIMODE=0 并且 RXONLY=0)時,TXE/BSY 變化示意圖
4 利用DMA的SPI通信
為了達到最大通信速度,需要及時往 SPI 發送緩沖器填數據,同樣接收緩沖器中的數據也必須及時讀走以防止溢出。為了方便高速率的數據傳輸,SPI 實現了一種采用簡單的請求/應答的 DMA 機制。
當 SPI_CR2 寄存器上的對應使能位被設置時,SPI 模塊可以發出 DMA 傳輸請求。發送緩沖器和接收緩沖器亦有各自的 DMA 請求。
發送時,在每次 TXE 被設置為'1'時發出 DMA 請求,DMA 控制器則寫數據至 SPI_DR 寄存器,TXE 標志因此而被清除。
接收時,在每次 RXNE 被設置為'1'時發出 DMA 請求,DMA 控制器則從 SPI_DR 寄存器讀出數據,RXNE 標志因此而被清除。當只使用 SPI 發送數據時,只需使能 SPI 的發送 DMA 通道。此時,因為沒有讀取收到的數據,OVR被置為'1'(譯注:軟件不必理會這個標志)。當只使用 SPI 接收數據時,只需使能 SPI 的接收 DMA 通道。
在發送模式下,當 DMA 已經傳輸了所有要發送的數據(DMA_ISR 寄存器的 TCIF 標志變為'1')后,可以通過監視 BSY 標志以確認 SPI 通信結束,這樣可以避免在關閉 SPI 或進入停止模式時,破壞最后一個數據的傳輸。因此軟件需要先等待 TXE=1,然后等待 BSY=0。
注: 在不連續的通信中,在寫數據到 SPI_DR 的操作與 BSY 位被置為'1'之間,有 2 個 APB 時鐘周期的延遲,因此,在寫完最后一個數據后需要先等待 TXE=1 再等待 BSY=0。

使用 DMA 發送

使用 DMA 接收
5 SPI中斷
SPI 中斷請求
| 中斷事件 | 事件標志 | 使能控制位 |
| 發送緩沖器空標志 | TXE | TXEIE |
| 接收緩沖器非空標志 | RXNE | RXNEIE |
| 主模式失效事件 | MODF | ERRIE |
| 溢出錯誤 | OVR | ERRIE |
| CRC 錯誤標志 | CRCERR | ERRIE |
6 例程設計
6.1 SPI_DMA例程
1.UART 模塊:配置 USART1,將printf輸出重定向到該串口,用于輸出系統時鐘信息與測試提示。
2.SPI 模塊:使能 SPI1 和 GPIOA 時鐘,配置相關引腳。
初始化 SPI1,設置為雙線全雙工、主模式,數據大小為 8 位等參數。
3.DMA 模塊:使能 DMA1 時鐘,配置 DMA1 通道 2 用于 SPI1 的接收,通道 3 用于 SPI1 的發送。
分別設置通道的外設地址、內存地址、數據傳輸方向等參數。
使能 SPI1 的 DMA 收發請求,但初始時禁用 DMA 通道。
4.主函數模塊:初始化延時函數和 UART。
int main(void)
{
RCC_ClocksTypeDef clocks;
uint16_t i;
// 初始化延時和串口
delay_init();
UART_Configuration(115200);
// 打印系統時鐘信息
RCC_GetClocksFreq(&clocks);
printf("nSYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhzn",
(float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000,
(float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000);
printf("SPI DMA Test.n");
// 初始化緩沖區:發送數據為0x01~0xFF,接收緩沖區清零
for (i = 0; i < SPI_BUFF_SIZE; i++)
{
SPI_TX_BUFF[i] = i + 1;
}
memset(SPI_RX_BUFF, 0, sizeof(SPI_RX_BUFF));
// 初始化SPI和DMA
SPI_Configuration();
DMA_Configuration();
// ================== SPI發送測試 ==================
printf("Start SPI DMA transmission...n");
GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 拉低片選(CS有效)
printf("Chip select (CS) is pulled low.n");
DMA_Cmd(DMA1_Channel3, ENABLE); // 啟用發送通道
printf("DMA channel 3 for SPI Tx is enabled.n");
// 等待發送完成(查詢傳輸完成標志)
while (!DMA_GetFlagStatus(DMA1_FLAG_TC3))
{
printf("DMA transfer in progress...n");
delay_ms(10);
}
printf("DMA transfer completed.n");
// 清除標志并禁用通道
DMA_ClearFlag(DMA1_FLAG_TC3);
printf("DMA transfer complete flag is cleared.n");
DMA_Cmd(DMA1_Channel3, DISABLE);
printf("DMA channel 3 for SPI Tx is disabled.n");
delay_ms(100);
GPIO_SetBits(GPIOA, GPIO_Pin_4); // 拉高片選(CS無效)
printf("Chip select (CS) is pulled high.n");
// 打印發送數據
printf("Data sent via SPI:n");
for (i = 0; i < SPI_BUFF_SIZE; i++)
{
printf("%02X ", SPI_TX_BUFF[i]);
if ((i + 1) % 16 == 0) printf("n");
}
printf("n");
// ================== SPI接收測試(如需自發自收需硬件環路) ==================
printf("Start SPI DMA reception...n");
GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 再次拉低片選(僅示例,實際需硬件支持)
printf("Chip select (CS) is pulled low.n");
DMA_Cmd(DMA1_Channel2, ENABLE); // 啟用接收通道
printf("DMA channel 2 for SPI Rx is enabled.n");
// 等待接收完成(假設發送后立即接收,需根據硬件調整)
while (!DMA_GetFlagStatus(DMA1_FLAG_TC2))
{
printf("DMA Rx transfer in progress...n");
delay_ms(10);
}
printf("DMA Rx transfer completed.n");
DMA_ClearFlag(DMA1_FLAG_TC2);
printf("DMA Rx transfer complete flag is cleared.n");
DMA_Cmd(DMA1_Channel2, DISABLE);
printf("DMA channel 2 for SPI Rx is disabled.n");
GPIO_SetBits(GPIOA, GPIO_Pin_4); // 拉高片選
// 打印接收數據(需硬件環路才能看到有效數據)
printf("Data received via SPI:n");
for (i = 0; i < SPI_BUFF_SIZE; i++)
{
printf("%02X ", SPI_RX_BUFF[i]);
if ((i + 1) % 16 == 0) printf("n");
}
printf("n");
while (1); // 主循環保持運行
}
?獲取系統時鐘頻率并輸出。
?填充發送緩沖區,清空接收緩沖區。
?配置 SPI 和 DMA。
?拉低片選信號,使能 DMA 發送通道,等待發送完成后清除標志位、禁用通道,最后拉高片選信號。
6.2 SPI_MasterSlaveDma例程
該例程是一個基于 W55MH32 的 SPI DMA 通信測試程序,支持主從模式切換,以下是其詳細運行過程:
1. 初始化階段
(1)時鐘配置
// 時鐘配置函數:啟用HSE并配置PLL倍頻
void RCC_ClkConfiguration(void)
{
RCC_DeInit(); // 復位RCC配置到默認狀態
// 啟用外部高速時鐘(HSE)
RCC_HSEConfig(RCC_HSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); // 等待HSE穩定
// 禁用PLL并配置PLL參數(HSE×27倍頻,假設HSE=8MHz,最終SYSCLK=216MHz)
RCC_PLLCmd(DISABLE);
WIZ_RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_27, 1); // HSE作為PLL輸入,倍頻27倍
RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); // 等待PLL鎖定
// 設置系統時鐘源及總線分頻
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // 使用PLL作為系統時鐘
RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB總線時鐘 = SYSCLK (216MHz)
RCC_PCLK1Config(RCC_HCLK_Div2); // APB1總線時鐘 = HCLK/2 (108MHz)
RCC_PCLK2Config(RCC_HCLK_Div1); // APB2總線時鐘 = HCLK (216MHz)
// 啟用內部低速(LSI)和高速(HSI)時鐘(供其他外設使用)
RCC_LSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
RCC_HSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
}
?調用RCC_ClkConfiguration():啟用外部高速時鐘(HSE),配置 PLL 為 HSE×27 倍頻(最終 SYSCLK=72MHz)。
······配置 AHB 時鐘(HCLK)=72MHz,APB1(PCLK1)=36MHz,APB2(PCLK2)=72MHz。
·······啟用內部低速時鐘(LSI)和高速時鐘(HSI)。
(2)串口初始化
?調用UART_Configuration(115200):配置 USART1 波特率為 115200,8 位數據位,1 位停止位,無校驗。
······初始化 GPIOA 的 Pin9(TX)和 Pin10(RX)為復用推挽輸出和浮空輸入。
······使能 USART1。
(3)打印時鐘信息
通過RCC_GetClocksFreq()獲取并打印系統各時鐘頻率:
SYSCLK: 72.0Mhz, HCLK: 72.0Mhz, PCLK1: 36.0Mhz, PCLK2: 72.0Mhz, ADCCLK: 36.0Mhz
2. 數據準備階段
初始化發送緩沖區:
for (i = 0; i < SPI_BUFF_SIZE; i++) {
SPI_TX_BUFF[i] = i + 1; // 填充數據0x01~0xFF
}
清空接收緩沖區:
memset(SPI_RX_BUFF, 0, sizeof(SPI_RX_BUFF));
3. SPI 與 DMA 配置
(1)模式選擇
?通過條件編譯選擇主模式(SPI_MASTER)或從模式(SPI_SLAVE)。當前代碼默認為主模式。
(2)GPIO 與時鐘使能
?主模式(SPI3):使能 SPI3、GPIOA、GPIOB、DMA2 時鐘。
······配置 GPIOB 的 Pin3(MOSI)、Pin4(MISO)、Pin5(SCK)為復用推挽輸出。
······配置 GPIOA 的 Pin15 為片選(CS)輸出,初始拉高。
(3)DMA 配置
?接收通道(DMA2_Channel1):外設地址為SPI3->DR,內存地址為SPI_RX_BUFF。
······方向為外設到內存,數據寬度為 8 位,循環模式關閉。
······使能 DMA 傳輸完成中斷。
?發送通道(DMA2_Channel2):外設地址為SPI3->DR,內存地址為SPI_TX_BUFF。
······方向為內存到外設,其他參數與接收通道一致。
(4)SPI 初始化
?主模式配置:全雙工模式,8 位數據,CPOL = 低,CPHA = 第一邊沿(模式 0)。
······波特率預分頻為 8(SPI 時鐘 = 72MHz/8=9MHz)。
······使能 SPI3。
4. 數據傳輸階段
(1)觸發 DMA 傳輸
void SpiDmaTrans(unsigned char *sendBuffer, unsigned char *reciveBuffer, unsigned int len)
{
// 主模式下拉低片選信號(假設PA15為片選引腳)
#ifdef SPI_MASTER
GPIO_ResetBits(GPIOA, GPIO_Pin_15); // 拉低片選,選中從設備
#endif
// 禁用舊的DMA請求和通道(確保配置干凈)
SPI_I2S_DMACmd(UseSpi, SPI_I2S_DMAReq_Tx, DISABLE);
SPI_I2S_DMACmd(UseSpi, SPI_I2S_DMAReq_Rx, DISABLE);
DMA_Cmd(UseTxChannel, DISABLE);
DMA_Cmd(UseRxChannel, DISABLE);
// 配置DMA緩沖區地址
UseTxChannel->CMAR = (uint32_t)sendBuffer; // 發送緩沖區地址
UseRxChannel->CMAR = (uint32_t)reciveBuffer; // 接收緩沖區地址
// 設置傳輸數據長度(256字節)
UseTxChannel->CNDTR = len;
UseRxChannel->CNDTR = len;
// 重置傳輸完成標志
SpiTransFinish = 0;
// 啟用DMA通道和SPI的DMA請求
DMA_Cmd(UseRxChannel, ENABLE); // 先啟用接收通道(確保同步)
DMA_Cmd(UseTxChannel, ENABLE);
SPI_I2S_DMACmd(UseSpi, SPI_I2S_DMAReq_Rx, ENABLE); // 使能SPI接收DMA請求
SPI_I2S_DMACmd(UseSpi, SPI_I2S_DMAReq_Tx, ENABLE); // 使能SPI發送DMA請求
}
?調用SpiDmaTrans():拉低片選信號(GPIOA Pin15)。
······配置 DMA 緩沖區地址和數據長度(256 字節)。
······啟用 DMA 通道和 SPI 的 DMA 請求。
(2)中斷處理
?傳輸完成中斷(UseSpiTransFinishHanlder):清除 DMA 完成標志,禁用 DMA 通道。
······拉高片選信號(主模式)。
······設置SpiTransFinish標志,通知主循環傳輸完成。
5. 數據驗證與循環
?主循環邏輯:等待 DMA 傳輸完成(SpiTransFinish標志)。
·······比較發送與接收數據:若不一致,打印錯誤信息并進入死循環。
--若一致,打印>>success并延時 10ms 后重試。
7 下載驗證
7.1 SPI_DMA例程
程序啟動
通過串口輸出系統時鐘頻率信息,可確認時鐘配置是否正確。
顯示測試提示信息,表明開始進行 SPI 的 DMA 數據傳輸測試。
SPI 數據發送
拉低片選信號(GPIOA 的引腳 4),選中 SPI 從設備,準備傳輸數據。
使能 DMA 發送通道,開始通過 SPI1 將發送緩沖區的數據傳輸到從設備。
等待 DMA 傳輸完成,此過程中硬件上 SPI 總線會有相應信號傳輸。
傳輸完成后,清除 DMA 傳輸完成標志,禁用 DMA 發送通道。
拉高片選信號,結束本次數據傳輸。

7.2 SPI_MasterSlaveDma例程

WIZnet 是一家無晶圓廠半導體公司,成立于 1998 年。產品包括互聯網處理器 iMCU?,它采用 TOE(TCP/IP 卸載引擎)技術,基于獨特的專利全硬連線 TCP/IP。iMCU? 面向各種應用中的嵌入式互聯網設備。
WIZnet 在全球擁有 70 多家分銷商,在香港、韓國、美國設有辦事處,提供技術支持和產品營銷。
香港辦事處管理的區域包括:澳大利亞、印度、土耳其、亞洲(韓國和日本除外)。
審核編輯 黃宇
-
crc
+關注
關注
0文章
205瀏覽量
30642 -
SPI
+關注
關注
17文章
1868瀏覽量
100004 -
I2S
+關注
關注
1文章
80瀏覽量
43899
發布評論請先 登錄
文檔更新 | 迅為RK3568驅動指南-第十七篇(串口)
全國互聯電網調度管理規程(試行)
太陽能充放電控制————求解
火力發電廠水汽分析方法 第十七部分:聯氨的測定(直接法)DL
模擬電路網絡課件 第十七節:結型場效應管
第十七屆中國電子電路行業排行榜頒獎會議正式召開
【正點原子FPGA連載】第三十七章雙路高速AD實驗 -摘自【正點原子】新起點之FPGA開發指南_V2.1
"STM32H7學習繼續(STM32H7系列5)第十七章比較實用,以后寫程序的時候會用到"
云英谷科技VTOS6205斬獲第十七屆“中國芯”優秀技術創新產品獎

第十七章 SPI
評論