0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何實(shí)現(xiàn)獨(dú)立片選一主多從

汽車電子技術(shù) ? 來源:嵌入式客棧 ? 作者:逸珺 ? 2023-01-20 11:53 ? 次閱讀

[導(dǎo)讀] 大家好,我是逸珺。

之前用STM32的SPI需要控制很多外部芯片,可是一個(gè)SPI的外設(shè)只有一個(gè)片選,要實(shí)現(xiàn)獨(dú)立片選一主多從,怎么實(shí)現(xiàn)呢?

SPI總線拓?fù)?/h2>

一般地,SPI總線按照下圖方式進(jìn)行連接,一主多從。

微信截圖_20230105161930.png

如上圖:

  • 每個(gè)從設(shè)備都有獨(dú)立的片選引腳,主機(jī)同一時(shí)間段內(nèi),與一個(gè)從設(shè)備進(jìn)行通信,也即選中一個(gè)從設(shè)備。
  • MOSI/MISO/SCLK并聯(lián)在一起
  • MISO須是三態(tài)門,當(dāng)從設(shè)備未選中時(shí),該腳須設(shè)置為高阻態(tài),而不能是輸出態(tài),否則會(huì)影響總線 !
  • 對于MOSI/SCLK,雖然并聯(lián)在一起,但是由于僅一個(gè)輸出,多輸入。

但是你看STM32的SPI外設(shè),一個(gè)SPI僅有一個(gè)NSS信號,以STM32F407的SPI2為例:

那么要實(shí)現(xiàn)前面說的一主多從,怎么辦呢?有朋友說,直接用GPIO去模擬不就可以了。

不錯(cuò),SPI總線要用GPIO模擬還是很容易的,但是這樣做波特率做不高,需要占用CPU時(shí)間,效率比較低!而用SPI外設(shè)控制器,底層bit流的收發(fā)由外設(shè)控制器實(shí)現(xiàn),用GPIO模擬則需要CPU參與。

怎么破呢?

菊花鏈拓?fù)?/h1>

微信截圖_20230105161930.png

這種方案,省引腳。但是要移位控制,相對獨(dú)立片選效率還是低不少。

獨(dú)立片選拓?fù)?/h1>

SPI外設(shè)的MOSI、MISO、SCK還是照用不誤,但是片選我們不用,設(shè)置成通用輸出模式,再用其他的GPIO片選從芯片即可。

上代碼看看:

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hspi->Instance==SPI1)
  {
    __HAL_RCC_SPI1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    PA15     ------> SPI1_NSS 但是這里不用
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

   /*__HAL_RCC_GPIOC_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);*/ 
  }
}

初始化SPI外設(shè)

#define SPI_CS1                        GPIO_PIN_1
#define SPI_CS1_PORT                   GPIOC
#define SPI_CS2                        GPIO_PIN_2
#define SPI_CS2_PORT                   GPIOC
#define SPI_CS3                        GPIO_PIN_3
#define SPI_CS3_PORT                   GPIOC
static void init_spi(SPI_HandleTypeDef * spi_handle)
{
  /* SPI1 parameter configuration*/
  spi_handle->Instance = SPI1;
  spi_handle->Init.Mode = SPI_MODE_MASTER;
  spi_handle->Init.Direction = SPI_DIRECTION_2LINES;
  spi_handle->Init.DataSize = SPI_DATASIZE_8BIT;
  spi_handle->Init.CLKPolarity = SPI_POLARITY_LOW;
  spi_handle->Init.CLKPhase = SPI_PHASE_1EDGE;
  spi_handle->Init.NSS = SPI_NSS_HARD_OUTPUT;
  spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  spi_handle->Init.FirstBit = SPI_FIRSTBIT_MSB;
  spi_handle->Init.TIMode = SPI_TIMODE_DISABLE;
  spi_handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  spi_handle->Init.CRCPolynomial = 10;
  ASSERT (HAL_SPI_Init(spi_handle) != HAL_OK);

 GPIO_InitTypeDef  GPIO_InitStructure;

 __HAL_RCC_GPIOC_CLK_ENABLE();

 GPIO_InitStructure.Pin = SPI_CS1;
 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStructure.Pull = GPIO_NOPULL;
 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_MEDIUM;
 HAL_GPIO_Init(SPI_CS1_PORT, &GPIO_InitStructure); 
  
 GPIO_InitStructure.Pin = SPI_CS2;
 HAL_GPIO_Init(SPI_CS2_PORT, &GPIO_InitStructure);  
 
 GPIO_InitStructure.Pin = SPI_CS3;
 HAL_GPIO_Init(SPI_CS3_PORT, &GPIO_InitStructure);   
}

