基于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是一个比较强大的工具,可这个不是意味着你可以没带基础的话随便使用它,理解协议和里面的每一个含义,才能不至于掉入坑里面。

再者,进去了能否出来,这个要考验你的编码水平和经验了。

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