新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32 SPI DMA 的使用

        STM32 SPI DMA 的使用

        作者: 時間:2016-11-19 來源:網絡 收藏
        一是想總結一下SPI總線的特點與注意點,二是總結一下SPI DMA的使用

        一、SPI信號線說明

        本文引用地址:http://www.104case.com/article/201611/318283.htm

          通常SPI通過4個引腳與外部器件相連:

        • MISO:主設備輸入/從設備輸出引腳。該引腳在從模式下發送數據,在主模式下接收數據。
        • MOSI:主設備輸出/從設備輸入引腳。該引腳在主模式下發送數據,在從模式下接收數據。
        • SCK:串口時鐘,作為主設備的輸出,從設備的輸入
        • NSS:從設備選擇。這是一個可選的引腳,用來選擇主/從設備。它的功能是用來作為“片選引腳”,讓主設備可以單獨地與特定從設備通訊,避免數據線上的沖突。

        二、原理

          MOSI腳相互連接,MISO腳相互連接。這樣,數據在主和從之間串行地傳輸(MSB位在前)。

          通信總是由主設備發起。主設備通過MOSI腳把數據發送給從設備,從設備通過MISO引腳回傳數據。這意味全雙工通信的數據輸出和數據輸入是用同一個時鐘信號同步的;時鐘信號由主設備通過SCK腳提供。

        三、NSS說明與注意點

          NSS分為內部引腳和外部引腳。

          NSS外部引腳可以作為輸入信號或者輸出信號,輸入信號一般用作硬件方式從機的片選,而輸出信號一般用于主SPI去片選與之相連的從SPI。

          NSS從設備選擇有兩種模式:

        1、軟件模式

          可以通過設置SPI_CR1寄存器的SSM位來使能這種模式,當它為1時,NSS引腳上的電平由SSI決定。在這種模式下NSS外部引腳可以用作它用,而內部NSS信號電平可以通過寫SPI_CR1的SSI位來驅動。 

        2、硬件模式

        兩種方式:

        (1)對于主SPI,NSS可以直接接高電平,對于從SPI,可以直接接低電平。  

        (2)當STM32F10xxx工作為主SPI,并且NSS輸出已經通過SPI_CR2寄存器的SSOE位使能,這時主機的NSS講作為輸出信號,引腳信號被拉低,所有NSS引腳與這個主SPI的NSS引腳相連并配置為硬件NSS的SPI設備,將自動變成從SPI設備。

          此時兩個的NSS信號線可以接個上拉電阻直連。

        四、DMA說明

          DMA是AMBA的先進高性能總線(AHB)上的設備,它有2個AHB端口:一個是從端口,用于配置DMA,另一個是主端口,使得DMA可以在不同的從設備之間傳輸數據。

          DMA的作用是在沒有Cortex-M3核心的干預下,在后臺完成數據傳輸。在傳輸數據的過程中,主處理器可以執行其它任務,只有在整個數據塊傳輸結束后,需要處理這些數據時才會中斷主處理器的操作。它可以在對系統性能產生較小影響的情況下,實現大量數據的傳輸。

        五、SPI_DMA的通信過程

        • 設置外設地址
        • 設置存儲器地址
        • 設置傳輸數據量
        • 設置通道的配置信息
        • 使能DMA通道,啟動傳輸

        • 發送時,在每次TXE被設置為’1’時發出DMA請求,DMA控制器則寫數據至SPI_DR寄存器,TXE標志因此而被清除。
        • 接收時,在每次RXNE被設置為’1’時發出DMA請求,DMA控制器則從SPI_DR寄存器讀出數據,RXNE標志因此而被清除。

        六、相關代碼

        這里使用的是SPI1

        SPI_DMA配置

        1 /*******************************************************************************2 * Function Name  : SPI1_DMA_Configuration3 * Description    : 配置SPI1_RX的DMA通道2,SPI1_TX的DMA通道34 * Input          : None5 * Output         : None6 * Return         : None7 * Attention             : 8 *******************************************************************************/9 void SPI1_DMA_Configuration( void )10 {11     DMA_InitTypeDef DMA_InitStructure;12     13     /* DMA1 Channel2 (triggered by SPI1 Rx event) Config */14   DMA_DeInit(DMA1_Channel2);  15   DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Addr;                          //設置 SPI1 發送外設(0x4001300C) 地址(目的地址)16   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI1_RX_Buff;                    //設置 SRAM 存儲地址(目的地址)17   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                //傳輸方向 外設-內存18   DMA_InitStructure.DMA_BufferSize = SPI1_ReciveBufferSize;                         //設置 SPI1 發送長度19   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;20   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;21   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;22   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;23   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;24   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;25   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;26   DMA_Init(DMA1_Channel2, &DMA_InitStructure);27   28   DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);29   /* Enable SPI1 DMA RX request */30   SPI1->CR2 = 1<<0;                                                                 //接收緩沖區DMA使能31   DMA_Cmd(DMA1_Channel2, ENABLE);32     33     34     /* DMA1 Channel3 (triggered by SPI1 Tx event) Config */35   DMA_DeInit(DMA1_Channel3);  36   DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Addr;                          //設置  接收外設(0x4001300C) 地址(源地址)37   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI1_TX_Buff;                    //設置 SRAM 存儲地址(源地址)38   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                //傳輸方向 內存-外設39   DMA_InitStructure.DMA_BufferSize = SPI1_SendBufferSize;                           //設置 SPI1 接收長度40   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                  //外設地址增量(不變)41   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                           //內存地址增量(變化)42   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;           //外設傳輸寬度(字節)43   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                   //內存傳輸寬度(字節)44   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                     //傳輸方式,一次傳輸完停止,不重新加載45   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                           //中斷方式-高(三級)46   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                      //內存到內存方式禁止47   DMA_Init(DMA1_Channel3, &DMA_InitStructure);48   49   DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);                                   //開啟 DMA1_Channel3 傳輸完成中斷50   DMA_ITConfig(DMA1_Channel3, DMA_IT_TE, ENABLE);                                   //開啟 DMA1_Channel3 傳輸錯誤中斷51   /* Enable SPI1 DMA TX request */52   SPI1->CR2 = 1<<1;                                                                //發送緩沖區DMA使能53   DMA_Cmd(DMA1_Channel3, DISABLE);                                                  //開啟 DMA 通道 DMA1_Channel354 }

        SPI發送

        1 /*******************************************************************************2 * Function Name  : SPI1_Send3 * Description    : SPI1的DMA方式發送4 * Input          : SPI1_TX_Buff[SPI1_SendBufferSize]5 * Output         : None6 * Return         : None7 * Attention             : 關閉DMA通道3之前必須等待TXE為1,等待忙標志為08 *******************************************************************************/9 void SPI1_Send( u8 *buff, u32 len )10 {11     DMA1_Channel3->CPAR = SPI1_DR_Addr; //外設地址12     DMA1_Channel3->CMAR = (u32) buff; //mem地址13     DMA1_Channel3->CNDTR = len ; //傳輸長度14     DMA1_Channel3->CCR = (0 << 14)  // 非存儲器到存儲器模式15             (2 << 12)  // 通道優先級高16             (0 << 11)  // 存儲器數據寬度8bit17             (0 << 10)  // 存儲器數據寬度8bit18             (0 <<  9)  // 外設數據寬度8bit19             (0 <<  8)  // 外設數據寬度8bit20             (1 <<  7)  // 存儲器地址增量模式21             (0 <<  6)  // 外設地址增量模式(不增)22             (0 <<  5)  // 非循環模式23             (1 <<  4)  // 從存儲器讀24             (1 <<  3)  // 允許傳輸錯誤中斷25             (0 <<  2)  // 允許半傳輸中斷26             (1 <<  1)  // 允許傳輸完成中斷27             (1);        // 通道開啟28 }

        SPI接收

        1 /*******************************************************************************2 * Function Name  : SPI1_Recive3 * Description    : SPI1的DMA方式接收4 * Input          : None5 * Output         : SPI1_RX_Buff[SPI1_ReciveBufferSize]6 * Return         : None7 * Attention             : 必須要先關閉通道2,然后再配置通道2的參數8 *******************************************************************************/9 void SPI1_Recive( u8 *buff, u32 len )10 {11     DMA1_Channel2->CCR &= ~( 1 << 0 );          //關閉DMA通道212     13     DMA1_Channel2->CPAR = SPI1_DR_Addr; //外設地址14     DMA1_Channel2->CMAR = (uint32_t)buff; //mem地址15     DMA1_Channel2->CNDTR = len ; //傳輸長度16     DMA1_Channel2->CCR = (0 << 14)  // 非存儲器到存儲器模式17             (2 << 12)  // 通道優先級高18             (0 << 11)  // 存儲器數據寬度8bit19             (0 << 10)  // 存儲器數據寬度8bit20             (0 <<  9)  // 外設數據寬度8bit21             (0 <<  8)  // 外設數據寬度8bit22             (1 <<  7)  // 存儲器地址增量模式23             (0 <<  6)  // 外設地址增量模式(不增)24             (0 <<  5)  // 非循環模式25             (0 <<  4)  // 傳輸方向 外設-內存26             (0 <<  3)  // 允許傳輸錯誤中斷27             (0 <<  2)  // 允許半傳輸中斷28             (1 <<  1)  // 允許傳輸完成中斷29             (1);        // 通道開啟30 }



        關鍵詞: STM32SPIDM

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 八宿县| 西藏| 读书| 凤阳县| 长宁区| 松阳县| 克什克腾旗| 横峰县| 尼玛县| 道真| 赣榆县| 泸水县| 丹寨县| 黄龙县| 富民县| 西林县| 石阡县| 临泽县| 论坛| 霍城县| 澄城县| 开阳县| 宜章县| 平原县| 常德市| 彭泽县| 吉木乃县| 巴林右旗| 克拉玛依市| 资中县| 巨鹿县| 华宁县| 长治市| 仁寿县| 中宁县| 平潭县| 六枝特区| 垣曲县| 西青区| 阿鲁科尔沁旗| 内乡县|