SPI(Serial Peripheral Interface),串行外圍設備接口。SPI是一種高速的、全雙工、同步的通信總線。
SPI接口一般使用4條線通信:
MISO 主設備數據輸入,從設備數據輸出
MOSI 主設備數據輸出,從設備數據輸入
SCLK 時鍾信號,有主設備產生
CS 從設備片選信號,有主設備控制
SPI模塊為了和外設進行數據交換,根據外設工作要求,其輸出串行同步時鍾極性和相位可以進行配置。SPI_CR寄存器的CPOL(時鍾極性)位,控制在沒有數據傳輸時時鍾的空閑狀態電平,此位對主模式和從模式下的設備都有效。CPOL=0,串行同步時鍾的空閑狀態為低電平;CPOL=1,串行同步時鍾的空閑狀態為高電平。SPI_CR寄存器的CPHA(時鍾相位)位,能配置用於選擇兩種不同的傳輸協議之一進行數據傳輸。CPHA=0,在串行同步時鍾的第一個跳變沿(上升或下降)數據被采樣;CPHA=1,在串行同步時鍾的第二個跳變沿(上升或下降)數據被采樣。
1.SPI主模式配置步驟
①使能SPI時鍾,配置PA口
APB2外設時鍾使能寄存器(RCC_APB2ENR)
APB1外設復位寄存器 (RCC_APB1RSTR)
Eg:RCC->APB2ENR|=1<<2; //PORTA時鍾使能
RCC->APB2ENR|=1<<12; //SPI1時鍾使能
//這里只針對SPI口初始化
GPIOA->CRL&=0X000FFFFF;
GPIOA->CRL|=0XBBB00000;//PA5.6.7復用
GPIOA->ODR|=0X7<<5; //PA5.6.7上拉
②開全雙工模式並軟件管理NSS
SPI控制寄存器1(SPI_CR1)(I2S模式下不使用)
Eg:SPI1->CR1|=0<<10;//全雙工模式
SPI1->CR1|=1<<9; //軟件nss管理
SPI1->CR1|=1<<8;
③設置SPI為主機並設置數據幀格式
Eg:SPI1->CR1|=1<<2; //SPI主機
SPI1->CR1|=0<<11;//8bit數據格式
④設置時鍾極性和相位極性
Eg:SPI1->CR1|=1<<1; //空閑模式下SCK為1 CPOL=1
SPI1->CR1|=1<<0; //數據采樣從第二個時間邊沿開始,CPHA=1
⑤傳輸速率和LSBFIRST幀格式設置
Eg:SPI1->CR1|=7<<3; //Fsck=Fcpu/256
SPI1->CR1|=0<<7; //MSBfirst
⑥使能SPI
Eg:SPI1->CR1|=1<<6; //SPI設備使能
2.SPI

1 //SPI口初始化 2 //這里針是對SPI1的初始化 3 void SPI1_Init(void) 4 { 5 RCC->APB2ENR|=1<<2; //PORTA時鍾使能 6 RCC->APB2ENR|=1<<12; //SPI1時鍾使能 7 8 //這里只針對SPI口初始化 9 GPIOA->CRL&=0X000FFFFF; 10 GPIOA->CRL|=0XBBB00000;//PA5.6.7復用 11 GPIOA->ODR|=0X7<<5; //PA5.6.7上拉 12 13 SPI1->CR1|=0<<10;//全雙工模式 14 SPI1->CR1|=1<<9; //軟件nss管理 15 SPI1->CR1|=1<<8; 16 17 SPI1->CR1|=1<<2; //SPI主機 18 SPI1->CR1|=0<<11;//8bit數據格式 19 SPI1->CR1|=1<<1; //空閑模式下SCK為1 CPOL=1 20 SPI1->CR1|=1<<0; //數據采樣從第二個時間邊沿開始,CPHA=1 21 SPI1->CR1|=7<<3; //Fsck=Fcpu/256 22 SPI1->CR1|=0<<7; //MSBfirst 23 SPI1->CR1|=1<<6; //SPI設備使能 24 SPI1_ReadWriteByte(0xff);//啟動傳輸(主要作用:維持MOSI為高) 25 } 26 //SPI1 速度設置函數 27 //SpeedSet:0~7 28 //SPI速度=fAPB2/2^(SpeedSet+1) 29 //APB2時鍾一般為72Mhz 30 void SPI1_SetSpeed(u8 SpeedSet) 31 { 32 SpeedSet&=0X07; //限制范圍 33 SPI1->CR1&=0XFFC7; 34 SPI1->CR1|=SpeedSet<<3; //設置SPI1速度 35 SPI1->CR1|=1<<6; //SPI設備使能 36 } 37 //SPI1 讀寫一個字節 38 //TxData:要寫入的字節 39 //返回值:讀取到的字節 40 u8 SPI1_ReadWriteByte(u8 TxData) 41 { 42 u16 retry=0; 43 while((SPI1->SR&1<<1)==0)//等待發送區空 44 { 45 retry++; 46 if(retry>0XFFFE)return 0; 47 } 48 SPI1->DR=TxData; //發送一個byte 49 retry=0; 50 while((SPI1->SR&1<<0)==0) //等待接收完一個byte 51 { 52 retry++; 53 if(retry>0XFFFE)return 0; 54 } 55 return SPI1->DR; //返回收到的數據 56 }

1 // SPI總線速度設置 2 #define SPI_SPEED_2 0 3 #define SPI_SPEED_4 1 4 #define SPI_SPEED_8 2 5 #define SPI_SPEED_16 3 6 #define SPI_SPEED_32 4 7 #define SPI_SPEED_64 5 8 #define SPI_SPEED_128 6 9 #define SPI_SPEED_256 7 10 11 void SPI1_Init(void); //初始化SPI口 12 void SPI1_SetSpeed(u8 SpeedSet); //設置SPI速度 13 u8 SPI1_ReadWriteByte(u8 TxData);//SPI總線讀寫一個字節 14 15 #endif