最近在研究SPI總線,至于協議和硬件描述就不多說了
四線包括時鐘、片選、接收、發送
初始化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設為外部GPIO來控制。
像我所做的項目是使用STM32與FPGA通信,而FPGA的SPI工作在這種一直狀態
作為主設備的STM32,CS在傳輸數據的時候為低,傳輸完畢后必須拉高,這樣FPGA可以判斷出SPI的傳輸起止狀態。
FPGA的數據傳輸格式是16bit地址+16bit數據
對于讀16bit,實現如下
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;
}
寫函數
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函數舉例
只所以這么設計是因為
如果是函數一開始就將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時鐘出來
之所以寫兩次再讀兩次而不是讀一次寫一次也是考慮到效率的問題
如果先寫一次再讀一次,看波形每個數據之間有比較大的空隙是沒有clk的,就是說在傳輸完一個數據后再
傳第二個會要等一段時間,這個對速度要求比較高的設備是不允許的
還有值得注意的是:
如果SPI是主模式,那么GPIO設置為
NSS是GPIO_Mode_Out_PP
CLK是GPIO_Mode_AF_PP
MOSI是GPIO_Mode_AF_PP
MISO是GPIO_Mode_IN_FLOATING
如果SPI是從模式,那么GPIO設置為
NSS是GPIO_Mode_Out_PP
CLK是GPIO_Mode_IN_FLOATING
MOSI是GPIO_Mode_IN_FLOATING
MISO是GPIO_Mode_AF_PP
上一篇:STM32的定時器和ADC
下一篇:STM32 ADC 采樣 頻率的確定
推薦閱讀
史海拾趣
面對能源轉型的挑戰,GPS在2015年轉型為智能電網解決方案的提供商。公司研發了一套集數據采集、監控、分析和優化于一體的智能電網平臺,幫助電力公司提高運營效率,減少能源浪費。該平臺通過實時監測電網狀態,預測電力需求,并自動調整供電策略,實現了電網的智能化管理。GPS的智能電網解決方案在全球多個國家和地區得到應用,成為推動能源轉型的重要力量。
隨著技術的不斷進步和市場需求的日益增長,智浦欣公司意識到,只有不斷創新和突破,才能在激烈的市場競爭中立于不敗之地。于是,公司加大了對研發團隊的投入,引進了一批國內外頂尖的模擬器件和混合信號設計人才。經過數月的努力,團隊成功研發出了一款具有高性價比的WLED驅動器產品,該產品以其卓越的性能和穩定的質量贏得了客戶的廣泛好評。隨后,公司又相繼推出了多款具有競爭力的新產品,進一步鞏固了其在消費類電子市場的地位。
樂鑫科技在發展過程中,與百度、亞馬遜等全球知名企業建立了緊密的合作關系。通過與這些合作伙伴的共同努力,樂鑫科技成功開發了一系列具有市場影響力的語音框架和物聯網解決方案,進一步提升了其品牌影響力和市場競爭力。
谷峰電子有限公司的故事始于1995年,當時公司在香港成立,標志著其半導體元器件研發與銷售的起點。初期,面對激烈的市場競爭和技術挑戰,谷峰團隊憑借對半導體技術的深刻理解和對市場需求的敏銳洞察,逐步確立了以功率MOSFET為核心產品的戰略方向。2000年,谷峰在深圳設立分公司,進一步擴大了其研發和銷售網絡,為公司的快速發展奠定了堅實基礎。
隨著公司的發展,E-Switch不斷推出新產品,以滿足不同客戶的需求。從最初的輕觸開關,到后來的防破壞按鈕、搖桿開關、滑動開關等多種類型,E-Switch的產品線逐漸豐富起來。同時,公司也積極拓展市場,將產品銷往全球各地,進一步提升了品牌影響力。
背景:HN Electronics成立于20世紀90年代初,正值全球電子市場快速崛起的時期。公司由一群在半導體領域擁有豐富經驗的工程師創立,他們看到了智能手機和消費電子產品市場的巨大潛力。
發展:初期,HN Electronics專注于研發高性能的電源管理芯片,通過技術創新解決了當時市場上存在的能效低、發熱量大等問題。公司迅速獲得了業界的認可,并與幾家知名手機制造商建立了合作關系。
關鍵事件:1995年,HN Electronics成功推出其首款自主研發的電源管理芯片,該產品迅速成為市場熱銷產品,為公司贏得了第一桶金。
Google將在美國時間周二推出Google Chrome網絡瀏覽器,旨在挑戰微軟的IE瀏覽器。該瀏覽器Google Chrome的官方網站gears.google.com/chrome/也已啟動。谷歌沒有對此馬上作出回應。據了解,Google Chrome瀏覽器通過強化地址欄功能和其它元素,使得瀏 ...… 查看全部問答∨ |
就算放大器和比較器如出一轍,簡單的講,比較器就是運放的開環應用,但比較器的設計 是針對電壓門限比較而用的,要求的比較門限精確,比較后的輸出邊沿上升或下降時間 要短,輸出符合TTL/CMOS 電平/或OC 等,不要求中間環節的準確度,同時驅動能 ...… 查看全部問答∨ |
.................... [BCSP] HCI_OpenConnection - Started CLK:66562500, BaudRate:9600, UBRDIV:432, UDIVSLOTn:5 CLK:66562500, BaudRate:115200, UBRDIV:35, UDIVSLOTn:1 [BCSP] BCSPLinkEstablishmentThread started... DeviceFolder::L ...… 查看全部問答∨ |
|
兩個C8051f04x芯片的串口uart的通訊問題,請高手幫忙,我沒啥分,只能感謝你了。。 這是我畢業設計的一部分,目前只是要求能有單片機a向b發送一個字節即可,剩下的就能整明白了,但是我的單片機b怎么也收不到信息呀。發送端只是發送一個字節,接受端節收到這個字節后將把字節顯示在LCD1602上,程序源代碼如下:(我現在不明白為什么 ...… 查看全部問答∨ |
我想在ce5.0的windows\\programs目錄下添加一個快捷方式文件, 但是我的是中文系統,所以"windows\\programs"變成了"windows\\程序目錄"了,我在platform.dat中指定目錄為Directory("windows\\programs")或者Directory("windows\\程 ...… 查看全部問答∨ |
只需要用小鍵盤輸入0000~9999任意數字,然后中間用.隔開,然后保存好,保存大概最大要50個左右,顯示用LED,輸入好后可以用USB跟電腦傳輸數據....可行么? 如果我需要把保存的數字用TXT文件保存是否是需要用到什么樣的嵌入系統?這樣的話需要用到什么芯片 ...… 查看全部問答∨ |
***uC/OS-II中實現多個生產者和多個消費者問題**** 利用uC/OS-II內核中的信號量操作,生產者和消費者的數目都是3,緩沖區的大小10。 如何利用uC/OS-II中的信號量來實現呢?想了很久不知道怎么實現任務間的同步和互斥,望大蝦指教,給個偽代碼看看也好。… 查看全部問答∨ |