最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

【全球新要闻】STM32 SPI DMA 源码解析及总结

来源:博客园


(资料图片)

一 前言最近在调试stm32的SPI时候i,遇到了一个非常诡异的问题。中间花费了不少时间才把问题搞定。这中间暴露的问题值得反思。借此机会,还是梳理一下stm32的SPI的代码做一个总结吧。二 初始化1.SPI接口的初始化比较标准,和几乎所有的stm32外围接口一样,分为接口初始化和链接部分组成:接口初始化:
/* SPI2 init function */void MX_SPI2_Init(void){  /* USER CODE BEGIN SPI2_Init 0 */  /* USER CODE END SPI2_Init 0 */  /* USER CODE BEGIN SPI2_Init 1 */  /* USER CODE END SPI2_Init 1 */  hspi2.Instance = SPI2;  hspi2.Init.Mode = SPI_MODE_MASTER;  hspi2.Init.Direction = SPI_DIRECTION_2LINES;  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;  hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;  hspi2.Init.NSS = SPI_NSS_SOFT;  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;  hspi2.Init.CRCPolynomial = 7;  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;  hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;  if (HAL_SPI_Init(&hspi2) != HAL_OK)  {    Error_Handler();  }  /* USER CODE BEGIN SPI2_Init 2 */  /* USER CODE END SPI2_Init 2 */

链接:

/* USER CODE END SPI2_MspInit 0 */    /* SPI2 clock enable */    __HAL_RCC_SPI2_CLK_ENABLE();    __HAL_RCC_GPIOB_CLK_ENABLE();    /**SPI2 GPIO Configuration    PB13     ------> SPI2_SCK    PB14     ------> SPI2_MISO    PB15     ------> SPI2_MOSI    */    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;    GPIO_InitStruct.Pull = GPIO_PULLUP;    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);    /* SPI2 DMA Init */    /* SPI2_TX Init */    hdma_spi2_tx.Instance = DMA1_Channel5;    hdma_spi2_tx.Init.Request = DMA_REQUEST_1;    hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;    hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;    hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;    hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;    hdma_spi2_tx.Init.Mode = DMA_NORMAL;    hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;    if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)    {      Error_Handler();    }    __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi2_tx);    /* SPI2_RX Init */    hdma_spi2_rx.Instance = DMA1_Channel4;    hdma_spi2_rx.Init.Request = DMA_REQUEST_1;    hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;    hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;    hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;    hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;    hdma_spi2_rx.Init.Mode = DMA_NORMAL;    hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW;    if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK)    {      Error_Handler();    }    __HAL_LINKDMA(spiHandle,hdmarx,hdma_spi2_rx);    /* SPI2 interrupt Init */    HAL_NVIC_SetPriority(SPI2_IRQn, 7, 0);    HAL_NVIC_EnableIRQ(SPI2_IRQn);
注意事项:这里面调试的时候注意以下几个地方:一个是接口不能被复用了。另外一个是接口硬件部分是通的。这两个可以通过GPIO的拉高拉地来测电平实现。另外一个就是系统的主频要注意,尽量不要设置太高,因为有些SPI接口速率没那么高的。三 数据收发:1.数据发送:HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);2.数据接收:HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);3.注意事项:其实,数据收发一般不会出问题,可是一旦出问题了,就不是小问题。这里,注意几个东西。由于是DMA接收和发送,所以CS一定要拉地的时间尽量长,系统允许的话,开始的时候,尽量不要随意拉高CS。否则会出现丢数据的情况。四 总结1.不要盲目详细计算机。它不会代替你思考的。遇到了问题,还是要凭借对代码的理解和实践出来的技能来判断的。

关键词: 注意事项 尽量不要 另外一个