單芯片解決方案,開啟全新體驗(yàn)——W55MH32 高性能以太網(wǎng)單片機(jī)
W55MH32是WIZnet重磅推出的高性能以太網(wǎng)單片機(jī),它為用戶帶來(lái)前所未有的集成化體驗(yàn)。這顆芯片將強(qiáng)大的組件集于一身,具體來(lái)說,一顆W55MH32內(nèi)置高性能Arm? Cortex-M3核心,其主頻最高可達(dá)216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲(chǔ)與數(shù)據(jù)處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協(xié)議棧、內(nèi)置MAC以及PHY,擁有獨(dú)立的32KB以太網(wǎng)收發(fā)緩存,可供8個(gè)獨(dú)立硬件socket使用。如此配置,真正實(shí)現(xiàn)了All-in-One解決方案,為開發(fā)者提供極大便利。
在封裝規(guī)格上,W55MH32 提供了兩種選擇:QFN68和QFN100。
W55MH32Q采用QFN68封裝版本,尺寸為8x8mm,它擁有36個(gè)GPIO、3個(gè)ADC、12通道DMA、17個(gè)定時(shí)器、2個(gè)I2C、3個(gè)串口、2個(gè)SPI接口(其中1個(gè)帶I2S接口復(fù)用)、1個(gè)CAN以及1個(gè)USB2.0。在保持與同系列其他版本一致的核心性能基礎(chǔ)上,僅減少了部分GPIO以及SDIO接口,其他參數(shù)保持一致,性價(jià)比優(yōu)勢(shì)顯著,尤其適合網(wǎng)關(guān)模組等對(duì)空間布局要求較高的場(chǎng)景。緊湊的尺寸和精簡(jiǎn)化外設(shè)配置,使其能夠在有限空間內(nèi)實(shí)現(xiàn)高效的網(wǎng)絡(luò)連接與數(shù)據(jù)交互,成為物聯(lián)網(wǎng)網(wǎng)關(guān)、邊緣計(jì)算節(jié)點(diǎn)等緊湊型設(shè)備的理想選擇。 同系列還有QFN100封裝的W55MH32L版本,該版本擁有更豐富的外設(shè)資源,適用于需要多接口擴(kuò)展的復(fù)雜工控場(chǎng)景,軟件使用方法一致。更多信息和資料請(qǐng)進(jìn)入http://www.w5500.com/網(wǎng)站或者私信獲取。
此外,本W(wǎng)55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應(yīng)用,涵蓋TCP SSL、HTTP SSL以及MQTT SSL等,為網(wǎng)絡(luò)通信安全再添保障。
為助力開發(fā)者快速上手與深入開發(fā),基于W55MH32Q這顆芯片,WIZnet精心打造了配套開發(fā)板。開發(fā)板集成WIZ-Link芯片,借助一根USB C口數(shù)據(jù)線,就能輕松實(shí)現(xiàn)調(diào)試、下載以及串口打印日志等功能。開發(fā)板將所有外設(shè)全部引出,拓展功能也大幅提升,便于開發(fā)者全面評(píng)估芯片性能。
若您想獲取芯片和開發(fā)板的更多詳細(xì)信息,包括產(chǎn)品特性、技術(shù)參數(shù)以及價(jià)格等,歡迎訪問官方網(wǎng)頁(yè):http://www.w5500.com/,我們期待與您共同探索W55MH32的無(wú)限可能。
第十七章 SPI
1 SPI簡(jiǎn)介
SPI 接口可以配置為支持 SPI 協(xié)議或者支持 I2S 音頻協(xié)議。SPI 接口默認(rèn)工作在 SPI 方式,可以通過軟件把功能從 SPI 模式切換到 I2S 模式。
串行外設(shè)接口(SPI)允許芯片與外部設(shè)備以半/全雙工、同步、串行方式通信。此接口可以被配置成主模式,并為外部從設(shè)備提供通信時(shí)鐘(SCK)。接口還能以多主配置方式工作。
它可用于多種用途,包括使用一條雙向數(shù)據(jù)線的雙線單工同步傳輸,還可使用 CRC 校驗(yàn)的可靠通信。
I2S 也是一種 3 引腳的同步串行接口通訊協(xié)議。它支持四種音頻標(biāo)準(zhǔn),包括飛利浦 I2S 標(biāo)準(zhǔn),MSB和 LSB 對(duì)齊標(biāo)準(zhǔn),以及 PCM 標(biāo)準(zhǔn)。它在半雙工通訊中,可以工作在主和從 2 種模式下。當(dāng)它作為主設(shè)備時(shí),通過接口向外部的從設(shè)備提供時(shí)鐘信號(hào)。
警告:由于 SPI3/I2S3 的部分引腳與 JTAG 引腳共享(SPI3_NSS/I2S3_WS 與 JTDI,SPI3_SCK/I2S3_CK 與 JTDO),因此這些引腳不受 IO 控制器控制,他們(在每次復(fù)位后)被默認(rèn)保留為 JTAG 用途。如果用戶想把引腳配置給 SPI3/I2S3,必須(在調(diào)試時(shí))關(guān)閉 JTAG并切換至 SWD 接口,或者(在標(biāo)準(zhǔn)應(yīng)用時(shí))同時(shí)關(guān)閉 JTAG 和 SWD 接口。
JTAG/SWD 復(fù)用功能重映射。
2 SPI和I2S主要特征
2.1 SPI特征
?3 線全雙工同步傳輸
?帶或不帶第三根雙向數(shù)據(jù)線的雙線單工同步傳輸
?8 或 16 位傳輸幀格式選擇
?主或從操作
?支持多主模式
?8 個(gè)主模式波特率預(yù)分頻系數(shù)(最大為 fPCLK/2)
?從模式頻率(最大為 fPCLK/2)
?主模式和從模式的快速通信
?主模式和從模式下均可以由軟件或硬件進(jìn)行 NSS 管理:主/從操作模式的動(dòng)態(tài)改變
?可編程的時(shí)鐘極性和相位
?可編程的數(shù)據(jù)順序,MSB 在前或 LSB 在前
?可觸發(fā)中斷的專用發(fā)送和接收標(biāo)志
?SPI 總線忙狀態(tài)標(biāo)志
?支持可靠通信的硬件 CRC
······在發(fā)送模式下,CRC 值可以被作為最后一個(gè)字節(jié)發(fā)送
······在全雙工模式中對(duì)接收到的最后一個(gè)字節(jié)自動(dòng)進(jìn)行 CRC 校驗(yàn)
?可觸發(fā)中斷的主模式故障、過載以及 CRC 錯(cuò)誤標(biāo)志
?支持 DMA 功能的 1 字節(jié)發(fā)送和接收緩沖器:產(chǎn)生發(fā)送和接受請(qǐng)求
2.2 I2S功能
?單工通信(僅發(fā)送或接收)
?主或者從操作
?8 位線性可編程預(yù)分頻器,獲得精確的音頻采樣頻率(8KHz 到 96kHz)
?數(shù)據(jù)格式可以是 16 位,24 位或者 32 位
?音頻信道固定數(shù)據(jù)包幀為 16 位(16 位數(shù)據(jù)幀)或 32 位(16、24 或 32 位數(shù)據(jù)幀)
?可編程的時(shí)鐘極性(穩(wěn)定態(tài))
?從發(fā)送模式下的下溢標(biāo)志位和主/從接收模式下的溢出標(biāo)志位
?16 位數(shù)據(jù)寄存器用來(lái)發(fā)送和接收,在通道兩端各有一個(gè)寄存器
?支持的 I2S 協(xié)議:
·······I2S 飛利浦標(biāo)準(zhǔn)
······MSB 對(duì)齊標(biāo)準(zhǔn)(左對(duì)齊)
······LSB 對(duì)齊標(biāo)準(zhǔn)(右對(duì)齊)
?PCM 標(biāo)準(zhǔn)(16 位通道幀上帶長(zhǎng)或短幀同步或者 16 位數(shù)據(jù)幀擴(kuò)展為 32 位通道幀)
?數(shù)據(jù)方向總是 MSB 在先
?發(fā)送和接收都具有 DMA 能力
?主時(shí)鐘可以輸出到外部音頻設(shè)備,比率固定為 256xFs(Fs 為音頻采樣頻率)
3 SPI功能描述
3.1 概述
SPI 的方框圖見下圖:
通常 SPI 通過 4 個(gè)引腳與外部器件相連:
?MISO:主設(shè)備輸入/從設(shè)備輸出引腳。該引腳在從模式下發(fā)送數(shù)據(jù),在主模式下接收數(shù)據(jù)。
?MOSI:主設(shè)備輸出/從設(shè)備輸入引腳。該引腳在主模式下發(fā)送數(shù)據(jù),在從模式下接收數(shù)據(jù)。
?SCK:串口時(shí)鐘,作為主設(shè)備的輸出,從設(shè)備的輸入
?NSS:從設(shè)備選擇。這是一個(gè)可選的引腳,用來(lái)選擇主/從設(shè)備。它的功能是用來(lái)作為“片選引腳”,讓主設(shè)備可以單獨(dú)地與特定從設(shè)備通訊,避免數(shù)據(jù)線上的沖突。從設(shè)備的 NSS 引腳可以由主設(shè)備的一個(gè)標(biāo)準(zhǔn) I/O 引腳來(lái)驅(qū)動(dòng)。一旦被使能(SSOE 位),NSS 引腳也可以作為輸出引腳,并在 SPI 處于主模式時(shí)拉低;此時(shí),所有的 SPI 設(shè)備,如果它們的 NSS 引腳連接到主設(shè)備的 NSS 引腳,則會(huì)檢測(cè)到低電平,如果它們被設(shè)置為 NSS 硬件模式,就會(huì)自動(dòng)進(jìn)入從設(shè)備狀態(tài)。當(dāng)配置為主設(shè)備、NSS 配置為輸入引腳(MSTR=1,SSOE=0)時(shí),如果 NSS 被拉低,則這個(gè) SPI 設(shè)備進(jìn)入主模式失敗狀態(tài):即 MSTR 位被自動(dòng)清除,此設(shè)備進(jìn)入從模式
下圖是一個(gè)單主和單從設(shè)備互連的例子:
單主和單從應(yīng)用
1.這里 NSS 引腳設(shè)置為輸入
MOSI 腳相互連接,MISO 腳相互連接。這樣,數(shù)據(jù)在主和從之間串行地傳輸(MSB 位在前)。
通信總是由主設(shè)備發(fā)起。主設(shè)備通過 MOSI 腳把數(shù)據(jù)發(fā)送給從設(shè)備,從設(shè)備通過 MISO 引腳回傳數(shù)據(jù)。這意味全雙工通信的數(shù)據(jù)輸出和數(shù)據(jù)輸入是用同一個(gè)時(shí)鐘信號(hào)同步的;時(shí)鐘信號(hào)由主設(shè)備通過 SCK 腳提供。
從選擇(NSS)腳管理
有 2 種 NSS 模式:
?軟件 NSS 模式:可以通過設(shè)置 SPI_CR1 寄存器的 SSM 位來(lái)使能這種模式(見圖 212)。在這種模式下 NSS 引腳可以用作它用,而內(nèi)部 NSS 信號(hào)電平可以通過寫 SPI_CR1 的 SSI 位來(lái)驅(qū)動(dòng)。
?硬件 NSS 模式,分兩種情況:
·······NSS 輸出被使能:當(dāng) W55MH32 工作為主 SPI,并且 NSS 輸出已經(jīng)通過 SPI_CR2 寄存器的SSOE 位使能,這時(shí) NSS 引腳被拉低,所有 NSS 引腳與這個(gè)主 SPI 的 NSS 引腳相連并配置為硬件 NSS 的 SPI 設(shè)備,將自動(dòng)變成從 SPI 設(shè)備。當(dāng)一個(gè) SPI 設(shè)備需要發(fā)送廣播數(shù)據(jù),它必須拉低 NSS 信號(hào),以通知所有其它的設(shè)備它是主設(shè)備;如果它不能拉低 NSS,這意味著總線上有另外一個(gè)主設(shè)備在通信,這時(shí)將產(chǎn)生一個(gè)硬件失敗錯(cuò)誤(Hard Fault)。
······NSS 輸出被關(guān)閉:允許操作于多主環(huán)境。
硬件/軟件的從選擇管理
時(shí)鐘信號(hào)的相位和極性
SPI_CR 寄存器的 CPOL 和 CPHA 位,能夠組合成四種可能的時(shí)序關(guān)系。CPOL(時(shí)鐘極性)位控制在沒有數(shù)據(jù)傳輸時(shí)時(shí)鐘的空閑狀態(tài)電平,此位對(duì)主模式和從模式下的設(shè)備都有效。如果 CPOL 被清'0',SCK 引腳在空閑狀態(tài)保持低電平;如果 CPOL 被置'1',SCK 引腳在空閑狀態(tài)保持高電平。如果CPHA(時(shí)鐘相位)位被置'1',SCK 時(shí)鐘的第二個(gè)邊沿(CPOL 位為 0 時(shí)就是下降沿,CPOL 位為'1'時(shí)就是上升沿)進(jìn)行數(shù)據(jù)位的采樣,數(shù)據(jù)在第二個(gè)時(shí)鐘邊沿被鎖存。如果 CPHA 位被清'0',SCK 時(shí)鐘的第一邊沿(CPOL 位為'0'時(shí)就是上升沿,CPOL 位為'1'時(shí)就是下降沿)進(jìn)行數(shù)據(jù)位采樣,數(shù)據(jù)在第一個(gè)時(shí)鐘邊沿被鎖存。CPOL 時(shí)鐘極性和 CPHA 時(shí)鐘相位的組合選擇數(shù)據(jù)捕捉的時(shí)鐘邊沿。
注意:
在改變 CPOL/CPHA 位之前,必須清除 SPE 位將 SPI 禁止。
主和從必須配置成相同的時(shí)序模式。
SCK 的空閑狀態(tài)必須和 SPI_CR1 寄存器指定的極性一致(CPOL 為'1'時(shí),空閑時(shí)應(yīng)上拉 SCK 為高電平;CPOL 為'0'時(shí),空閑時(shí)應(yīng)下拉 SCK 為低電平)。
數(shù)據(jù)幀格式(8 位或 16 位)由 SPI_CR1 寄存器的 DFF 位選擇,并且決定發(fā)送/接收的數(shù)據(jù)長(zhǎng)度。
數(shù)據(jù)時(shí)鐘時(shí)序圖
數(shù)據(jù)幀格式
根據(jù) SPI_CR1 寄存器中的 LSBFIRST 位,輸出數(shù)據(jù)位時(shí)可以 MSB 在先也可以 LSB 在先。
根據(jù) SPI_CR1 寄存器的 DFF 位,每個(gè)數(shù)據(jù)幀可以是 8 位或是 16 位。所選擇的數(shù)據(jù)幀格式對(duì)發(fā)送和/或接收都有效。
3.2 配置SPI為從模式
在從模式下,SCK 引腳用于接收從主設(shè)備來(lái)的串行時(shí)鐘。SPI_CR1 寄存器中 BR[2:0]的設(shè)置不影響數(shù)據(jù)傳輸速率。
注: 建議在主設(shè)備發(fā)送時(shí)鐘之前使能 SPI 從設(shè)備,否則可能會(huì)發(fā)生意外的數(shù)據(jù)傳輸。在通信時(shí)鐘的第一個(gè)邊沿到來(lái)之前或正在進(jìn)行的通信結(jié)束之前,從設(shè)備的數(shù)據(jù)寄存器必須就緒。在使能從設(shè)備和主設(shè)備之前,通信時(shí)鐘的極性必須處于穩(wěn)定的數(shù)值。
請(qǐng)按照以下步驟配置 SPI 為從模式:
配置步驟
1. 設(shè)置 DFF 位以定義數(shù)據(jù)幀格式為 8 位或 16 位。
2. 選擇 CPOL 和 CPHA 位來(lái)定義數(shù)據(jù)傳輸和串行時(shí)鐘之間的相位關(guān)系(見圖 213)。為保證正確的數(shù)據(jù)傳輸,從設(shè)備和主設(shè)備的 CPOL 和 CPHA 位必須配置成相同的方式。
3. 幀格式(SPI_CR1 寄存器中的 LSBFIRST 位定義的”MSB 在前”還是”LSB 在前”)必須與主設(shè)備相同。
4. 硬件模式下(參考從選擇(NSS)腳管理部分),在完整的數(shù)據(jù)幀(8 位或 16 位)傳輸過程中,NSS引腳必須為低電平。在 NSS 軟件模式下,設(shè)置 SPI_CR1 寄存器中的 SSM 位并清除 SSI 位。
5. 清除 MSTR 位、設(shè)置 SPE 位(SPI_CR1 寄存器),使相應(yīng)引腳工作于 SPI 模式下。在這個(gè)配置中,MOSI 引腳是數(shù)據(jù)輸入,MISO 引腳是數(shù)據(jù)輸出。
數(shù)據(jù)發(fā)送
過程在寫操作中,數(shù)據(jù)字被并行地寫入發(fā)送緩沖器。
當(dāng)從設(shè)備收到時(shí)鐘信號(hào),并且在 MOSI 引腳上出現(xiàn)第一個(gè)數(shù)據(jù)位時(shí),發(fā)送過程開始(譯注:此時(shí)第一個(gè)位被發(fā)送出去)。余下的位(對(duì)于 8 位數(shù)據(jù)幀格式,還有 7 位;對(duì)于 16 位數(shù)據(jù)幀格式,還有 15位)被裝進(jìn)移位寄存器。當(dāng)發(fā)送緩沖器中的數(shù)據(jù)傳輸?shù)揭莆患拇嫫鲿r(shí),SPI_SP 寄存器的 TXE 標(biāo)志被設(shè)置,如果設(shè)置了 SPI_CR2 寄存器的 TXEIE 位,將會(huì)產(chǎn)生中斷。
數(shù)據(jù)接收過程
對(duì)于接收器,當(dāng)數(shù)據(jù)接收完成時(shí):
移位寄存器中的數(shù)據(jù)傳送到接收緩沖器,SPI_SR 寄存器中的 RXNE 標(biāo)志被設(shè)置。
如果設(shè)置了 SPI_CR2 寄存器中的 RXNEIE 位,則產(chǎn)生中斷。
在最后一個(gè)采樣時(shí)鐘邊沿后,RXNE 位被置'1',移位寄存器中接收到的數(shù)據(jù)字節(jié)被傳送到接收緩沖器。當(dāng)讀 SPI_DR 寄存器時(shí),SPI 設(shè)備返回這個(gè)接收緩沖器的數(shù)值。讀 SPI_DR 寄存器時(shí),RXNE 位被清除。
3.3 配置SPI為主模式
在主配置時(shí),在 SCK 腳產(chǎn)生串行時(shí)鐘。
配置步驟
1. 通過 SPI_CR1 寄存器的 BR[2:0]位定義串行時(shí)鐘波特率。
2. 選擇 CPOL 和 CPHA 位,定義數(shù)據(jù)傳輸和串行時(shí)鐘間的相位關(guān)系(見圖 213)。
3. 設(shè)置 DFF 位來(lái)定義 8 位或 16 位數(shù)據(jù)幀格式。
4. 配置 SPI_CR1 寄存器的 LSBFIRST 位定義幀格式。
5. 如果需要 NSS 引腳工作在輸入模式,硬件模式下,在整個(gè)數(shù)據(jù)幀傳輸期間應(yīng)把 NSS 腳連接到高電平;在軟件模式下,需設(shè)置 SPI_CR1 寄存器的 SSM 位和 SSI 位。如果 NSS 引腳工作在輸出模式,則只需設(shè)置 SSOE 位。
必須設(shè)置 MSTR 位和 SPE 位(只當(dāng) NSS 腳被連到高電平,這些位才能保持置位)。在這個(gè)配置中,MOSI 引腳是數(shù)據(jù)輸出,而 MISO 引腳是數(shù)據(jù)輸入。
數(shù)據(jù)發(fā)送過程
當(dāng)寫入數(shù)據(jù)至發(fā)送緩沖器時(shí),發(fā)送過程開始。
在發(fā)送第一個(gè)數(shù)據(jù)位時(shí),數(shù)據(jù)字被并行地(通過內(nèi)部總線)傳入移位寄存器,而后串行地移出到MOSI 腳上;MSB 在先還是 LSB 在先,取決于 SPI_CR1 寄存器中的 LSBFIRST 位的設(shè)置。數(shù)據(jù)從發(fā)送緩沖器傳輸?shù)揭莆患拇嫫鲿r(shí) TXE 標(biāo)志將被置位,如果設(shè)置了 SPI_CR1 寄存器中的 TXEIE位,將產(chǎn)生中斷。
數(shù)據(jù)接收過程
對(duì)于接收器來(lái)說,當(dāng)數(shù)據(jù)傳輸完成時(shí):
傳送移位寄存器里的數(shù)據(jù)到接收緩沖器,并且 RXNE 標(biāo)志被置位。
如果設(shè)置了 SPI_CR2 寄存器中的 RXNEIE 位,則產(chǎn)生中斷。
在最后采樣時(shí)鐘沿,RXNE 位被設(shè)置,在移位寄存器中接收到的數(shù)據(jù)字被傳送到接收緩沖器。讀SPI_DR 寄存器時(shí),SPI 設(shè)備返回接收緩沖器中的數(shù)據(jù)。讀 SPI_DR 寄存器將清除 RXNE 位。
一旦傳輸開始,如果下一個(gè)將發(fā)送的數(shù)據(jù)被放進(jìn)了發(fā)送緩沖器,就可以維持一個(gè)連續(xù)的傳輸流。在試圖寫發(fā)送緩沖器之前,需確認(rèn) TXE 標(biāo)志應(yīng)該為'1'。
注: 在 NSS 硬件模式下,從設(shè)備的 NSS 輸入由 NSS 引腳控制或另一個(gè)由軟件驅(qū)動(dòng)的 GPIO 引腳控制。
3.4 配置SPI為單工通信
SPI 模塊能夠以兩種配置工作于單工方式:
?1 條時(shí)鐘線和 1 條雙向數(shù)據(jù)線;
?1 條時(shí)鐘線和 1 條數(shù)據(jù)線(只接收或只發(fā)送);
1 條時(shí)鐘線和 1 條雙向數(shù)據(jù)線(BIDIMODE=1)
設(shè)置 SPI_CR1 寄存器中的 BIDIMODE 位而啟用此模式。在這個(gè)模式下,SCK 引腳作為時(shí)鐘,主設(shè)備使用 MOSI 引腳而從設(shè)備使用 MISO 引腳作為數(shù)據(jù)通信。傳輸?shù)姆较蛴?SPI_CR1 寄存器里的 BIDIOE控制,當(dāng)這個(gè)位是'1'的時(shí)候,數(shù)據(jù)線是輸出,否則是輸入。
1 條時(shí)鐘和 1 條單向數(shù)據(jù)線(BIDIMODE=0)
?在這個(gè)模式下,SPI 模塊可以或者作為只發(fā)送,或者作為只接收。
?只發(fā)送模式類似于全雙工模式(BIDIMODE=0,RXONLY=0):數(shù)據(jù)在發(fā)送引腳(主模式時(shí)是 MOSI、從模式時(shí)是 MISO)上傳輸,而接收引腳(主模式時(shí)是 MISO、從模式時(shí)是 MOSI)可以作為通用的I/O 使用。此時(shí),軟件不必理會(huì)接收緩沖器中的數(shù)據(jù)(如果讀出數(shù)據(jù)寄存器,它不包含任何接收數(shù)據(jù))。
?在只接收模式,可以通過設(shè)置 SPI_CR2 寄存器的 RXONLY 位而關(guān)閉 SPI 的輸出功能;此時(shí),發(fā)送引腳(主模式時(shí)是 MOSI、從模式時(shí)是 MISO)被釋放,可以作為其它功能使用。
配置并使能 SPI 模塊為只接收模式的方式是:
?在主模式時(shí),一旦使能 SPI,通信立即啟動(dòng),當(dāng)清除 SPE 位時(shí)立即停止當(dāng)前的接收。在此模式下,不必讀取 BSY 標(biāo)志,在 SPI 通信期間這個(gè)標(biāo)志始終為'1'。
?在從模式時(shí),只要 NSS 被拉低(或在 NSS 軟件模式時(shí),SSI 位為'0')同時(shí) SCK 有時(shí)鐘脈沖,SPI就一直在接收。
3.5 數(shù)據(jù)發(fā)送與接收過程
接收與發(fā)送緩沖器
在接收時(shí),接收到的數(shù)據(jù)被存放在一個(gè)內(nèi)部的接收緩沖器中;在發(fā)送時(shí),在被發(fā)送之前,數(shù)據(jù)將首先被存放在一個(gè)內(nèi)部的發(fā)送緩沖器中。對(duì) SPI_DR 寄存器的讀操作,將返回接收緩沖器的內(nèi)容;寫入 SPI_DR 寄存器的數(shù)據(jù)將被寫入發(fā)送緩沖器中。
主模式下開始傳輸
?全雙工模式(BIDIMODE=0 并且 RXONLY=0)
······當(dāng)寫入數(shù)據(jù)到 SPI_DR 寄存器(發(fā)送緩沖器)后,傳輸開始;
······在傳送第一位數(shù)據(jù)的同時(shí),數(shù)據(jù)被并行地從發(fā)送緩沖器傳送到 8 位的移位寄存器中,然后按順序被串行地移位送到 MOSI 引腳上;
······與此同時(shí),在 MISO 引腳上接收到的數(shù)據(jù),按順序被串行地移位進(jìn)入 8 位的移位寄存器中,然后被并行地傳送到 SPI_DR 寄存器(接收緩沖器)中。
?單向的只接收模式(BIDIMODE=0 并且 RXONLY=1)
········SPE=1 時(shí),傳輸開始;
······只有接收器被激活,在 MISO 引腳上接收到的數(shù)據(jù),按順序被串行地移位進(jìn)入 8 位的移位寄存器中,然后被并行地傳送到 SPI_DR 寄存器(接收緩沖器)中。
······雙向模式,發(fā)送時(shí)(BIDIMODE=1 并且 BIDIOE=1)
······當(dāng)寫入數(shù)據(jù)到 SPI_DR 寄存器(發(fā)送緩沖器)后,傳輸開始;
·······在傳送第一位數(shù)據(jù)的同時(shí),數(shù)據(jù)被并行地從發(fā)送緩沖器傳送到 8 位的移位寄存器中,然后按順序被串行地移位送到 MOSI 引腳上;
······不接收數(shù)據(jù)。
?雙向模式,接收時(shí)(BIDIMODE=1 并且 BIDIOE=0)
······SPE=1 并且 BIDIOE=0 時(shí),傳輸開始;
······在 MOSI 引腳上接收到的數(shù)據(jù),按順序被串行地移位進(jìn)入 8 位的移位寄存器中,然后被并行地傳送到 SPI_DR 寄存器(接收緩沖器)中。
······不激活發(fā)送器,沒有數(shù)據(jù)被串行地送到 MOSI 引腳上。
從模式下開始傳輸
?全+雙工模式(BIDIMODE=0 并且 RXONLY=0)
······當(dāng)從設(shè)備接收到時(shí)鐘信號(hào)并且第一個(gè)數(shù)據(jù)位出現(xiàn)在它的 MOSI 時(shí),數(shù)據(jù)傳輸開始,隨后的數(shù)據(jù)位依次移動(dòng)進(jìn)入移位寄存器;
······與此同時(shí),在傳輸?shù)谝粋€(gè)數(shù)據(jù)位時(shí),發(fā)送緩沖器中的數(shù)據(jù)被并行地傳送到 8 位的移位寄存器,隨后被串行地發(fā)送到 MISO 引腳上。軟件必須保證在 SPI 主設(shè)備開始數(shù)據(jù)傳輸之前在發(fā)送寄存器中寫入要發(fā)送的數(shù)據(jù)。
?單向的只接收模式(BIDIMODE=0 并且 RXONLY=1)
·······當(dāng)從設(shè)備接收到時(shí)鐘信號(hào)并且第一個(gè)數(shù)據(jù)位出現(xiàn)在它的 MOSI 時(shí),數(shù)據(jù)傳輸開始,隨后數(shù)據(jù)位依次移動(dòng)進(jìn)入移位寄存器;
······不啟動(dòng)發(fā)送器,沒有數(shù)據(jù)被串行地傳送到 MISO 引腳上。
?雙向模式,發(fā)送時(shí)(BIDIMODE=1 并且 BIDIOE=1)
······當(dāng)從設(shè)備接收到時(shí)鐘信號(hào)并且發(fā)送緩沖器中的第一個(gè)數(shù)據(jù)位被傳送到MISO引腳上的時(shí)候,數(shù)據(jù)傳輸開始;
······在第一個(gè)數(shù)據(jù)位被傳送到 MISO 引腳上的同時(shí),發(fā)送緩沖器中要發(fā)送的數(shù)據(jù)被平行地傳送到 8 位的移位寄存器中,隨后被串行地發(fā)送到 MISO 引腳上。軟件必須保證在 SPI 主設(shè)備開始數(shù)據(jù)傳輸之前在發(fā)送寄存器中寫入要發(fā)送的數(shù)據(jù);
······不接收數(shù)據(jù)。
?雙向模式,接收時(shí)(BIDIMODE=1 并且 BIDIOE=0)
······當(dāng)從設(shè)備接收到時(shí)鐘信號(hào)并且第一個(gè)數(shù)據(jù)位出現(xiàn)在它的 MOSI 時(shí),數(shù)據(jù)傳輸開始;
······從 MISO 引腳上接收到的數(shù)據(jù)被串行地傳送到 8 位的移位寄存器中,然后被平行地傳送到SPI_DR 寄存器(接收緩沖器);
······不啟動(dòng)發(fā)送器,沒有數(shù)據(jù)被串行地傳送到 MISO 引腳上。
處理數(shù)據(jù)的發(fā)送與接收
當(dāng)數(shù)據(jù)從發(fā)送緩沖器傳送到移位寄存器時(shí),設(shè)置 TXE 標(biāo)志(發(fā)送緩沖器空),它表示內(nèi)部的發(fā)送緩沖器可以接收下一個(gè)數(shù)據(jù);如果在 SPI_CR2 寄存器中設(shè)置了 TXEIE 位,則此時(shí)會(huì)產(chǎn)生一個(gè)中斷;寫入 SPI_DR 寄存器即可清除 TXE 位。
注: 在寫入發(fā)送緩沖器之前,軟件必須確認(rèn) TXE 標(biāo)志為'1',否則新的數(shù)據(jù)會(huì)覆蓋已經(jīng)在發(fā)送緩沖器中的數(shù)據(jù)。
在采樣時(shí)鐘的最后一個(gè)邊沿,當(dāng)數(shù)據(jù)被從移位寄存器傳送到接收緩沖器時(shí),設(shè)置 RXNE 標(biāo)志(接收緩沖器非空);它表示數(shù)據(jù)已經(jīng)就緒,可以從 SPI_DR 寄存器讀出;如果在 SPI_CR2 寄存器中設(shè)置了 RXNEIE 位,則此時(shí)會(huì)產(chǎn)生一個(gè)中斷;讀出 SPI_DR 寄存器即可清除 RXNIE 標(biāo)志位。
在一些配置中,傳輸最后一個(gè)數(shù)據(jù)時(shí),可以使用 BSY 標(biāo)志等待數(shù)據(jù)傳輸?shù)慕Y(jié)束。
主或從模式下(BIDIMODE=0 并且 RXONLY=0)全雙工發(fā)送和接收過程模式
1. 設(shè)置 SPE 位為'1',使能 SPI 模塊;
2. 在 SPI_DR 寄存器中寫入第一個(gè)要發(fā)送的數(shù)據(jù),這個(gè)操作會(huì)清除 TXE 標(biāo)志;
3. 等待 TXE=1,然后寫入第二個(gè)要發(fā)送的數(shù)據(jù)。等待 RXNE=1,然后讀出 SPI_DR 寄存器并獲得第一個(gè)接收到的數(shù)據(jù),讀 SPI_DR 的同時(shí)清除了 RXNE 位。重復(fù)這些操作,發(fā)送后續(xù)的數(shù)據(jù)同時(shí)接收 n-1 個(gè)數(shù)據(jù);
4. 等待 RXNE=1,然后接收最后一個(gè)數(shù)據(jù);
5. 等待 TXE=1,在 BSY=0 之后關(guān)閉 SPI 模塊。
也可以在響應(yīng) RXNE 或 TXE 標(biāo)志的上升沿產(chǎn)生的中斷的處理程序中實(shí)現(xiàn)這個(gè)過程。
主模式、全雙工模式下(BIDIMODE=0 并且 RXONLY=0)連續(xù)傳輸時(shí),TXE/RXNE/BSY 的變化示意圖
從模式、全雙工模式下(BIDIMODE=0 并且 RXONLY=0)連續(xù)傳輸時(shí),TXE/RXNE/BSY 的變化示意圖
只發(fā)送過程(BIDIMODE=0 并且 RXONLY=0)
在此模式下,傳輸過程可以簡(jiǎn)要說明如下,使用 BSY 位等待傳輸?shù)慕Y(jié)束(見下兩圖):
1. 設(shè)置 SPE 位為'1',使能 SPI 模塊;
2. 在 SPI_DR 寄存器中寫入第一個(gè)要發(fā)送的數(shù)據(jù),這個(gè)操作會(huì)清除 TXE 標(biāo)志;
3. 等待 TXE=1,然后寫入第二個(gè)要發(fā)送的數(shù)據(jù)。重復(fù)這個(gè)操作,發(fā)送后續(xù)的數(shù)據(jù);
4. 寫入最后一個(gè)數(shù)據(jù)到 SPI_DR 寄存器之后,等待 TXE=1;然后等待 BSY=0,這表示最后一個(gè)數(shù)據(jù)的傳輸已經(jīng)完成。
也可以在響應(yīng) TXE 標(biāo)志的上升沿產(chǎn)生的中斷的處理程序中實(shí)現(xiàn)這個(gè)過程。
注:
對(duì)于不連續(xù)的傳輸,在寫入 SPI_DR 寄存器的操作與設(shè)置 BSY 位之間有 2 個(gè) APB 時(shí)鐘周期的延遲,因此在只發(fā)送模式下,寫入最后一個(gè)數(shù)據(jù)后,最好先等待 TXE=1,然后再等待 BSY=0。
只發(fā)送模式下,在傳輸 2 個(gè)數(shù)據(jù)之后,由于不會(huì)讀出接收到的數(shù)據(jù),SPI_SR 寄存器中的 OVR位會(huì)變?yōu)?1'。軟件不必理會(huì)這個(gè) OVR 標(biāo)志位。
主設(shè)備只發(fā)送模式(BIDIMODE=0 并且 RXONLY=0)下連續(xù)傳輸時(shí),,TXE/BSY 變化示意圖
從設(shè)備只發(fā)送模式(BIDIMODE=0 并且 RXONLY=0)下連續(xù)傳輸時(shí),TXE/BSY 變化示意圖
雙向發(fā)送過程(BIDIMODE=1 并且 BIDIOE=1)
在此模式下,操作過程類似于只發(fā)送模式,不同的是:在使能 SPI 模塊之前,需要在 SPI_CR2 寄存器中同時(shí)設(shè)置 BIDIMODE 和 BIDIOE 位為'1'。
單向只接收模式(BIDIMODE=0 并且 RXONLY=1)在此模式下,傳輸過程可以簡(jiǎn)要說明如下(見):
在 SPI_CR2 寄存器中,設(shè)置 RXONLY=1;
設(shè)置 SPE=1,使能 SPI 模塊:
主模式下,立刻產(chǎn)生 SCK 時(shí)鐘信號(hào),在關(guān)閉 SPI(SPE=0)之前,不斷地接收串行數(shù)據(jù);
從模式下,當(dāng) SPI 主設(shè)備拉低 NSS 信號(hào)并產(chǎn)生 SCK 時(shí)鐘時(shí),接收串行數(shù)據(jù)。
等待 RXNE=1,然后讀出 SPI_DR 寄存器以獲得收到的數(shù)據(jù)(同時(shí)會(huì)清除 RXNE 位)。重復(fù)這個(gè)操作接收所有數(shù)據(jù)。也可以在響應(yīng) RXNE 標(biāo)志的上升沿產(chǎn)生的中斷的處理程序中實(shí)現(xiàn)這個(gè)過程。
注: 如果在最后一個(gè)數(shù)據(jù)傳輸結(jié)束后關(guān)閉 SPI 模塊,請(qǐng)按照第 16.3.8 節(jié)的建議操作
只接收模式(BIDIMODE=0 并且 RXONLY=1)下連續(xù)傳輸時(shí),RXNE 變化示意圖
單向接收過程(BIDIMODE=1 并且 BIDIOE=0)
在此模式下,操作過程類似于只接收模式,不同的是:在使能 SPI 模塊之前,需要在 SPI_CR2 寄存器中設(shè)置 BIDIMODE 為'1'并清除 BIDIOE 位為'0'。
連續(xù)和非連續(xù)傳輸
當(dāng)在主模式下發(fā)送數(shù)據(jù)時(shí),如果軟件足夠快,能夠在檢測(cè)到每次 TXE 的上升沿(或 TXE 中斷),并立即在正在進(jìn)行的傳輸結(jié)束之前寫入 SPI_DR 寄存器,則能夠?qū)崿F(xiàn)連續(xù)的通信;此時(shí),在每個(gè)數(shù)據(jù)項(xiàng)的傳輸之間的 SPI 時(shí)鐘保持連續(xù),同時(shí) BSY 位不會(huì)被清除。
如果軟件不夠快,則會(huì)導(dǎo)致不連續(xù)的通信;這時(shí),在每個(gè)數(shù)據(jù)傳輸之間會(huì)被清除(見下圖)。在主模式的只接收模式下(RXONLY=1),通信總是連續(xù)的,而且 BSY 標(biāo)志始終為'1'。
在從模式下,通信的連續(xù)性由 SPI 主設(shè)備決定。不管怎樣,即使通信是連續(xù)的,BSY 標(biāo)志會(huì)在每個(gè)數(shù)據(jù)項(xiàng)之間至少有一個(gè) SPI 時(shí)鐘周期為低。
非連續(xù)傳輸發(fā)送(BIDIMODE=0 并且 RXONLY=0)時(shí),TXE/BSY 變化示意圖
4 利用DMA的SPI通信
為了達(dá)到最大通信速度,需要及時(shí)往 SPI 發(fā)送緩沖器填數(shù)據(jù),同樣接收緩沖器中的數(shù)據(jù)也必須及時(shí)讀走以防止溢出。為了方便高速率的數(shù)據(jù)傳輸,SPI 實(shí)現(xiàn)了一種采用簡(jiǎn)單的請(qǐng)求/應(yīng)答的 DMA 機(jī)制。
當(dāng) SPI_CR2 寄存器上的對(duì)應(yīng)使能位被設(shè)置時(shí),SPI 模塊可以發(fā)出 DMA 傳輸請(qǐng)求。發(fā)送緩沖器和接收緩沖器亦有各自的 DMA 請(qǐng)求。
發(fā)送時(shí),在每次 TXE 被設(shè)置為'1'時(shí)發(fā)出 DMA 請(qǐng)求,DMA 控制器則寫數(shù)據(jù)至 SPI_DR 寄存器,TXE 標(biāo)志因此而被清除。
接收時(shí),在每次 RXNE 被設(shè)置為'1'時(shí)發(fā)出 DMA 請(qǐng)求,DMA 控制器則從 SPI_DR 寄存器讀出數(shù)據(jù),RXNE 標(biāo)志因此而被清除。當(dāng)只使用 SPI 發(fā)送數(shù)據(jù)時(shí),只需使能 SPI 的發(fā)送 DMA 通道。此時(shí),因?yàn)闆]有讀取收到的數(shù)據(jù),OVR被置為'1'(譯注:軟件不必理會(huì)這個(gè)標(biāo)志)。當(dāng)只使用 SPI 接收數(shù)據(jù)時(shí),只需使能 SPI 的接收 DMA 通道。
在發(fā)送模式下,當(dāng) DMA 已經(jīng)傳輸了所有要發(fā)送的數(shù)據(jù)(DMA_ISR 寄存器的 TCIF 標(biāo)志變?yōu)?1')后,可以通過監(jiān)視 BSY 標(biāo)志以確認(rèn) SPI 通信結(jié)束,這樣可以避免在關(guān)閉 SPI 或進(jìn)入停止模式時(shí),破壞最后一個(gè)數(shù)據(jù)的傳輸。因此軟件需要先等待 TXE=1,然后等待 BSY=0。
注: 在不連續(xù)的通信中,在寫數(shù)據(jù)到 SPI_DR 的操作與 BSY 位被置為'1'之間,有 2 個(gè) APB 時(shí)鐘周期的延遲,因此,在寫完最后一個(gè)數(shù)據(jù)后需要先等待 TXE=1 再等待 BSY=0。
使用 DMA 發(fā)送
使用 DMA 接收
5 SPI中斷
SPI 中斷請(qǐng)求
中斷事件 | 事件標(biāo)志 | 使能控制位 |
發(fā)送緩沖器空標(biāo)志 | TXE | TXEIE |
接收緩沖器非空標(biāo)志 | RXNE | RXNEIE |
主模式失效事件 | MODF | ERRIE |
溢出錯(cuò)誤 | OVR | ERRIE |
CRC 錯(cuò)誤標(biāo)志 | CRCERR | ERRIE |
6 例程設(shè)計(jì)
6.1 SPI_DMA例程
1.UART 模塊:配置 USART1,將printf輸出重定向到該串口,用于輸出系統(tǒng)時(shí)鐘信息與測(cè)試提示。
2.SPI 模塊:使能 SPI1 和 GPIOA 時(shí)鐘,配置相關(guān)引腳。
初始化 SPI1,設(shè)置為雙線全雙工、主模式,數(shù)據(jù)大小為 8 位等參數(shù)。
3.DMA 模塊:使能 DMA1 時(shí)鐘,配置 DMA1 通道 2 用于 SPI1 的接收,通道 3 用于 SPI1 的發(fā)送。
分別設(shè)置通道的外設(shè)地址、內(nèi)存地址、數(shù)據(jù)傳輸方向等參數(shù)。
使能 SPI1 的 DMA 收發(fā)請(qǐng)求,但初始時(shí)禁用 DMA 通道。
4.主函數(shù)模塊:初始化延時(shí)函數(shù)和 UART。
int main(void) { RCC_ClocksTypeDef clocks; uint16_t i; // 初始化延時(shí)和串口 delay_init(); UART_Configuration(115200); // 打印系統(tǒng)時(shí)鐘信息 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"); // 初始化緩沖區(qū):發(fā)送數(shù)據(jù)為0x01~0xFF,接收緩沖區(qū)清零 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發(fā)送測(cè)試 ================== 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); // 啟用發(fā)送通道 printf("DMA channel 3 for SPI Tx is enabled.n"); // 等待發(fā)送完成(查詢傳輸完成標(biāo)志) while (!DMA_GetFlagStatus(DMA1_FLAG_TC3)) { printf("DMA transfer in progress...n"); delay_ms(10); } printf("DMA transfer completed.n"); // 清除標(biāo)志并禁用通道 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無(wú)效) printf("Chip select (CS) is pulled high.n"); // 打印發(fā)送數(shù)據(jù) 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接收測(cè)試(如需自發(fā)自收需硬件環(huán)路) ================== printf("Start SPI DMA reception...n"); GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 再次拉低片選(僅示例,實(shí)際需硬件支持) printf("Chip select (CS) is pulled low.n"); DMA_Cmd(DMA1_Channel2, ENABLE); // 啟用接收通道 printf("DMA channel 2 for SPI Rx is enabled.n"); // 等待接收完成(假設(shè)發(fā)送后立即接收,需根據(jù)硬件調(diào)整) 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); // 拉高片選 // 打印接收數(shù)據(jù)(需硬件環(huán)路才能看到有效數(shù)據(jù)) 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); // 主循環(huán)保持運(yùn)行 }
?獲取系統(tǒng)時(shí)鐘頻率并輸出。
?填充發(fā)送緩沖區(qū),清空接收緩沖區(qū)。
?配置 SPI 和 DMA。
?拉低片選信號(hào),使能 DMA 發(fā)送通道,等待發(fā)送完成后清除標(biāo)志位、禁用通道,最后拉高片選信號(hào)。
6.2 SPI_MasterSlaveDma例程
該例程是一個(gè)基于 W55MH32 的 SPI DMA 通信測(cè)試程序,支持主從模式切換,以下是其詳細(xì)運(yùn)行過程:
1. 初始化階段
(1)時(shí)鐘配置
// 時(shí)鐘配置函數(shù):?jiǎn)⒂肏SE并配置PLL倍頻 void RCC_ClkConfiguration(void) { RCC_DeInit(); // 復(fù)位RCC配置到默認(rèn)狀態(tài) // 啟用外部高速時(shí)鐘(HSE) RCC_HSEConfig(RCC_HSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); // 等待HSE穩(wěn)定 // 禁用PLL并配置PLL參數(shù)(HSE×27倍頻,假設(shè)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鎖定 // 設(shè)置系統(tǒng)時(shí)鐘源及總線分頻 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // 使用PLL作為系統(tǒng)時(shí)鐘 RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB總線時(shí)鐘 = SYSCLK (216MHz) RCC_PCLK1Config(RCC_HCLK_Div2); // APB1總線時(shí)鐘 = HCLK/2 (108MHz) RCC_PCLK2Config(RCC_HCLK_Div1); // APB2總線時(shí)鐘 = HCLK (216MHz) // 啟用內(nèi)部低速(LSI)和高速(HSI)時(shí)鐘(供其他外設(shè)使用) RCC_LSICmd(ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); RCC_HSICmd(ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET); }
?調(diào)用RCC_ClkConfiguration():?jiǎn)⒂猛獠扛咚贂r(shí)鐘(HSE),配置 PLL 為 HSE×27 倍頻(最終 SYSCLK=72MHz)。
······配置 AHB 時(shí)鐘(HCLK)=72MHz,APB1(PCLK1)=36MHz,APB2(PCLK2)=72MHz。
·······啟用內(nèi)部低速時(shí)鐘(LSI)和高速時(shí)鐘(HSI)。
(2)串口初始化
?調(diào)用UART_Configuration(115200):配置 USART1 波特率為 115200,8 位數(shù)據(jù)位,1 位停止位,無(wú)校驗(yàn)。
······初始化 GPIOA 的 Pin9(TX)和 Pin10(RX)為復(fù)用推挽輸出和浮空輸入。
······使能 USART1。
(3)打印時(shí)鐘信息
通過RCC_GetClocksFreq()獲取并打印系統(tǒng)各時(shí)鐘頻率:
SYSCLK: 72.0Mhz, HCLK: 72.0Mhz, PCLK1: 36.0Mhz, PCLK2: 72.0Mhz, ADCCLK: 36.0Mhz
2. 數(shù)據(jù)準(zhǔn)備階段
初始化發(fā)送緩沖區(qū):
for (i = 0; i < SPI_BUFF_SIZE; i++) { SPI_TX_BUFF[i] = i + 1; // 填充數(shù)據(jù)0x01~0xFF }
清空接收緩沖區(qū):
memset(SPI_RX_BUFF, 0, sizeof(SPI_RX_BUFF));
3. SPI 與 DMA 配置
(1)模式選擇
?通過條件編譯選擇主模式(SPI_MASTER)或從模式(SPI_SLAVE)。當(dāng)前代碼默認(rèn)為主模式。
(2)GPIO 與時(shí)鐘使能
?主模式(SPI3):使能 SPI3、GPIOA、GPIOB、DMA2 時(shí)鐘。
······配置 GPIOB 的 Pin3(MOSI)、Pin4(MISO)、Pin5(SCK)為復(fù)用推挽輸出。
······配置 GPIOA 的 Pin15 為片選(CS)輸出,初始拉高。
(3)DMA 配置
?接收通道(DMA2_Channel1):外設(shè)地址為SPI3->DR,內(nèi)存地址為SPI_RX_BUFF。
······方向?yàn)橥庠O(shè)到內(nèi)存,數(shù)據(jù)寬度為 8 位,循環(huán)模式關(guān)閉。
······使能 DMA 傳輸完成中斷。
?發(fā)送通道(DMA2_Channel2):外設(shè)地址為SPI3->DR,內(nèi)存地址為SPI_TX_BUFF。
······方向?yàn)閮?nèi)存到外設(shè),其他參數(shù)與接收通道一致。
(4)SPI 初始化
?主模式配置:全雙工模式,8 位數(shù)據(jù),CPOL = 低,CPHA = 第一邊沿(模式 0)。
······波特率預(yù)分頻為 8(SPI 時(shí)鐘 = 72MHz/8=9MHz)。
······使能 SPI3。
4. 數(shù)據(jù)傳輸階段
(1)觸發(fā) DMA 傳輸
void SpiDmaTrans(unsigned char *sendBuffer, unsigned char *reciveBuffer, unsigned int len) { // 主模式下拉低片選信號(hào)(假設(shè)PA15為片選引腳) #ifdef SPI_MASTER GPIO_ResetBits(GPIOA, GPIO_Pin_15); // 拉低片選,選中從設(shè)備 #endif // 禁用舊的DMA請(qǐng)求和通道(確保配置干凈) 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緩沖區(qū)地址 UseTxChannel->CMAR = (uint32_t)sendBuffer; // 發(fā)送緩沖區(qū)地址 UseRxChannel->CMAR = (uint32_t)reciveBuffer; // 接收緩沖區(qū)地址 // 設(shè)置傳輸數(shù)據(jù)長(zhǎng)度(256字節(jié)) UseTxChannel->CNDTR = len; UseRxChannel->CNDTR = len; // 重置傳輸完成標(biāo)志 SpiTransFinish = 0; // 啟用DMA通道和SPI的DMA請(qǐng)求 DMA_Cmd(UseRxChannel, ENABLE); // 先啟用接收通道(確保同步) DMA_Cmd(UseTxChannel, ENABLE); SPI_I2S_DMACmd(UseSpi, SPI_I2S_DMAReq_Rx, ENABLE); // 使能SPI接收DMA請(qǐng)求 SPI_I2S_DMACmd(UseSpi, SPI_I2S_DMAReq_Tx, ENABLE); // 使能SPI發(fā)送DMA請(qǐng)求 }
?調(diào)用SpiDmaTrans():拉低片選信號(hào)(GPIOA Pin15)。
······配置 DMA 緩沖區(qū)地址和數(shù)據(jù)長(zhǎng)度(256 字節(jié))。
······啟用 DMA 通道和 SPI 的 DMA 請(qǐng)求。
(2)中斷處理
?傳輸完成中斷(UseSpiTransFinishHanlder):清除 DMA 完成標(biāo)志,禁用 DMA 通道。
······拉高片選信號(hào)(主模式)。
······設(shè)置SpiTransFinish標(biāo)志,通知主循環(huán)傳輸完成。
5. 數(shù)據(jù)驗(yàn)證與循環(huán)
?主循環(huán)邏輯:等待 DMA 傳輸完成(SpiTransFinish標(biāo)志)。
·······比較發(fā)送與接收數(shù)據(jù):若不一致,打印錯(cuò)誤信息并進(jìn)入死循環(huán)。
--若一致,打印>>success并延時(shí) 10ms 后重試。
7 下載驗(yàn)證
7.1 SPI_DMA例程
程序啟動(dòng)
通過串口輸出系統(tǒng)時(shí)鐘頻率信息,可確認(rèn)時(shí)鐘配置是否正確。
顯示測(cè)試提示信息,表明開始進(jìn)行 SPI 的 DMA 數(shù)據(jù)傳輸測(cè)試。
SPI 數(shù)據(jù)發(fā)送
拉低片選信號(hào)(GPIOA 的引腳 4),選中 SPI 從設(shè)備,準(zhǔn)備傳輸數(shù)據(jù)。
使能 DMA 發(fā)送通道,開始通過 SPI1 將發(fā)送緩沖區(qū)的數(shù)據(jù)傳輸?shù)綇脑O(shè)備。
等待 DMA 傳輸完成,此過程中硬件上 SPI 總線會(huì)有相應(yīng)信號(hào)傳輸。
傳輸完成后,清除 DMA 傳輸完成標(biāo)志,禁用 DMA 發(fā)送通道。
拉高片選信號(hào),結(jié)束本次數(shù)據(jù)傳輸。
7.2 SPI_MasterSlaveDma例程
WIZnet 是一家無(wú)晶圓廠半導(dǎo)體公司,成立于 1998 年。產(chǎn)品包括互聯(lián)網(wǎng)處理器 iMCU?,它采用 TOE(TCP/IP 卸載引擎)技術(shù),基于獨(dú)特的專利全硬連線 TCP/IP。iMCU? 面向各種應(yīng)用中的嵌入式互聯(lián)網(wǎng)設(shè)備。
WIZnet 在全球擁有 70 多家分銷商,在香港、韓國(guó)、美國(guó)設(shè)有辦事處,提供技術(shù)支持和產(chǎn)品營(yíng)銷。
香港辦事處管理的區(qū)域包括:澳大利亞、印度、土耳其、亞洲(韓國(guó)和日本除外)。
審核編輯 黃宇
-
crc
+關(guān)注
關(guān)注
0文章
204瀏覽量
29960 -
SPI
+關(guān)注
關(guān)注
17文章
1775瀏覽量
94603 -
I2S
+關(guān)注
關(guān)注
1文章
71瀏覽量
42631
發(fā)布評(píng)論請(qǐng)先 登錄
文檔更新 | 迅為RK3568驅(qū)動(dòng)指南-第十七篇(串口)
太陽(yáng)能充放電控制————求解
火力發(fā)電廠水汽分析方法 第十七部分:聯(lián)氨的測(cè)定(直接法)DL
第十七講 譯碼器

