簡介
SPI,是英語Serial Peripheral interface的縮寫,顧名思義就是串行外圍設備接口。是Motorola首先在其MC68HCXX系列處理器上定義的。SPI接口主要應用在 EEPROM,FLASH,實時時鐘,AD轉換器,還有數字信號處理器和數字信號解碼器之間。SPI,是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上只占用四根線,節約了芯片的管腳,同時為PCB的布局上節省空間,提供方便,正是出于這種簡單易用的特性,現在越來越多的芯片集成了這種通信協議。
SPI 具有信號線少,協議簡單,數據率高等優點。數據傳送速率達幾MB/s
Pin 腳介紹
標準的 SPI 使用 4 Pin 進行數據傳送:
(1)MOSI – 主器設備數據輸出,從器件數據輸入
(2)MISO – 主器設備件數據輸入,從器件數據輸出
(3)SCLK – 時鐘信號,由主器件產生, 最大為fPCLK/2,從模式頻率最大為fCPU/2
(4)NSS – 從器件使能信號,由主器件控制,有的 IC 會標注為 CS (Chip select)
數據時在 CLK 時鐘的驅動下,在數據線上按照一個 bit 一個 bit 的進行傳送,數據可以在時鐘的上升沿或者下降沿改變(或者采樣)。
SPI 傳輸的缺點是,沒有數據完整性校驗,也沒有流控機制。
既然稱 SPI 為總線,則 SPI 就可以支持多個設備相連接,通過 CS 片選信號來指定期望通訊的設備。(多機通訊)
SPI 模式
SPI 通訊有 4 中不同的通訊模式,通信雙方需要配置成為一樣的模式,才能夠進行正常的數據傳輸,這里有兩個概念:
CPOL:時鐘極性
CPHA:時鐘相位
CPOL:(時鐘極性)控制在沒有數據傳輸時,SPI 時鐘的空閑狀態電平。即,定義了總線空閑的工作狀態(注意,和 UART 不同,SPI 是通過 CLK 的狀態來表征當前的總線狀態,即不發生任何數據交互的時候,時鐘信號總是沒有進行翻轉的)
CPOL=0,表示當SCLK=0時處于空閑態
CPOL=1,表示當SCLK=1時處于空閑態
CPHA:(時鐘相位)是用來配置數據采樣是在第幾個邊沿。
CPHA=0,表示數據采樣是在第1個邊沿
CPHA=1,表示數據采樣是在第2個邊沿
所以 CPOL 和 CPHA 的不同組合,成為了 SPI 的四種傳輸模式:
SPI Mode
四種傳輸模式,定義了不同時刻的總線啟動,以及數據發送和采樣時間:
CPOL=0,CPHA=0:此時空閑態時,SCLK處于低電平,數據采樣是在第1個邊沿,也就是 SCLK 由低電平到高電平的跳變,所以數據采樣是在上升沿,數據發送是在下降沿。
CPOL=0,CPHA=1:此時空閑態時,SCLK處于低電平,數據發送是在第1個邊沿,也就是 SCLK 由低電平到高電平的跳變,所以數據采樣是在下降沿,數據發送是在上升沿。
CPOL=1,CPHA=0:此時空閑態時,SCLK處于高電平,數據采集是在第1個邊沿,也就是 SCLK 由高電平到低電平的跳變,所以數據采集是在下降沿,數據發送是在上升沿。
CPOL=1,CPHA=1:此時空閑態時,SCLK處于高電平,數據發送是在第1個邊沿,也就是 SCLK 由高電平到低電平的跳變,所以數據采集是在上升沿,數據發送是在下降沿。
對應到波形上:
STM32 SPI 特性
STM32 上支持 3 路 SPI:
可以支持全雙工的通信
支持硬件 CRC
可編程的數據順序,MSB在前或LSB在前
主模式和從模式的快速通信
可編程的時鐘極性和相位(CPOL,CPHA)
可觸發中斷的專用發送和接收標志
可觸發中斷的主模式故障、過載以及CRC錯誤標志
支持DMA功能的1字節發送和接收緩沖器:產生發送和接受請求
SPI 時鐘
單板上使用 SPI2 進行 SPI FLASH 的操作,使用的是 APB1 的時鐘,最大配置為 36MHz。
硬件連接
硬件上,通過單板的 SPI2 引腳,連接到外部的 SPI FLASH (W25Q64)
所以,在配置的時候,需要針對 SPI2 進行配置。
SPI Flash 簡介
硬件單板上,連接的是 WinBond 的 W25Q64BV 的 SPI Flash,此款 Flash 的特性如下:
大小:64M-bit / 8M-byte
頁 : 256B
支持 80MHz 的時鐘
支持扇區擦除:Sector Erase (4K-bytes)
支持塊擦除:Block Erase (32K and 64K-bytes)
支持頁寫入:0~256-bytes
軟件/硬件寫保護
由于暫時不需要硬件寫保護和Hold功能,故,直接將 WP和HOLD引腳接到 VCC(3.3V)
(此款SPI FLASH 還支持雙線和4線 QSPI 的讀寫,由于 STM32 不支持,所以不在多說)
根據 W25Q64BV 的 Datasheet 描述,在操作這塊 FLASH 的時候,需要配置主機為:
SPI Mode 0 或者 Mode 3
MSB 先傳輸
故,在 SPI2 配置的時候,需要進行對應的配置,才能夠繼續正常數據通信。
W25Q64BV 存在兩個寄存器可以被訪問,為 Status Register-1 和 Status Register-2,其中描述的關于 Write-Protect 的部分,暫時不管。與讀寫相關的就是 BUSY 位了,因為對 SPI Flash 編程后,Flash 需要內部的 cylce 進行數據的寫入,內部program的時候會將 BUSY 置成 1,寫入完成后,會將 BUSY 位置 0,故,每次對 Flash 進行寫(包括擦除)之前,均要進行 BUSY 位的判斷。
好啦,現在就開始按照 DateSheet 進行配置我們的 STM32 了。
STM32 SPI2 配置
配置過程主要分為兩步:GPIO 的配置,SPI2 的配置(如原理圖所示,PB_12 的 GPIO 用于了 CS 片選,我們需要將其配置成為輸出的 GPIO,拉低的時候,選中 Flash,拉高的時候釋放 Flash 信號)
1. 開啟 GPIO B 組的時鐘
2. 開啟 SPI2 的時鐘
3. 按照 STM32 手冊,配置 SCK 、MOSI 和 NSS 為復用推挽輸出、MISO為浮空輸入(有的代碼將 MISO 配置成為的輸出,雖然也可以運行,不過,您不覺得別扭么?還是遵循 Spec 的來吧)。同時將 GPIO_B _12配置為輸出(CS信號)
4. 配置 SPI2 為全雙工模式
5. SPI2 為 Master
6. SPI2 運行在 MODE3(按照 W25Q64BV 的 Timing 要求 )
7. SPI2 NSS 為軟件模式(根本沒用)
8. 預分頻系數為 4 分頻(APB1 為 36M,則 SPI2 的 SCK 為 9 MHz)
9. SPI2 傳輸 MSB(按照 W25Q64BV 的 Timing 要求)
10. 不啟用 CRC
11. 開啟 SPI 功能
此刻 SPI 的配置就基本完成了。接下來就是 按照 W25Q64BV 的 Timing 要求,寫 FLASH 驅動咯.....
#define SK_SPI_FLASH_CS_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_12)
#define SK_SPI_FLASH_CS_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_12)
/*******************************************************************************
* Function Name : SK_SPIPortInit
* Description : Configure the I/O port for SPI2.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void _SK_SPI2PortInit(void)
{
GPIO_InitTypeDef stGpioInit;
/*!< Configure pins: SCK */
stGpioInit.GPIO_Pin = GPIO_Pin_13;
stGpioInit.GPIO_Speed = GPIO_Speed_50MHz;
stGpioInit.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &stGpioInit);
/*!< Configure pins: MISO */
stGpioInit.GPIO_Pin = GPIO_Pin_14;
stGpioInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &stGpioInit);
/*!< Configure pins: MOSI */
stGpioInit.GPIO_Pin = GPIO_Pin_15;
stGpioInit.GPIO_Speed = GPIO_Speed_50MHz;
stGpioInit.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &stGpioInit);
/*!< Configure pins: CS */
stGpioInit.GPIO_Pin = GPIO_Pin_12;
stGpioInit.GPIO_Speed = GPIO_Speed_50MHz;
stGpioInit.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &stGpioInit);
}
/*******************************************************************************
* Function Name : _SK_SPI2BusInit
* Description : Configure the SPI2 Bus to adpte the W25Q64 Flash.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void _SK_SPI2BusInit(void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // PCLK = 36M, SPI2 CLK = PCLK/4 = 9M
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
}
/*******************************************************************************
* Function Name : SK_SPIInit
* Description : Initializes the peripherals used by the SPI FLASH driver.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SK_SPIFlashInit(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
_SK_SPI2PortInit();
SK_SPI_FLASH_CS_HIGH();
_SK_SPI2BusInit();
}
W25Q64BV Flash 驅動
W25Q64BV 是 Flash 嘛,最主要的就是讀和寫。當然,除了這些,還有擦除功能,讀 ID 等等。不著急,一步一步來,都是套路。
STM32 在進行 SPI 全雙工數據傳輸的時候,在通過 MOSI 寫出去數據后,可以立馬進行 MISO 數據讀取,通過輪詢 TXE 標志來判斷數據已經全部加載到移位寄存器,通過輪詢 RXE 標志來得知本次 MISO 的數據已經全部到賬。
針對 W25Q64BV Flash,Datasheet 中列出了支持的多種不同的命令:
對應上述表格,有不同的 Timing 進行描述,比如:Opcode 為 0x9F 的時候,是讀取一個叫 JEDEC ID 的東西:
可以看到,主機首先將 CS 拉低,然后主機處在 Mode 0 或者 Mode 3 的時候,在 MOSI 信號上輸出 0x9F 的數據(命令),然后接著寫入 Dummy Data (隨便寫點東西),然后再 MISO 信號上就能夠收到 manufacture ID 的信息(為 0xEF),在繼續寫入 Dummy Data,繼續接收,繼續寫入,繼續接收,這樣便可以得到期望的數據了。
獲取 Flash ID 信息
根據上述方式,便可以獲取 ID 信息:
/********************** W25Q64 Flash Command Defination ***********************/
#define SPI_FLASH_PerWritePageSize 256
#define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04
#define W25X_ReadStatusReg_1 0x05
#define W25X_ReadStatusReg_2 0x35
#define W25X_WriteStatusReg 0x01
#define W25X_ReadData 0x03
#define W25X_FastReadData 0x0B
#define W25X_FastReadDual 0x3B
#define W25X_PageProgram 0x02
#define W25X_64K_BlockErase 0xD8
#define W25X_32K_BlockErase 0x52
#define W25X_4K_SectorErase 0x20
#define W25X_ChipErase 0xC7
#define W25X_PowerDown 0xB9
#define W25X_ReleasePowerDown 0xAB
#define W25X_DeviceID 0xAB
#define W25X_ManufactDeviceID 0x90
#define W25X_JedecDeviceID 0x9F
#define Busy_Flag 0x01 /* Write In Progress (WIP) flag */
#define Dummy_Byte 0xFF /* Dummy Data */
typedef struct {
uint8_t manufacturer_id;
uint8_t memory_type_id;
uint8_t capacity_id;
uint8_t device_id;
} W25Q64_ID_t;
/*******************************************************************************
* Function Name : SPI_FLASH_SendByte
* Description : Sends a byte through the SPI interface and return the byte
* received from the SPI bus.
* Input : byte : byte to send.
* Output : None
* Return : The value of the received byte.
*******************************************************************************/
static uint8_t SPI_FLASH_SendByte(uint8_t byte)
{
/* Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
/* Send byte through the SPI2 peripheral */
上一篇:STM32 DMA外設地址的計算問題
下一篇:STM32F103ZET6 — SDIO (Mirco SDCard)
推薦閱讀
史海拾趣
在2005年的一個陽光明媚的春天,思博科技(Cybermax)公司在硅谷正式成立。創始人李明,一位經驗豐富的電子工程師,看準了當時電子市場蓬勃發展的機遇,決定創辦自己的公司。起初,公司只有幾名員工,主要致力于研發和生產高性能的電子元器件。通過不懈的努力和優質的產品,思博科技逐漸在市場上嶄露頭角。
Captive Fastener公司在電子緊固件領域一直致力于技術創新。某年,公司研發團隊成功開發出一種新型的自鎖緊固件,這種緊固件能夠在高振動環境下保持穩定的連接性能,極大地提高了電子設備的可靠性和耐久性。這一創新產品迅速獲得了市場的認可,Captive Fastener公司因此獲得了大量訂單,實現了業務的快速增長。
Captive Fastener公司在電子緊固件領域一直致力于技術創新。某年,公司研發團隊成功開發出一種新型的自鎖緊固件,這種緊固件能夠在高振動環境下保持穩定的連接性能,極大地提高了電子設備的可靠性和耐久性。這一創新產品迅速獲得了市場的認可,Captive Fastener公司因此獲得了大量訂單,實現了業務的快速增長。
DEWALT公司非常注重產品品質和用戶體驗。公司建立了嚴格的質量控制體系,確保每一件產品都符合高質量標準。同時,DEWALT還積極傾聽用戶反饋,不斷改進產品和服務。這些努力使DEWALT公司的電動工具在市場上獲得了廣泛認可,并贏得了大量忠實用戶。
在第二次世界大戰期間,DEWALT公司面臨了巨大的挑戰。由于戰爭的影響,許多原材料和零部件供應中斷,生產受到嚴重影響。然而,DEWALT公司憑借自身的技術實力和創新能力,成功克服了這些困難。公司還積極為軍隊提供所需的電動工具產品,為戰爭勝利做出了貢獻。這些經歷使DEWALT公司更加堅定了技術創新和品質控制的信念。
AR RF/Microwave Instrumentation的創立源于對射頻和微波技術的深入研究和理解。公司創始人在行業內具有豐富的經驗,他們看到了這一領域的巨大潛力,并決定成立一家公司來專門研發和生產相關的儀器設備。起初,公司規模較小,但憑借高質量的產品和專業的服務,逐漸在行業內贏得了聲譽。
[ip]快畢業了,畢業論文是 基于modbus協議的數據采集系統,不知道各位高手們有沒有想要對我這個笨笨知道的地方.謝謝,謝謝,十分感謝.… 查看全部問答∨ |
|
淘寶:http://gooogleman.taobao.com/ OK6410 官方報價 860 RMB——團購活動,再下一城,那么大家還猶豫什么?! 結構:核心板+底板 接口:眾多,詳細情況請看官方介紹了,不多說了。 團購活動因為是非正常價格銷 ...… 查看全部問答∨ |
|
各位大俠:小弟現需在WinCE5.0開發wifi driver,以前完全沒有相關經驗,完全沒有概念,模不著頭腦,問題真的很多。感覺微軟本身的文檔挺混亂的,說的也不怎么具體,大家有沒有好的教材?最好可以可以手把手教這個開發過程的啊(第一步做什么,第二 ...… 查看全部問答∨ |
|
收集到很多關于Altium Designer 資料,希望對大家有所幫助。 [ 本帖最后由 熊貓 于 2010-12-23 20:17 編輯 ]… 查看全部問答∨ |
這篇學習筆記,完全是基于《STM32不完全手冊》而言的,我沒有買Alientek的開發板,買的是ARMFly的,其實都差不多,只不過安福萊的板載資源非常豐富罷了,應用起來其實都差不都。 《STM32不完全手冊》的51到56頁就是要這次筆記學習的內容,請自己參 ...… 查看全部問答∨ |
建立源程序時首先用偽指令TITLE提供程序的標題,接著給出整個程序的總說明,并用列表偽指令LIST指定所用單片機型號和文件輸出格式,再利用INCLUDE偽指令讀入MPASM中提供的定義文件如《P16F84?INC》,然后對片內常用資源進行定義,再給出一般程序的 ...… 查看全部問答∨ |
設計資源 培訓 開發板 精華推薦
- 試用Vishay新型“IHLP磁芯損耗計算器”,搶樓贏好禮
- LPC4370重磅來襲 有獎問答贏好禮!
- 電子工程師,如何更好地擁抱GaN?參與問卷有好禮!
- 報名贏京東卡 | 國產FPGA安路科技2024線上新品發布會
- 兆易GD32450I-EVAL免費測評試用
- 追更有驚喜:解救被FSM折磨過的你,justd0解析LSM6DSOX有限狀態機官方例程
- 電路圖站2.0版上線,公開征集網友建議,填寫調查問卷贏積分!
- 全球首款Cortex-M23內核物聯網芯片SAML10和SAM L11系列 闖關獲取SAML10/SAML11法寶,拆除電子界安全危機,贏好禮!
- 邀請好友體驗WEBENCH,禮品豐厚你有他也有!