一是想總結一下SPI總線的特色與注意點,二是總結一下SPI DMA的使用性能
1、SPI信號線說明ui
一般SPI經過4個引腳與外部器件相連:spa
2、原理3d
MOSI腳相互鏈接,MISO腳相互鏈接。這樣,數據在主和從之間串行地傳輸(MSB位在前)。code
通訊老是由主設備發起。主設備經過MOSI腳把數據發送給從設備,從設備經過MISO引腳回傳數據。這意味全雙工通訊的數據輸出和數據輸入是用同一個時鐘信號同步的;時鐘信號由主設備經過SCK腳提供。orm
NSS分爲內部引腳和外部引腳。xml
NSS外部引腳能夠做爲輸入信號或者輸出信號,輸入信號通常用做硬件方式從機的片選,而輸出信號通常用於主SPI去片選與之相連的從SPI。blog
NSS從設備選擇有兩種模式:ip
一、軟件模式內存
能夠經過設置SPI_CR1寄存器的SSM位來使能這種模式,當它爲1時,NSS引腳上的電平由SSI決定。在這種模式下NSS外部引腳能夠用做它用,而內部NSS信號電平能夠經過寫SPI_CR1的SSI位來驅動。
二、硬件模式
兩種方式:
(1)對於主SPI,NSS能夠直接接高電平,對於從SPI,能夠直接接低電平。
(2)當STM32F10xxx工做爲主SPI,而且NSS輸出已經經過SPI_CR2寄存器的SSOE位使能,這時主機的NSS講做爲輸出信號,引腳信號被拉低,全部NSS引腳與這個主SPI的NSS引腳相連並配置爲硬件NSS的SPI設備,將自動變成從SPI設備。
此時兩個的NSS信號線能夠接個上拉電阻直連。
4、DMA說明
DMA是AMBA的先進高性能總線(AHB)上的設備,它有2個AHB端口:一個是從端口,用於配置DMA,另外一個是主端口,使得DMA能夠在不一樣的從設備之間傳輸數據。
DMA的做用是在沒有Cortex-M3核心的干預下,在後臺完成數據傳輸。在傳輸數據的過程當中,主處理器能夠執行其它任務,只有在整個數據塊傳輸結束後,須要處理這些數據時纔會中斷主處理器的操做。它能夠在對系統性能產生較小影響的狀況下,實現大量數據的傳輸。
5、SPI_DMA的通訊過程
6、相關代碼
這裏使用的是SPI1
SPI_DMA配置
1 /******************************************************************************* 2 * Function Name : SPI1_DMA_Configuration 3 * Description : 配置SPI1_RX的DMA通道2,SPI1_TX的DMA通道3 4 * Input : None 5 * Output : None 6 * Return : None 7 * 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_Channel3 54 }
SPI發送
1 /******************************************************************************* 2 * Function Name : SPI1_Send 3 * Description : SPI1的DMA方式發送 4 * Input : SPI1_TX_Buff[SPI1_SendBufferSize] 5 * Output : None 6 * Return : None 7 * Attention : 關閉DMA通道3以前必須等待TXE爲1,等待忙標誌爲0 8 *******************************************************************************/ 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) | // 存儲器數據寬度8bit 17 (0 << 10) | // 存儲器數據寬度8bit 18 (0 << 9) | // 外設數據寬度8bit 19 (0 << 8) | // 外設數據寬度8bit 20 (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_Recive 3 * Description : SPI1的DMA方式接收 4 * Input : None 5 * Output : SPI1_RX_Buff[SPI1_ReciveBufferSize] 6 * Return : None 7 * Attention : 必需要先關閉通道2,而後再配置通道2的參數 8 *******************************************************************************/ 9 void SPI1_Recive( u8 *buff, u32 len ) 10 { 11 DMA1_Channel2->CCR &= ~( 1 << 0 ); //關閉DMA通道2 12 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) | // 存儲器數據寬度8bit 19 (0 << 10) | // 存儲器數據寬度8bit 20 (0 << 9) | // 外設數據寬度8bit 21 (0 << 8) | // 外設數據寬度8bit 22 (1 << 7) | // 存儲器地址增量模式 23 (0 << 6) | // 外設地址增量模式(不增) 24 (0 << 5) | // 非循環模式 25 (0 << 4) | // 傳輸方向 外設-內存 26 (0 << 3) | // 容許傳輸錯誤中斷 27 (0 << 2) | // 容許半傳輸中斷 28 (1 << 1) | // 容許傳輸完成中斷 29 (1); // 通道開啓 30 }