基於stm32的spi接口dma 數據收發實例解析

一 前記

   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是一個比較強大的工具,可這個不是意味着你可以沒帶基礎的話隨便使用它,理解協議和裏面的每一個含義,才能不至於掉入坑裏面。

再者,進去了能否出來,這個要考驗你的編碼水平和經驗了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章