STM32值SPI的使用及SPI初始化注意事項
在STM32F10x系列晶片中,雖然所擁有的SPI同步串列埠數量不相同,但是初始化的方法都是一樣的。其中使用SPI時候我們回憶GPIO的使用,要注意6點,我們這裡主要講解一點。
根據系統對該不同功能的要求,初始化不同功能外設,初始化GPIO,初始化SPI同步串列埠裝置就會比較複雜。STM32F10x系列晶片的所有SIP同步串列埠都是和GPIO共用,SPI的初始化分為2大塊,就是SPI所使用的I/O口的初始化和SPI功能的初始化。對於SPI同步串列埠要用到的引腳,根據資料的方向,要設定GPIO_Mode_IN_FLOATING或者GPIO_Mode_AF_PP複用推免輸出。其他的和GPIO引腳設定一樣。
至於低於SPI同步串列埠引數的初始化方法將在之後的一個例子中體現出來。
我們在使用SPI時候,必須開啟SPI的同步串列埠的時鐘。這樣系統才可以從這個開啟的同步串列埠中傳送和接收資料。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
在SPI傳送資料很簡單,把要傳送的資料位元組寫進發送緩衝器時,傳送過程就開始了。只不過在試圖寫傳送緩衝器之前,需要確認TXE標誌是否為1.
同樣對於接收器而言,當資料傳輸完成時,資料結束以後也完成。在最後取樣時鐘沿,RXNE標誌位置位。在移位暫存器中接收到的資料字被傳送到接收快取器。都SPI_DR暫存器時將清楚RXNE位。
故:在傳送資料時要判斷上一次的資料是否傳送完成。只有資料傳送完成才可以進行新的資料的傳送。
例:要用PA7做SPI1同步串列埠的MOSI引腳,用PA6做SPI1同步串列埠的MISO引腳,同PA5做SCK引腳,用PA4做NSS片選引腳。在定義同步串列埠SPI1為主裝置,每次傳送8個 資料位,高位在前,SPI時鐘頻率為9MHz,資料捕獲在第二個時鐘沿,時鐘空閒時為低電平,NSS引腳有軟體管理。
完整的程式碼如下:
#include"stm32f10x_lib.h"
void SPI_Configuration(void)
{
//SPI_1串列埠引數部分定義,SPI_1引數為時鐘平時為高,上升沿取樣
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI2,ENABLE);//使能SPI_2時鐘
//配置SPI1的MISO(PA6)為浮空輸入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_MODE = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//配置SPI1的MOSI(PA7)和SPI1的CLK(PA5)為複用推免輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;
GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//配置SPI1的NSS(PA4)為推免輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA,&GPIO_InitSturcture);
//SPI1同步引數初始化定義
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_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1,&SPI_InitStructure);
SPI_Cmd(SPI1,ENABLE);
}
//通過SPI1口傳送一個數據,同時接受一個數據
unsigned char SPI_SendByte(unsigned char Byte)
{
//如果傳送暫存器資料沒有傳送完,迴圈等待
while(SPI_T1S_GetFlagStatus(SPI1,SPI_T1S_FLAG_TXE) == RESET);
//往傳送暫存器寫入要傳送的資料
SPI_T1S_SendData(SPI2,Byte);
//如果接受暫存器沒有收到資料,迴圈
while(SPI_T1S_GetFlagStatus(SPI1,SPI_T1S_FLAG_RXNE) == RESET);
return SPI_T1S_ReceiveData(SPI1);
}