從而原來SPI的收發(fā)函數(shù)前后加上片選信號即可:

typedef enum 
{  
 SPI_CH_1=0,
 SPI_CH_2,
 SPI_CH_3,
 SPI_CH_LAST,
} SPI_CH;
static HAL_StatusTypeDef SPI_Select(SPI_CH ch)
{
   switch (ch)
   {
     case SPI_CH_1:
       HAL_GPIO_WritePin(SPI_CS1_PORT,SPI_CS1,GPIO_PIN_RESET);
       break;
       
     case SPI_CH_2:
       HAL_GPIO_WritePin(SPI_CS2_PORT,SPI_CS2,GPIO_PIN_RESET);
       break;
       
     case SPI_CH_3:
       HAL_GPIO_WritePin(SPI_CS3_PORT,SPI_CS3,GPIO_PIN_RESET);
       break;       
     
     default:
       return HAL_ERROR;
   }  
   return HAL_OK;
}
static HAL_StatusTypeDef SPI_DeSelect(SPI_CH ch)
{
   switch (ch)
   {
     case SPI_CH_1:
       HAL_GPIO_WritePin(SPI_CS1_PORT,SPI_CS1,GPIO_PIN_SET);
       break;
       
     case SPI_CH_2:
       HAL_GPIO_WritePin(SPI_CS2_PORT,SPI_CS2,GPIO_PIN_SET);
       break;
       
     case SPI_CH_3:
       HAL_GPIO_WritePin(SPI_CS3_PORT,SPI_CS3,GPIO_PIN_SET);
       break;       
     
     default:
       return HAL_ERROR;
   }
   return HAL_OK;
}

HAL_StatusTypeDef SPI_TransmitReceive(SPI_CH ch,
                    SPI_HandleTypeDef *hspi, 
                    uint8_t *pTxData, 
                    uint8_t *pRxData, 
                    uint16_t Size,
                    uint32_t Timeout)
{
   HAL_StatusTypeDef ret; 
   if(ch>=SPI_CH_LAST)
     return HAL_ERROR;  
    
   SPI_Select(ch);
   ret = HAL_SPI_TransmitReceive(hspi,pTxData,pRxData,Size,Timeout);
   SPI_DeSelect(ch);
   
   return ret;
}

HAL_StatusTypeDef SPI_Transmit(SPI_CH ch,
                 SPI_HandleTypeDef *hspi, 
                 uint8_t *pData, 
                 uint16_t Size, 
                 uint32_t Timeout)
{
   HAL_StatusTypeDef ret; 
   if(ch>=SPI_CH_LAST)
     return HAL_ERROR;  
    
   SPI_Select(ch);
   ret = HAL_SPI_Transmit(hspi,pData,Size,Timeout);
   SPI_DeSelect(ch);
   
   return ret;  
}

如此一來,一個(gè)SPI外設(shè)就可以控制多個(gè)從芯片了。你如果有興趣,不妨照這個(gè)思路試試看。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 芯片
    +關(guān)注

    關(guān)注

    452

    文章

    49938

    瀏覽量

    419621
  • STM32
    +關(guān)注

    關(guān)注

    2263

    文章

    10846

    瀏覽量

    353701
  • SPI
    SPI
    +關(guān)注

    關(guān)注

    17

    文章

    1681

    瀏覽量

    91052
