本實(shí)驗(yàn)采用W25Q64芯片
W25Q64是華邦公司推出的大容量SPI
FLASH產(chǎn)品,其容量為64Mb。該25Q系列的器件在靈活性和性能方面遠(yuǎn)遠(yuǎn)超過(guò)普通的串行閃存器件。W25Q64將8M字節(jié)的容量分為128個(gè)塊,每個(gè)塊大小為64K字節(jié),每個(gè)塊又分為16個(gè)扇區(qū),每個(gè)扇區(qū)4K個(gè)字節(jié)。W25Q64的最小擦除單位為一個(gè)扇區(qū),也就是每次必須擦除4K個(gè)字節(jié)。所以,這需要給W25Q64開(kāi)辟一個(gè)至少4K的緩存區(qū),這樣必須要求芯片有4K以上的SRAM才能有很好的操作。
W25Q64的擦寫(xiě)周期多達(dá)10W次,可將數(shù)據(jù)保存達(dá)20年之久,支持2.7~3.6V的電壓,支持標(biāo)準(zhǔn)的SPI,還支持雙輸出/四輸出的SPI,最大SPI時(shí)鐘可達(dá)80Mhz。
一。SPI接口原理
(一)概述

高速,全雙工,同步的通信總線。
全雙工:可以同時(shí)發(fā)送和接收,需要2條引腳
同步: 需要時(shí)鐘引腳
片選引腳:方便一個(gè)SPI接口上可以掛多個(gè)設(shè)備。
總共四根引腳。
(二)SPI內(nèi)部結(jié)構(gòu)簡(jiǎn)明圖

MISO: 做主機(jī)的時(shí)候輸入,做從機(jī)的時(shí)候輸出
MOSI:做主機(jī)的時(shí)候輸出,做從機(jī)的時(shí)候輸入
主機(jī)和從機(jī)都有一個(gè)移位寄存器,在同一個(gè)時(shí)鐘的控制下主機(jī)的最高位移到從機(jī)的最高位,同時(shí)從機(jī)的最高位往前移一位,移到主機(jī)的最低位。在一個(gè)時(shí)鐘的控制下主機(jī)和從機(jī)進(jìn)行了一個(gè)位的交換,那么在8個(gè)時(shí)鐘的控制下就交換了8位,最后的結(jié)果就是兩個(gè)移位寄存器的數(shù)據(jù)完全交換。
在8個(gè)時(shí)鐘的控制下,主機(jī)和從機(jī)的兩個(gè)字節(jié)進(jìn)行了交換,也就是說(shuō)主機(jī)給從機(jī)發(fā)送一個(gè)字節(jié)8個(gè)位的同時(shí),從機(jī)也給主機(jī)傳回來(lái)了8個(gè)位,也就是一個(gè)字節(jié)。
(三)SPI接口框圖

上面左邊部分就是在時(shí)鐘控制下怎么傳輸數(shù)據(jù),右邊是控制單元,還包括左下的波特率發(fā)生器。
(四)SPI工作原理總結(jié)

(五)SPI的特征

(六)從選擇(NSS)腳管理

兩個(gè)SPI通信首先有2個(gè)數(shù)據(jù)線,一個(gè)時(shí)鐘線,還有一個(gè)片選線,只有把片選拉低,SPI芯片才工作,片選引腳可以是SPI規(guī)定的片選引腳,還可以通過(guò)軟件的方式選擇任意一個(gè)IO口作為片選引腳,這樣做的好處是:比如一個(gè)SPI接口上掛多個(gè)設(shè)備,比如掛了4個(gè)設(shè)備,第二個(gè)用PA2,第三個(gè)用PA3,第四個(gè)用PA4作為片選,我們
跟第二個(gè)設(shè)備進(jìn)行通信的時(shí)候,只需要把第二個(gè)片選選中,比如拉低,其他設(shè)備的片選都拉高,這樣就實(shí)現(xiàn)了一個(gè)SPI接口可以連接個(gè)SPI設(shè)備,戰(zhàn)艦開(kāi)發(fā)板上就是通過(guò)這種方法來(lái)實(shí)現(xiàn)的。
(七)時(shí)鐘信號(hào)的相位和極性

時(shí)鐘信號(hào)的相位和極性是通過(guò)CR寄存器的 CPOL 和 CPHA兩個(gè)位確定的。
CPOL:時(shí)鐘極性,設(shè)置在沒(méi)有數(shù)據(jù)傳輸時(shí)時(shí)鐘的空閑狀態(tài)電平。CPOL置0,SCK引腳在空閑時(shí)為低電平,CPOL置1,SCK引腳在空閑時(shí)保持高電平。
CPHA:時(shí)鐘相位 設(shè)置時(shí)鐘信號(hào)在第幾個(gè)邊沿?cái)?shù)據(jù)被采集
CPHA=1時(shí):在時(shí)鐘信號(hào)的第二個(gè)邊沿