模擬電路網(wǎng)絡(luò)課件 第十七節(jié):結(jié)型場(chǎng)效應(yīng)管

第十七屆中國(guó)電子電路行業(yè)排行榜頒獎(jiǎng)會(huì)議正式召開
LSK現(xiàn)在是第十七大加密貨幣它的市值約為28.7億美元
2012 ADI第十七屆國(guó)際集成電路展覽會(huì)現(xiàn)場(chǎng)花絮
STM32單片機(jī)最小系統(tǒng)電路(洋桃 入門一百步第十七步)

第十七屆全國(guó)大學(xué)智能汽車競(jìng)賽競(jìng)速比賽規(guī)則

【正點(diǎn)原子FPGA連載】第三十七章雙路高速AD實(shí)驗(yàn) -摘自【正點(diǎn)原子】新起點(diǎn)之FPGA開發(fā)指南_V2.1

"STM32H7學(xué)習(xí)繼續(xù)(STM32H7系列5)第十七章比較實(shí)用,以后寫程序的時(shí)候會(huì)用到"

云英谷科技VTOS6205斬獲第十七屆“中國(guó)芯”優(yōu)秀技術(shù)創(chuàng)新產(chǎn)品獎(jiǎng)

宏微科技將參加第十七屆上海太陽(yáng)能光伏與智慧能源展

評(píng)論