寒假學(xué)習(xí)之stm32(17)----SPI通信協(xié)議
背景知識(shí)介紹:
wiki :http://wiki.csie.ncku.edu.tw/embedded/SPI#introduction
百度:http://baike.baidu.com/item/SPI
一定要看?。。。?/p>
小小的摘要:
1. 通信模式:SPI是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上只占用四根線(SDI,SDO,SCLK,CS)
MISO(masterinslaverout)主設(shè)備數(shù)據(jù)輸入,從設(shè)備數(shù)據(jù)輸出。MOSI(masteroutslaverin)主設(shè)備數(shù)據(jù)輸出,從設(shè)備數(shù)據(jù)輸入。SCLK時(shí)鐘信號(hào),由主設(shè)備產(chǎn)生。CS從設(shè)備片選信號(hào),由主設(shè)備控制
2. 內(nèi)部結(jié)構(gòu):
3. 工作原理:
1.硬件上為4根線。2.主機(jī)和從機(jī)都有一個(gè)串行移位寄存器,主機(jī)通過向它的SPI串行寄存器寫入一個(gè)字節(jié)來(lái)發(fā)起一次傳輸。3.串行移位寄存器通過MOSI信號(hào)線將字節(jié)傳送給從機(jī),從機(jī)也將自己的串行移位寄存器中的內(nèi)容通過MISO信號(hào)線返回給主機(jī)。這樣,兩個(gè)移位寄存器中的內(nèi)容就被交換。(具有環(huán)形通信的特點(diǎn))4.外設(shè)的寫操作和讀操作是同步完成的。如果只進(jìn)行寫操作,主機(jī)只需忽略接收到的字節(jié);反之,若主機(jī)要讀取從機(jī)的一個(gè)字節(jié),就必須發(fā)送一個(gè)空字節(jié)來(lái)引發(fā)從機(jī)的傳輸。
4. 應(yīng)用:主要應(yīng)用在 EEPROM,F(xiàn)LASH,實(shí)時(shí)時(shí)鐘,AD轉(zhuǎn)換器,還有數(shù)字信號(hào)處理器和數(shù)字信號(hào)解碼器之間。
我們可以看一下SPI的單從機(jī)模式的接線:
多從機(jī)模式(從這里也能夠看出片選接口的作用):
stm32下的SPI配置
PS:我發(fā)現(xiàn)這些通信協(xié)議的配置真特么相似啊啊啊啊啊
然后就是它的框圖:
配置過程:配置相關(guān)引腳的復(fù)用功能,使能SPIx時(shí)鐘
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
初始化SPIx,設(shè)置SPIx工作模式
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
使能SPIx
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
SPI傳輸數(shù)據(jù)
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) ;
查看SPI傳輸狀態(tài)
SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE);
完整的配置過程:
voidSPI2_Init(void){GPIO_InitTypeDefGPIO_InitStructure;SPI_InitTypeDefSPI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//PORTB時(shí)鐘使能RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);//SPI2時(shí)鐘使能GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//PB13/14/15復(fù)用推挽輸出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIOBGPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);//PB13/14/15上拉SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//設(shè)置SPI單向或者雙向的數(shù)據(jù)模式:SPI設(shè)置為雙線雙向全雙工SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//設(shè)置SPI工作模式:設(shè)置為主SPISPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;//設(shè)置SPI的數(shù)據(jù)大小:SPI發(fā)送接收8位幀結(jié)構(gòu)SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;//串行同步時(shí)鐘的空閑狀態(tài)為高電平SPI_InitStructure.SPI_CPHA=SPI_CPHA_2Edge;//串行同步時(shí)鐘的第二個(gè)跳變沿(上升或下降)數(shù)據(jù)被采樣SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;//NSS信號(hào)由硬件(NSS管腳)還是軟件(使用SSI位)管理:內(nèi)部NSS信號(hào)有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_256;//定義波特率預(yù)分頻的值:波特率預(yù)分頻值為256SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;//指定數(shù)據(jù)傳輸從MSB位還是LSB位開始:數(shù)據(jù)傳輸從MSB位開始SPI_InitStructure.SPI_CRCPolynomial=7;//CRC值計(jì)算的多項(xiàng)式SPI_Init(SPI2,&SPI_InitStructure);//根據(jù)SPI_InitStruct中指定的參數(shù)初始化外設(shè)SPIx寄存器SPI_Cmd(SPI2,ENABLE);//使能SPI外設(shè)SPI2_ReadWriteByte(0xff);//啟動(dòng)傳輸}//SPI速度設(shè)置函數(shù)//SpeedSet://SPI_BaudRatePrescaler_22分頻//SPI_BaudRatePrescaler_88分頻//SPI_BaudRatePrescaler_1616分頻//SPI_BaudRatePrescaler_256256分頻voidSPI2_SetSpeed(u8SPI_BaudRatePrescaler){assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));SPI2->CR1&=0XFFC7;SPI2->CR1|=SPI_BaudRatePrescaler;//設(shè)置SPI2速度SPI_Cmd(SPI2,ENABLE);}//SPIx讀寫一個(gè)字節(jié)//TxData:要寫入的字節(jié)//返回值:讀取到的字節(jié)u8SPI2_ReadWriteByte(u8TxData){u8retry=0;while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET)//檢查指定的SPI標(biāo)志位設(shè)置與否:發(fā)送緩存空標(biāo)志位{retry++;if(retry>200)return0;}SPI_I2S_SendData(SPI2,TxData);//通過外設(shè)SPIx發(fā)送一個(gè)數(shù)據(jù)retry=0;while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET)//檢查指定的SPI標(biāo)志位設(shè)置與否:接受緩存非空標(biāo)志位{retry++;if(retry>200)return0;}returnSPI_I2S_ReceiveData(SPI2);//返回通過SPIx最近接收的數(shù)據(jù)}