CPOL=1,CPHA=1,
CPOL=1表示時(shí)鐘信號(hào)在沒(méi)有數(shù)據(jù)傳輸時(shí)即空閑時(shí)的狀態(tài)為高電平。如果CPHA=1,那么數(shù)據(jù)就在時(shí)鐘信號(hào)的第二個(gè)邊沿即上升沿的時(shí)候被采集。
CPOL= 0,CPHA=1, CPOL=0表示時(shí)鐘信號(hào)在沒(méi)有數(shù)據(jù)傳輸時(shí)即空閑時(shí)的狀態(tài)為低電平。
如果CPHA=1,那么數(shù)據(jù)就在時(shí)鐘信號(hào)的第二個(gè)邊沿即下降沿的時(shí)候被采集。
CPHA=0時(shí):在時(shí)鐘信號(hào)的第一個(gè)邊沿

CPOL=1,CPHA=0,
CPOL=1表示時(shí)鐘信號(hào)在沒(méi)有數(shù)據(jù)傳輸時(shí)即空閑時(shí)的狀態(tài)為高電平。如果CPHA=1,那么數(shù)據(jù)就在時(shí)鐘信號(hào)的第一個(gè)邊沿即下降沿的時(shí)候被采集。
CPOL= 0,CPHA=0, CPOL=0表示時(shí)鐘信號(hào)在沒(méi)有數(shù)據(jù)傳輸時(shí)即空閑時(shí)的狀態(tài)為低電平。
如果CPHA=1,那么數(shù)據(jù)就在時(shí)鐘信號(hào)的第一個(gè)邊沿即上升沿的時(shí)候被采集。
為什么要配置這兩個(gè)參數(shù)?
因?yàn)镾PI外設(shè)的從機(jī)的時(shí)鐘相位和極性都是有嚴(yán)格要求的。所以我們要根據(jù)選擇的外設(shè)的時(shí)鐘相位和極性來(lái)配置主機(jī)的相位和極性。必須要與從機(jī)匹配。
(八)數(shù)據(jù)幀的格式和狀態(tài)標(biāo)志

數(shù)據(jù)幀格式:根據(jù)CR1寄存器的LSBFIRST位的設(shè)置,數(shù)據(jù)可以MSB在前也可以LSB在前。
根據(jù)CR1寄存器的DEF位,每個(gè)數(shù)據(jù)幀可以是8位或16位。
(九)SPI中斷

(十)SPI引腳配置 (3個(gè)SPI)

引腳的工作模式設(shè)置

引腳必須要按照這個(gè)表格配置。
二。SPI寄存器庫(kù)函數(shù)配置
(一)常用寄存器

(二)SPI相關(guān)庫(kù)函數(shù)

STM32的SPI接口可以配置為支持SPI協(xié)議或者支持I2S音頻協(xié)議。默認(rèn)是SPI模式,可以通過(guò)軟件切換到I2S方式。
常用的函數(shù):
1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef*
SPI_InitStruct);//SPI的初始化
2. void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState); //SPI使能
3. void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT,
FunctionalState NewState); //開(kāi)啟中斷
4. void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq,
FunctionalState NewState);//通 過(guò)DMA傳輸數(shù)據(jù)
5. void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data); //發(fā)送數(shù)據(jù)
6. uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx); //接收數(shù)據(jù)
7. void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);
//設(shè)置數(shù)據(jù)是8位還是16位
8. 其他幾個(gè)狀態(tài)函數(shù)
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef*
SPI_InitStruct);//SPI的初始化

