一 前記
SPI接口平時用的比較少,再加上對CUBEMX不是很熟悉,這裏踩了不少坑才把問題解決。針對遇到了不少問題,是要值得梳理一下了。
二 源碼解析
1 SPI的DMA發送端配置:
2 主函數源碼:
uint32_t g_spi_cnt = 0; void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) { g_spi_cnt++; } 2 主函數源碼: /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_SPI2_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ uart1_test(); memset(TX_Data,0x01,DATA_SIZE); /* USER CODE END 2 */ HAL_SPI_Transmit_DMA(&hspi2, TX_Data, sizeof(TX_Data)); /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ HAL_Delay(1000); mprintf("g_spi_master_dma_cnt 2.18h is:0x%x \n\r",g_spi_cnt%0xff); for (uint32_t iss = 0; iss < DATA_SIZE; iss++) { /* code */ TX_Data[iss] = g_spi_cnt%0xff; } dump8(TX_Data,sizeof(TX_Data)); HAL_SPI_Transmit_DMA(&hspi2, TX_Data, sizeof(TX_Data)); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
3 SPI的DMA接收端配置:
4 SPI SLAVE源碼:
#define DATA_SIZE 64 uint8_t RX_Data[DATA_SIZE]; uint32_t g_spi_cnt = 0; void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef * hspi) { HAL_SPI_Receive_DMA(&hspi2, RX_Data, DATA_SIZE); dump8(RX_Data,10); g_spi_cnt++; mprintf("g_spi_slave_cnt 2.18hh is:%d \n\r",g_spi_cnt); } /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_SPI2_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ uart1_test(); /* USER CODE END 2 */ memset(RX_Data,0x00,sizeof(RX_Data)); HAL_SPI_Receive_DMA(&hspi2, RX_Data, sizeof(RX_Data)); /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ //HAL_Delay(200); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
三 總結
1 DMA的配置模式,
筆者剛開始根據網上的資料,配置了circular模式,發現接收側一直收到莫名其妙的數據,並且數據經常出錯。
修改成了normal模式之後,接收到的數據就對了。關於這兩種模式的區別,我已經在前文中介紹過了。
2 SPI位寬設置:
這裏遇到的另外一個大問題就是SPI位寬,cube軟件默認是4bit,加入按照這個模式設置,你會發現只收到後四個bit的數據,前四個bit爲零。
所以,把這個改稱8bit是一個必備的。如下圖所示:
3 感觸:
stm32 CUBE MX是一個比較強大的工具,可這個不是意味着你可以沒帶基礎的話隨便使用它,理解協議和裏面的每一個含義,才能不至於掉入坑裏面。
再者,進去了能否出來,這個要考驗你的編碼水平和經驗了。