收藏 人收藏

    評論

    相關(guān)推薦

    TLE9867QXA20如何實(shí)現(xiàn)

    您好,團(tuán)隊(duì),我在我的應(yīng)用程序中使用 TLE9867QXA20,,現(xiàn)在我想為我的應(yīng)用實(shí)現(xiàn)
    發(fā)表于 03-04 07:26

    藍(lán)牙的通訊問題

    最近在做個(gè)藍(lán)牙的通訊。所謂的
    發(fā)表于 08-08 10:06

    SPI如何實(shí)現(xiàn)

    本帖最后由 dave520l 于 2014-6-23 17:11 編輯 有沒有人知道SPI怎么設(shè)計(jì),目前做的個(gè)小項(xiàng)目中,ST
    發(fā)表于 06-23 17:10

    verilog如何實(shí)現(xiàn)ram

    ram,如何根據(jù)地址其中一片譯碼器:module choose(in,cs);input [2:0] in; output reg [5:0] cs;always
    發(fā)表于 02-10 10:26

    spi2通訊 主從都是stm32f103,站nss可以配置成硬件模式嗎?

    通過輪尋站,過程如下:發(fā)收,收后進(jìn)行處
    發(fā)表于 10-29 18:52

    STM32的SPI要實(shí)現(xiàn)獨(dú)立怎么辦呢

    之前用STM32的SPI需要控制很多外部芯片,可是個(gè)SPI的外設(shè)只有個(gè),要實(shí)現(xiàn)獨(dú)立
    發(fā)表于 09-21 14:51

    CH579怎么實(shí)現(xiàn)?

    CH579Y以太網(wǎng),走自定義協(xié)議實(shí)現(xiàn),,測試方式是每次經(jīng)過個(gè)模塊數(shù)據(jù)+1,總共有五個(gè)C
    發(fā)表于 10-14 06:53

    ESP32的官方例程中是否有實(shí)現(xiàn)BLE的例程呢?

    請問各位大佬,ESP32的官方例程中是否有實(shí)現(xiàn)BLE的例程呢,應(yīng)該如何學(xué)習(xí)這類方面的知
    發(fā)表于 02-10 07:47

    ESP32的官方例程中是否有實(shí)現(xiàn)BLE的例程呢?

    請問各位大佬,ESP32的官方例程中是否有實(shí)現(xiàn)BLE的例程呢,應(yīng)該如何學(xué)習(xí)這類方面的知
    發(fā)表于 03-03 06:17

    ESP32的官方例程中是否有實(shí)現(xiàn)BLE的例程呢?

    請問各位大佬,ESP32的官方例程中是否有實(shí)現(xiàn)BLE的例程呢,應(yīng)該如何學(xué)習(xí)這類方面的知
    發(fā)表于 03-08 08:59

    動(dòng)態(tài)顯示-譯碼器實(shí)現(xiàn)【匯編版】

    動(dòng)態(tài)顯示-譯碼器實(shí)現(xiàn)【匯編版】動(dòng)態(tài)顯示-譯碼器實(shí)現(xiàn)【匯編版】動(dòng)態(tài)顯示-譯碼器
    發(fā)表于 12-29 15:51 ?0次下載

    動(dòng)態(tài)顯示-譯碼器實(shí)現(xiàn)【C語言】

    動(dòng)態(tài)顯示-譯碼器實(shí)現(xiàn)【C語言】動(dòng)態(tài)顯示-譯碼器實(shí)現(xiàn)【C語言】動(dòng)態(tài)顯示-譯碼器
    發(fā)表于 12-29 15:51 ?0次下載

    Modbus通訊協(xié)議的無線通訊

    該方案可適用于3臺(tái)以上西門子PLC,S7-200或S7-200Smart之間實(shí)現(xiàn)Modbus通訊協(xié)議的無線通訊。
    發(fā)表于 06-04 09:50 ?1.1w次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>主</b><b class='flag-5'>多</b><b class='flag-5'>從</b>Modbus通訊協(xié)議的無線通訊

    Modbus S7-200實(shí)現(xiàn)機(jī)的通信資料說明

    該方案可適用于3臺(tái)以上西門子PLC,S7-200 或S7-200Smart之間實(shí)現(xiàn)Modbus通訊協(xié)議的無線通訊。
    發(fā)表于 10-22 08:00 ?13次下載
    Modbus S7-200<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>一</b><b class='flag-5'>主</b><b class='flag-5'>多</b><b class='flag-5'>從</b>機(jī)的通信資料說明

    工業(yè)場合站場景如何實(shí)現(xiàn)設(shè)備數(shù)據(jù)采集

    到云平臺(tái),那么如何實(shí)現(xiàn)場景的數(shù)據(jù)采集呢?? 物通博聯(lián)物聯(lián)網(wǎng)網(wǎng)關(guān)具有串口轉(zhuǎn)發(fā)功能,將串口數(shù)據(jù)轉(zhuǎn)發(fā)到另
    發(fā)表于 02-09 16:02 ?455次閱讀
    工業(yè)場合<b class='flag-5'>多</b><b class='flag-5'>主</b>站<b class='flag-5'>一</b><b class='flag-5'>從</b>站場景如何<b class='flag-5'>實(shí)現(xiàn)</b>設(shè)備數(shù)據(jù)采集