結(jié)構(gòu)體成員變量比較多,這里我們挑取幾個(gè)重要的成員變量講解一下:
第一個(gè)參數(shù) SPI_Direction 是用來(lái)設(shè)置 SPI 的通信方式,可以選擇為半雙工,全雙工,以及串行發(fā)和串行收方式,這里我們選擇全雙工模式
SPI_Direction_2Lines_FullDuplex。
第二個(gè)參數(shù) SPI_Mode 用來(lái)設(shè)置 SPI 的主從模式,這里我們?cè)O(shè)置為主機(jī)模式 SPI_Mode_Master,當(dāng)然有需要你也可以選擇為從機(jī)模式
SPI_Mode_Slave。
第三個(gè)參數(shù) SPI_DataSiz 為 8 位還是 16 位幀格式選擇項(xiàng),這里我們是 8 位傳輸,選擇SPI_DataSize_8b。
第四個(gè)參數(shù) SPI_CPOL 用來(lái)設(shè)置時(shí)鐘極性,我們?cè)O(shè)置串行同步時(shí)鐘的空閑狀態(tài)為高電平所以我們選擇 SPI_CPOL_High。
第五個(gè)參數(shù) SPI_CPHA
用來(lái)設(shè)置時(shí)鐘相位,也就是選擇在串行同步時(shí)鐘的第幾個(gè)跳變沿(上升或下降)數(shù)據(jù)被采樣,可以為第一個(gè)或者第二個(gè)條邊沿采集,這里我們選擇第二個(gè)跳變沿,所以選擇
SPI_CPHA_2Edge
第六個(gè)參數(shù) SPI_NSS 設(shè)置 NSS 信號(hào)由硬件(NSS 管腳)還是軟件控制,這里我們通過(guò)軟件控
制 NSS 關(guān)鍵,而不是硬件自動(dòng)控制,所以選擇 SPI_NSS_Soft。
第七個(gè)參數(shù) SPI_BaudRatePrescaler 很關(guān)鍵,就是設(shè)置 SPI 波特率預(yù)分頻值也就是決定 SPI 的時(shí)
鐘的參數(shù) , 從不分頻道 256 分頻 8 個(gè)可選值,初始化的時(shí)候我們選擇 256 分頻值
SPI_BaudRatePrescaler_256, 傳輸速度為 36M/256=140.625KHz。
第八個(gè)參數(shù) SPI_FirstBit 設(shè)置數(shù)據(jù)傳輸順序是 MSB 位在前還是 LSB 位在前, ,這里我們選擇
SPI_FirstBit_MSB 高位在前。
第九個(gè)參數(shù) SPI_CRCPolynomial 是用來(lái)設(shè)置 CRC 校驗(yàn)多項(xiàng)式,提高通信可靠性,大于 1 即可。
設(shè)置好上面 9 個(gè)參數(shù),我們就可以初始化 SPI 外設(shè)了。
初始化的范例格式為:
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
//雙線雙向全雙工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主 SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // SPI 發(fā)送接收 8 位幀結(jié)構(gòu)
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//串行同步時(shí)鐘的空閑狀態(tài)為高電平
371
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//第二個(gè)跳變沿?cái)?shù)據(jù)被采樣
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS 信號(hào)由軟件控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //預(yù)分頻
256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //數(shù)據(jù)傳輸從 MSB 位開(kāi)始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC 值計(jì)算的多項(xiàng)式
SPI_Init(SPI2, &SPI_InitStructure); //根據(jù)指定的參數(shù)初始化外設(shè) SPIx 寄存器
(三)程序配置步驟

三。W25Qxx配置講解
(一)電路圖

片選用的PB12
W25Q64 是華邦公司推出的大容量SPI FLASH 產(chǎn)品,W25Q64 的容量為 64Mb,該系列還有 W25Q80/16/32
等。ALIENTEK 所選擇的 W25Q64 容量為 64Mb,也就是 8M 字節(jié)。(1M=1024K)
W25Q64 將 8M 的容量分為 128 個(gè)塊(Block),每個(gè)塊大小為 64K 字節(jié),每個(gè)塊又分為 16個(gè)扇區(qū)(Sector),每個(gè)扇區(qū) 4K
個(gè)字節(jié)。W25Q64 的最少擦除單位為一個(gè)扇區(qū),也就是每次必須擦除 4K 個(gè)字節(jié)。這樣我們需要給 W25Q64 開(kāi)辟一個(gè)至少 4K 的緩存區(qū),這樣對(duì) SRAM
要求比較高,要求芯片必須有 4K 以上 SRAM 才能很好的操作。
W25Q64 的擦寫(xiě)周期多達(dá) 10W 次,具有 20 年的數(shù)據(jù)保存期限,支持電壓為 2.7~3.6V,W25Q64 支持標(biāo)準(zhǔn)的
SPI,還支持雙輸出/四輸出的 SPI,最大 SPI 時(shí)鐘可以到 80Mhz(雙輸出時(shí)相當(dāng)于 160Mhz,四輸出時(shí)相當(dāng)于 320M),更多的 W25Q64
的介紹,請(qǐng)參考 W25Q64 的DATASHEET。
在往一個(gè)地址寫(xiě)數(shù)據(jù)之前,要先把這個(gè)扇區(qū)的數(shù)據(jù)全部讀出來(lái)保存在緩存里,然后再把這個(gè)扇區(qū)擦除,然后在緩存中修改要寫(xiě)的數(shù)據(jù),然后再把整個(gè)緩存中的數(shù)據(jù)再重新寫(xiě)入剛才擦除的扇區(qū)中。
便于學(xué)習(xí)和參考再給大家分享些spi 的資料
stm32之SPI通信
http://www.makeru.com.cn/live/3523_1795.html?s=45051
SPI通信協(xié)議驅(qū)動(dòng)norFlash