1. 程式人生 > >16.HAL庫之SPI和QSPI

16.HAL庫之SPI和QSPI

1.SPI協議(以RN8302為例)

SPI是序列外設介面(Serial Peripheral Interface)的縮寫。SPI,是一種高速的,全雙工,同步的通訊匯流排,並且在晶片的管腳上只佔用四根線(SCSN,SCLK,SDI,SDO).

總結傳輸流程:

a.寫時序

SCSN拉低,開啟通訊。主機依次寫入地址,命令,資料(高位在前,低位在後),CS校驗。主機在SCLK下降沿將資料通過SDI寫入從機。最後SCSN拉高結束通訊。

b.讀時序

SCSN拉低開啟通訊,主機先寫入地址+命令共兩個位元組,隨後在SCLK下降沿讀取從機從SDO輸出的資料(高位在前,低位在後)。最後SCSN拉高結束通訊。

驅動程式編寫:標頭檔案中需定義管腳控制命令,暫存器地址,晶片命令。c檔案中依次編寫讀寫位元組,讀寫幀資料,讀寫暫存器,晶片初始化等函式。

主機(STM32F746)只需配置SPI介面即可,具體流程為:開啟時鐘,GPIO管腳配置,SPI配置。

2.QSPI

QSPI是Queued SPI的簡寫,是Motorola公司推出的SPI介面的擴充套件,比SPI應用更加廣泛。在SPI協議的基礎上,Motorola公司對其功能進行了增強,增加了佇列傳輸機制,推出了佇列序列外圍介面協議(即QSPI協議)。QSPI 是一種專用的通訊介面,連線單、雙或四(條資料線) SPI Flash 儲存介質。共有SNCS,SCLK,BK0,BK1,BK2,BK3共6根接線,可以實現多種通訊模式。

主機需進行QSPI介面的配置,QSPI協議主要通過傳送命令來進行通訊,因此主機的配置包括管腳配置,QSPI初始化。

QUADSPI通過命令和FLASH通訊,命令包括:指令+地址+交替位元組+空週期+資料五個階段,並且各階段可省略。

單線SPI模式:BK_IO0即SO,BK_IO1即SI,加上NCS和SCLK,類似於SPI模式。

雙線SPI模式:BK_IO0和BK_IO1實現資料的雙入雙出。

四線SPI模式:BK_IO0,BK_IO1,BK_IO2,BK_IO3四根線實現資料的傳輸。

SDR模式:QSPI驅動IO0~IO3在SCLK的下降沿進行資料變化。

DDR模式:在該模式下,指令階段在SCLK下降沿傳送資料,而在地址,交替位元組,資料階段在SCLK上升沿和下降沿均傳送資料。

雙快閃記憶體模式:使用兩個外部SPI四線,可將flash擴大一倍。

QSPI配置:

時鐘使能,管腳定義,QSPI配置,flash初始化,QSPI讀/寫函式定義。

void Qspi_Config()
{
	__HAL_RCC_QSPI_CLK_ENABLE();
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_GPIOF_CLK_ENABLE();
	
	Flash_GPIO.Pin=GPIO_PIN_2;
	Flash_GPIO.Mode=GPIO_MODE_AF_PP;
	Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;
	Flash_GPIO.Pull=GPIO_NOPULL;
	Flash_GPIO.Alternate=GPIO_AF9_QUADSPI;
	HAL_GPIO_Init(GPIOB,&Flash_GPIO);   //QSPI_CLK, PB2
	
	Flash_GPIO.Pin=GPIO_PIN_6;
	Flash_GPIO.Mode=GPIO_MODE_AF_PP;
	Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;
	Flash_GPIO.Pull=GPIO_PULLUP;
	Flash_GPIO.Alternate=GPIO_AF10_QUADSPI;
	HAL_GPIO_Init(GPIOB,&Flash_GPIO);   //QSPI_NCS, PB6
	
	Flash_GPIO.Pin=GPIO_PIN_8;
	Flash_GPIO.Mode=GPIO_MODE_AF_PP;
	Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;
	Flash_GPIO.Pull=GPIO_NOPULL;
	Flash_GPIO.Alternate=GPIO_AF10_QUADSPI;
	HAL_GPIO_Init(GPIOF,&Flash_GPIO);   //QSPI_IO0, PF8
	
	Flash_GPIO.Pin=GPIO_PIN_9;
	Flash_GPIO.Mode=GPIO_MODE_AF_PP;
	Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;
	Flash_GPIO.Pull=GPIO_NOPULL;
	Flash_GPIO.Alternate=GPIO_AF10_QUADSPI;
	HAL_GPIO_Init(GPIOF,&Flash_GPIO);   //QSPI_IO1, PF9
	
	Flash_GPIO.Pin=GPIO_PIN_7;
	Flash_GPIO.Mode=GPIO_MODE_AF_PP;
	Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;
	Flash_GPIO.Pull=GPIO_NOPULL;
	Flash_GPIO.Alternate=GPIO_AF9_QUADSPI;
	HAL_GPIO_Init(GPIOF,&Flash_GPIO);   //QSPI_IO2, PF7
	
	Flash_GPIO.Pin=GPIO_PIN_6;
	Flash_GPIO.Mode=GPIO_MODE_AF_PP;
	Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;
	Flash_GPIO.Pull=GPIO_NOPULL;
	Flash_GPIO.Alternate=GPIO_AF9_QUADSPI;
	HAL_GPIO_Init(GPIOF,&Flash_GPIO);   //QSPI_IO3, PF6
	
  QSPI_Flash.Instance=QUADSPI;
	QSPI_Flash.Init.ClockPrescaler=2;
	QSPI_Flash.Init.FifoThreshold=4;
	QSPI_Flash.Init.SampleShifting=QSPI_SAMPLE_SHIFTING_HALFCYCLE;
	QSPI_Flash.Init.FlashSize=25;
	QSPI_Flash.Init.ChipSelectHighTime=QSPI_CS_HIGH_TIME_8_CYCLE;
	QSPI_Flash.Init.ClockMode=QSPI_CLOCK_MODE_0;
	HAL_QSPI_Init(&QSPI_Flash);
}