日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀] 最近在研究SPI總線,至于協(xié)議和硬件描述就不多說了四線包括時鐘、片選、接收、發(fā)送初始化SP SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全雙工 SPI_InitStructure.SPI_Mod

最近在研究SPI總線,至于協(xié)議和硬件描述就不多說了
四線包括時鐘、片選、接收、發(fā)送


初始化SP
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全雙工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //16bit寬度
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_2; //2--18MHz; 4--9MHz; 8--4.5MHz
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //高位在前
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPIx, &SPI_InitStructure);
SPI_Cmd(SPIx, ENABLE);

SPI不能硬件控制CS,只能軟件來控,就是通過將NSS設(shè)為外部GPIO來控制。
像我所做的項目是使用STM32FPGA通信,而FPGA的SPI工作在這種一直狀態(tài)
作為主設(shè)備的STM32,CS在傳輸數(shù)據(jù)的時候為低,傳輸完畢后必須拉高,這樣FPGA可以判斷出SPI的傳輸起止?fàn)顟B(tài)。


FPGA的數(shù)據(jù)傳輸格式是16bit地址+16bit數(shù)據(jù)
對于讀16bit,實現(xiàn)如下


uint16_t spi_read(SPI_TypeDef* SPIx,uint32_t addr)
{
uint16_t value;
uint16_t spi_nss;
uint16_t add;
uint32_t level;


if(SPI1 == SPIx)
spi_nss = SPI1_PIN_NSS;
else if(SPI2 == SPIx)
spi_nss = SPI2_PIN_NSS;


while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
GPIO_ResetBits(GPIOA, spi_nss);
SPI_I2S_SendData(SPIx, addr); //0xf014 >> 2


while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPIx, 0x0);


while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPIx);


while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
GPIO_SetBits(GPIOA, spi_nss);

while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
value = SPI_I2S_ReceiveData(SPIx);


return value;
}

寫函數(shù)


void spi_write(SPI_TypeDef* SPIx,uint32_t addr, uint16_t value)
{


uint16_t spi_nss;


uint32_t level;


if(SPI1 == SPIx)
spi_nss = SPI1_PIN_NSS;
else if(SPI2 == SPIx)
spi_nss = SPI2_PIN_NSS;



while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
GPIO_ResetBits(GPIOA, spi_nss);
SPI_I2S_SendData(SPIx, addr);


while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPIx, value);


while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPIx);


while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
GPIO_SetBits(GPIOA, spi_nss);


while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPIx);


}
拿write函數(shù)舉例
只所以這么設(shè)計是因為
如果是函數(shù)一開始就將NSS腳拉低,然后再去send,如下
GPIO_ResetBits(GPIOA, spi_nss);
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPIx, addr);

這樣在CS拉低一段時間后(時間大概有16個時鐘周期),才有CLK,這樣延時就會降低SPI的傳輸效率
之前那種方式會在CS拉底后很快就有clk時鐘出來


之所以寫兩次再讀兩次而不是讀一次寫一次也是考慮到效率的問題


如果先寫一次再讀一次,看波形每個數(shù)據(jù)之間有比較大的空隙是沒有clk的,就是說在傳輸完一個數(shù)據(jù)后再
傳第二個會要等一段時間,這個對速度要求比較高的設(shè)備是不允許的


還有值得注意的是:
如果SPI是主模式,那么GPIO設(shè)置為
NSS是GPIO_Mode_Out_PP
CLK是GPIO_Mode_AF_PP
MOSI是GPIO_Mode_AF_PP
MISO是GPIO_Mode_IN_FLOATING


如果SPI是從模式,那么GPIO設(shè)置為
NSS是GPIO_Mode_Out_PP
CLK是GPIO_Mode_IN_FLOATING
MOSI是GPIO_Mode_IN_FLOATING
MISO是GPIO_Mode_AF_PP

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除( 郵箱:macysun@21ic.com )。
換一批
延伸閱讀
關(guān)閉