|
本帖最后由 秦延雷 于 2017-12-20 17:31 編輯
一、概述
1.SPI通訊總線介紹
2.STM32F40xSPI模塊介紹
3.STM32F40xSPI模塊相關(guān)寄存器
4.W25Q64 Flah存儲(chǔ)芯片介紹
二、講解
1.SPI通訊總線介紹
1)SPI通訊協(xié)議概述
SPI是由MOTOROLA公司研發(fā)的串行外圍通訊設(shè)備接口,是一種高速的、全雙工、同步的通訊總線。
2)SPI通訊接口
SPIO通訊接口分為:五線制和四線制
①五線制:
a)MOSI:也稱為DO,作為主器件的時(shí)候?yàn)閿?shù)據(jù)輸出,作為從器件的時(shí)候?yàn)閿?shù)據(jù)輸入。
b)MISO:也稱為DI,作為主器件的時(shí)候?yàn)閿?shù)據(jù)輸入,作為從器件的時(shí)候?yàn)閿?shù)據(jù)輸出。
c)SCLK:時(shí)鐘信號(hào)線。由主器件產(chǎn)生。
d)NSS:也稱為CS,從器件使能信號(hào)。由主器件控制。
e)GND:公共地線
②四線制:
a)MOSI:雙向數(shù)據(jù)線(可收可發(fā))
b)SCLK:時(shí)鐘信號(hào)線。由主器件產(chǎn)生。
c)NSS:也稱為CS,從器件使能信號(hào)。由主器件控制。
d)GND:公共地線
3)SPI通訊物理連接
4)SPI通訊原理
①NSS控制從器件是否被選中,也就是說(shuō)當(dāng)只有片選信號(hào)為預(yù)先規(guī)定的使能信號(hào)(高電平或者低電平)時(shí),對(duì)從器件的操作才算有效。
②主器件在SCLK時(shí)鐘線上提供時(shí)鐘脈沖,MOSI或MISO則基于這個(gè)脈沖信號(hào)完成數(shù)據(jù)的傳輸。
③數(shù)據(jù)通過(guò)MOSI線,在時(shí)鐘的上升沿或者下降沿改變數(shù)據(jù),在緊接著的下降沿或者上升沿被讀取。SPI通訊協(xié)議規(guī)定傳輸?shù)臄?shù)據(jù)為8位,傳輸順序是高位在前,低位在后。
④SPI總線是一個(gè)數(shù)據(jù)交換協(xié)議,主機(jī)給從機(jī)發(fā)送一個(gè)位的數(shù)據(jù),從機(jī)必定會(huì)返回一個(gè)位的數(shù)據(jù)給主機(jī)。也就是說(shuō),主機(jī)想讀取從機(jī)的數(shù)據(jù),需要先發(fā)一個(gè)位的數(shù)據(jù)給從機(jī),從機(jī)才會(huì)回發(fā)一個(gè)位的數(shù)據(jù)給主機(jī)。
5)SPI總線數(shù)據(jù)傳輸方式
SPI一共有四種傳輸方式,四種方式的主要區(qū)別是總線空閑時(shí)SCLK的時(shí)鐘狀態(tài)以及數(shù)據(jù)采樣的時(shí)刻(上升沿、下降沿、前沿或者后沿)
SPI模式 時(shí)鐘極性(CPOL) 時(shí)鐘相位(CPHA) 時(shí)鐘空閑狀態(tài) 數(shù)據(jù)采集時(shí)刻
0 0 0 低電平 時(shí)鐘的奇數(shù)邊緣采集
1 0 1 低電平 時(shí)鐘的偶數(shù)邊緣采集
2 1 0 高電平 時(shí)鐘的奇數(shù)邊緣采集
3 1 1 高電平 時(shí)鐘的偶數(shù)邊緣采集
①時(shí)鐘相位(CPHA):決定了數(shù)據(jù)線上第1個(gè)數(shù)據(jù)的采集時(shí)刻。
a)CPHA = 0:MOSI或MISO數(shù)據(jù)線上的數(shù)據(jù)在串行時(shí)鐘線(SCLK)的奇數(shù)邊沿被采集。
b)CPHA = 1:MOSI或MISO數(shù)據(jù)線上的數(shù)據(jù)在串行時(shí)鐘線(SCLK)的偶數(shù)邊沿被采集。
②時(shí)鐘極性(CPOL):決定了SPI總線在空閑狀態(tài)時(shí)(SPI通訊開(kāi)始之前),時(shí)鐘線的電平狀態(tài)。
a)CPOL = 0:串行同步時(shí)鐘總線(SCLK)的空閑狀態(tài)為低電平。
b)CPOL = 1:串行同步時(shí)鐘總線(SCLK)的空閑狀態(tài)為高電平。
2.STM32F40xSPI模塊介紹
1)STM32F40xSPI模塊概述
STM32F40x的SPI模塊支持兩個(gè)功能,分別為:SPI通訊總線協(xié)議以及IIS音頻協(xié)議,默認(rèn)功能為SPI通訊總線協(xié)議功能。SPI通訊協(xié)議支持SPI四線制(半雙工)和五線制(全雙工)通訊模式。同時(shí)還可以配置成主機(jī)模式和從機(jī)模式以及多主機(jī)模式,還可以使用CRC校驗(yàn)實(shí)現(xiàn)可靠通信。
2)STM32F40xSPI模塊主要特性
①由SPI模塊中的SCLK、MOSI以及MISO三線組成全雙工同步通信。
②支持SPI四線制同步半雙工通信
③支持?jǐn)?shù)據(jù)傳輸字長(zhǎng)為8位或16位
④可以設(shè)置成主機(jī)模式和從機(jī)模式(默認(rèn)是從機(jī)模式)和多主機(jī)模式(在同一個(gè)時(shí)間內(nèi)只能有1個(gè)主機(jī)在工作)
⑤可以對(duì)SPI的輸入時(shí)鐘源進(jìn)行分頻,頻率最大值為(fpclk/2)
⑥NSS在主模式下為軟件管理,在從模式線為硬件管理
⑦可以設(shè)置數(shù)據(jù)的傳輸順序(先高還是先低)以及SPI的數(shù)據(jù)傳輸方式
⑧支持MOTOROL公司以及TI公司的SPI通訊協(xié)議
⑨SPI中斷源分別為:發(fā)送、接收、主模式錯(cuò)誤、上溢錯(cuò)誤、CRC錯(cuò)誤
⑩支持DMA功能
3)SPI主機(jī)模式設(shè)置
①根據(jù)需要驅(qū)動(dòng)的目標(biāo)器件來(lái)確定SPI的傳輸速度比特率。
②根據(jù)需要驅(qū)動(dòng)的目標(biāo)器件來(lái)配置時(shí)鐘極性和相位(TI模式忽略此步)。
③根據(jù)需要驅(qū)動(dòng)的目標(biāo)器件來(lái)確定數(shù)據(jù)位長(zhǎng)度。
④根據(jù)需要驅(qū)動(dòng)的目標(biāo)器件來(lái)配置數(shù)據(jù)的傳輸方式(TI模式忽略此步)。
⑤把NSS管腳設(shè)置位軟件管理模式
⑥選擇SPI通信協(xié)議格式
⑦把SPI配置位主機(jī)模式
⑧是SPI模塊
3.STM32F40xSPI模塊相關(guān)寄存器
1)SPI 控制寄存器 1 (SPI_CR1)
寄存器作用:設(shè)置SPI模塊工作模式
2)SPI 控制寄存器 2 (SPI_CR2)
寄存器作用:設(shè)置SPI模塊工作模式
3)SPI 狀態(tài)寄存器 (SPI_SR)
寄存器作用:檢測(cè)SPI具體相應(yīng)功能的具體狀態(tài)。
4)SPI 數(shù)據(jù)寄存器 (SPI_DR)
寄存器作用:存放需要發(fā)送或接收的數(shù)據(jù)
4.W25Q64 Flah存儲(chǔ)芯片介紹
1)W25Q64 Flah芯片概述
W25Q64是一款具有SPI通信接口,大小為8M(Byte)的Flash芯片。W25Q64內(nèi)部把8M大小的存儲(chǔ)空間分為128塊(Bolck),每塊大小為64K字節(jié),而每塊又分為16個(gè)扇區(qū)(Sector),每個(gè)扇區(qū)大小為4K字節(jié)。每個(gè)扇區(qū)分為16頁(yè),每頁(yè)256個(gè)字節(jié)。Flash內(nèi)部數(shù)據(jù)只能有1變0,不能由0變1。
2)W25Q64管腳
①/CS:片選管腳,低電平有效。在執(zhí)行一條新指令之前,必須要讓CS管腳先出現(xiàn)一個(gè)下降沿。
②DO(MISO):串行數(shù)據(jù)輸出管腳,在CLK管腳的下降沿輸出數(shù)據(jù)。
③/WP:寫(xiě)保護(hù)管腳,低電平有效,高電平可讀可寫(xiě),低電平僅僅可讀。
④DI(MOSI):串行數(shù)據(jù)輸入管腳,在CLK管腳的上升沿捕獲數(shù)據(jù)。
⑤CLK:串行時(shí)鐘管腳,為輸入和輸出數(shù)據(jù)提供時(shí)鐘脈沖。
⑥/HOLD:保存管腳,有效電平為低電平。當(dāng)/HOLD為低電,并且CS也為低電平時(shí),數(shù)據(jù)輸出管腳將保持高阻態(tài),同時(shí)會(huì)忽略數(shù)據(jù)輸出管腳以及時(shí)鐘管腳上的信號(hào)。把/HOLD管腳拉高,器件恢復(fù)正常工作。
3)W25Q64傳輸速度
W25Q64在標(biāo)準(zhǔn)模式下支持80Mbit/s;快速模式下支持160Mbit/s;高速模式下支持320Mbit/s
4)W25Q64數(shù)據(jù)傳輸
W25Q64支持模式0和模式3數(shù)據(jù)傳輸時(shí)序模式。數(shù)據(jù)傳輸?shù)淖珠L(zhǎng)為8位,傳輸順序?yàn)橄雀咴俚汀?br />
5)W25Q64工作原理
通過(guò)SPI總線接口,用標(biāo)準(zhǔn)的SPI協(xié)議發(fā)送相應(yīng)的指令給Flash,然后Flash根據(jù)命令執(zhí)行各種相關(guān)操作。
5.SPI通信編程思路
1)配置SPI相應(yīng)功能的GPIO管腳
2)使能SPI模塊時(shí)鐘
3)設(shè)置SPI模塊工作模式:按照SPI主機(jī)模式設(shè)置步驟設(shè)置
4)編寫(xiě)SPI字節(jié)數(shù)據(jù)傳輸函數(shù)
#include "spi.h"
/********** SPI初始化函數(shù)**************
DO ----> PB4 復(fù)用模式
CLK ----> PB3 復(fù)用模式
DI ----> PB5 復(fù)用模式
***************************************/
void SPI_Init(void)
{
/* SPI引腳管腳配置 */
RCC->AHB1ENR |= 1 << 1; //使能 GPIOB外設(shè)時(shí)鐘
/* PB3(CLK)管腳配置 復(fù)用模式 */
/* 管腳模式配置 */
GPIOB->MODER &= ~(3 << (3 * 2)); //清零
GPIOB->MODER |= 2 << (3 * 2); //PB3配置為復(fù)用模式
/* 復(fù)用功能配置 */
GPIOB->AFR[0] &= ~(0x0f << (3 * 4)); //清零
GPIOB->AFR[0] |= 5 << (3 * 4); //PB3 復(fù)用選擇SPI_1
/* 輸出速率配置 */
GPIOB->OSPEEDR &= ~(3 << (3 * 2)); //清零
GPIOB->OSPEEDR |= 2 << (3 * 2); //輸出速率50M
/* PB4(DO)管腳配置 復(fù)用模式*/
/* 管腳模式配置 */
GPIOB->MODER &= ~(3 << (4 * 2)); //清零
GPIOB->MODER |= 2 << (4 * 2); //PB4配置為復(fù)用模式
/* 復(fù)用功能配置 */
GPIOB->AFR[0] &= ~(0x0f << (4 * 4)); //清零
GPIOB->AFR[0] |= 5 << (4 * 4); //PB4 復(fù)用選擇SPI_1
/* PB5(DI)管腳配置 復(fù)用模式 */
/* 管腳模式配置 */
GPIOB->MODER &= ~(3 << (5 * 2)); //清零
GPIOB->MODER |= 2 << (5 * 2); //PB5配置為復(fù)用模式
/* 復(fù)用功能配置 */
GPIOB->AFR[0] &= ~(0x0f << (5 * 4)); //清零
GPIOB->AFR[0] |= 5 << (5 * 4); //PB5 復(fù)用選擇SPI_1
/* 輸出速率配置 */
GPIOB->OSPEEDR &= ~(3 << (5 * 2)); //清零
GPIOB->OSPEEDR |= 2 << (5 * 2); //輸出速率50M
/* 使能SPI模塊時(shí)鐘 */
RCC->APB2ENR |= 1 << 12; //使能SPI_1時(shí)鐘
/* 設(shè)置SPI模塊工作模式 */
SPI1->CR1 &= ~(7 << 3); //SPI_1波特率42M
SPI1->CR1 &= ~(1 << 1); //SPI_1時(shí)序模式0
SPI1->CR1 &= ~(1 << 0);
SPI1->CR1 &= ~(1 << 11); //8位數(shù)據(jù)長(zhǎng)度
SPI1->CR1 &= ~(1 << 7); //先發(fā)高位
SPI1->CR1 |= 1 << 9; //NSS軟件管理
SPI1->CR1 |= 1 << 8; //NSS內(nèi)部狀態(tài)為高電平
SPI1->CR2 &= ~(1 << 4); //選擇MOTOROLA模式
SPI1->CR1 |= 1 << 2; //主機(jī)模式
/* 使能SPI */
SPI1->CR1 |= 1 << 6; //使能SPI_1
}
/********************** SPI數(shù)據(jù)傳輸函數(shù) *********************************/
u16 SPI_Send_Read_Byte(u8 data)
{
u16 ErrTimer = 0;
/* 寫(xiě)功能 */
while( !(SPI1->SR & (1 << 1)) )
{
ErrTimer++;
if(ErrTimer >= 0xfffe)
{
return 0;
}
}
SPI1->DR = data;
ErrTimer = 0;
/* 讀功能 */
while( !(SPI1->SR & (1 << 0)) )
{
ErrTimer++;
if(ErrTimer >= 0xfffe)
{
return 0;
}
}
return SPI1->DR;
}
|
|