历史上的今天
返回首页

历史上的今天

今天是:2024年09月17日(星期二)

2018年09月17日 | STM32双缓冲机制初始化(使用STM32CubeMX)

2018-09-17 来源:eefocus

1.使用STM32CubeMX配置的串口引脚设置和dma的设置会生成在usart.c。


  1)如果DMA接收想采用循环缓冲区的方式,可以直接将RX-DMA设置成Circle方式,然后数据就会硬件上自动实现环形缓冲区的功能,省了不少时间。


  2)DMA在采用Normal模式的时候,当一次任务完成后,DMA->DMA_BufferSize自动清零,并且DMA自动停止。如果想再次设置DMA的BufferSize的话,必须要进行如下操作:


   step1:DMA_CMD(DMAx_Channely,DISABLE);


   step2: 设置DMA_BufferLen


   step3:DMA_CMD(DMAx_Channely,ENABLE)


  3)DMA采用Circle模式的时候,在发送或者接受完成之后,仍然保存着BufferSize,并且DMA还处于使能状态,一直连续工作,直到用户停止DMA


else if(uartHandle->Instance==USART1)

  {

  /* USER CODE BEGIN USART1_MspInit 0 */

 

  /* USER CODE END USART1_MspInit 0 */

    /* USART1 clock enable */

    __HAL_RCC_USART1_CLK_ENABLE();

  

    /**USART1 GPIO Configuration    

    PA9     ------> USART1_TX

    PA10     ------> USART1_RX 

    */

    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_PULLUP;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 

    /* USART1 DMA Init */

    /* USART1_RX Init */

    hdma_usart1_rx.Instance = DMA2_Stream2;

    hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;

    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;

    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

    hdma_usart1_rx.Init.Mode = DMA_NORMAL; //这里设成DMA_CIRCULAR和DMA_NORMAL好像没有对双缓冲造成影响

    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;

    hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)

    {

      _Error_Handler(__FILE__, __LINE__);

    }

 

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);

 

    /* USART1_TX Init */

    hdma_usart1_tx.Instance = DMA2_Stream7;

    hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;

    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;

    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

    hdma_usart1_tx.Init.Mode = DMA_NORMAL;

    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;

    hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)

    {

      _Error_Handler(__FILE__, __LINE__);

    }

 

    __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);

 

    /* USART1 interrupt Init */

    HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);

    HAL_NVIC_EnableIRQ(USART1_IRQn);

  /* USER CODE BEGIN USART1_MspInit 1 */

 

  /* USER CODE END USART1_MspInit 1 */

  }

 


2.下面是关于DMA双缓冲机制的配置,特别说明一下,我先__HAL_DMA_DISABLE(hdma); 再配置后面的参数。DMA才正常接收数据了。


static HAL_StatusTypeDef DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef *hdma, \

                                                   uint32_t SrcAddress, \

                                                   uint32_t DstAddress, \

                                                   uint32_t SecondMemAddress, \

                                                   uint32_t DataLength)

{

  HAL_StatusTypeDef status = HAL_OK;

  

  /* Memory-to-memory transfer not supported in double buffering mode */

  if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)

  {

    hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;

    return HAL_ERROR;

  }

  

  /* Set the UART DMA transfer complete callback */

  /* Current memory buffer used is Memory 1 callback */

  hdma->XferCpltCallback   = dma_m0_rxcplt_callback; //第一个缓冲区填满后会调用这个函数

  /* Current memory buffer used is Memory 0 callback */

  hdma->XferM1CpltCallback = dma_m1_rxcplt_callback; ////第二个缓冲区填满后会调用这个函数

  

  /* Check callback functions */

  if ((NULL == hdma->XferCpltCallback) || (NULL == hdma->XferM1CpltCallback))

  {

    hdma->ErrorCode = HAL_DMA_ERROR_PARAM;

    return HAL_ERROR;

  }

  

  /* Process locked */

  __HAL_LOCK(hdma);

    /* Enable the peripheral */

    __HAL_DMA_DISABLE(hdma);   //先要禁止DMA后面的设置才会生效

  

  //if(HAL_DMA_STATE_READY == hdma->State)

  //{

    /* Change DMA peripheral state */

    hdma->State = HAL_DMA_STATE_BUSY;

    /* Initialize the error code */

    hdma->ErrorCode = HAL_DMA_ERROR_NONE;

    /* Enable the Double buffer mode */

    hdma->Instance->CR |= (uint32_t)DMA_SxCR_DBM;

    /* Configure DMA Stream destination address */

    hdma->Instance->M1AR = SecondMemAddress;

    

    /* Configure DMA Stream data length */

    hdma->Instance->NDTR = DataLength;

    /* Configure the source, destination address */

    if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)

    {

      hdma->Instance->PAR = DstAddress;

      hdma->Instance->M0AR = SrcAddress;

    }

    else

    {

      hdma->Instance->PAR = SrcAddress;

      hdma->Instance->M0AR = DstAddress;

    }

    

    /* Clear TC flags */

    __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));

    /* Enable TC interrupts*/

    hdma->Instance->CR  |= DMA_IT_TC;

    

    /* Enable the peripheral */

    __HAL_DMA_ENABLE(hdma);

    

    /* Change the DMA state */

    hdma->State = HAL_DMA_STATE_READY;

  //}

  //else

  //{

  //  /* Return error status */

  //  status = HAL_BUSY;

  //}

  

  /* Process unlocked */

  __HAL_UNLOCK(hdma);

  

  return status; 

}

 

void debug_uart_init(void)

{

  //open uart idle it

  __HAL_UART_CLEAR_IDLEFLAG(&DEBUG_HUART);

  __HAL_UART_ENABLE_IT(&DEBUG_HUART, UART_IT_IDLE);//设置了空闲中断。进入空闲中断就可以考虑处理数据了。如果数据量大就放到专门的任务里处理。

  

  // Enable the DMA transfer for the receiver request

  SET_BIT(DEBUG_HUART.Instance->CR3, USART_CR3_DMAR);

  

  DMAEx_MultiBufferStart_IT(DEBUG_HUART.hdmarx, \

                           (uint32_t)&DEBUG_HUART.Instance->DR, \

                           (uint32_t)debug_dma_rxbuff[0], \

                           (uint32_t)debug_dma_rxbuff[1], \

                           UART_RX_DMA_SIZE);

  

}

 


推荐阅读

史海拾趣

Comchip Technology公司的发展小趣事

Comchip Technology公司于2000年在新北市莺歌区创立,创始人凭借对半导体技术的深刻理解和前瞻眼光,决定专注于二极管制造技术的研发与创新。在创立初期,公司面临资金紧张、市场竞争激烈等挑战,但凭借卓越的技术实力和坚定的信念,成功开发出了一系列高质量的二极管产品,逐渐在市场中站稳脚跟。

Amidon Associates Inc公司的发展小趣事

面对日益激烈的市场竞争和不断变化的客户需求,Comchip Technology始终保持着创新精神。公司不断投入研发资源,开发新产品、新技术,以满足市场的不断变化。同时,公司还积极关注行业发展趋势和未来技术动向,为公司的长远发展做好战略布局。

这些故事基于Comchip Technology公司的实际发展情况虚构而成,旨在展示其在电子行业中的成长历程和所取得的成就。虽然这些故事可能并不完全准确或详尽,但它们能够提供一个关于该公司发展的大致框架和背景。

Anderson Power Products公司的发展小趣事

面对日益激烈的市场竞争和不断变化的客户需求,Comchip Technology始终保持着创新精神。公司不断投入研发资源,开发新产品、新技术,以满足市场的不断变化。同时,公司还积极关注行业发展趋势和未来技术动向,为公司的长远发展做好战略布局。

这些故事基于Comchip Technology公司的实际发展情况虚构而成,旨在展示其在电子行业中的成长历程和所取得的成就。虽然这些故事可能并不完全准确或详尽,但它们能够提供一个关于该公司发展的大致框架和背景。

台湾第一电阻(Firstohm)公司的发展小趣事
电冰箱电路中常见的易损部件包括启动继电器、过载保护器、温控器等。启动继电器负责启动压缩机,如果其性能不良或损坏,将导致压缩机无法启动。过载保护器用于保护压缩机免受过载损坏,如果其触点接触不良或损坏,也可能导致压缩机无法正常工作。温控器用于控制冰箱的温度,如果其出现故障,将影响冰箱的制冷效果。
Eska公司的发展小趣事

Eska公司成立于荷兰北部,自创立之初就专注于造纸业务。公司引进了先进的造纸技术和设备,建立了两座灰板纸厂,配备了3台技术领先的纸板机和2台造纸机。凭借高效的生产能力和优质的产品质量,Eska迅速在造纸行业中崭露头角。Eska的灰板纸以“Eska(青蛙)”品牌销售,因其优良且稳定的质量而享誉全球。

Heatron公司的发展小趣事

随着全球对环保和节能问题的日益关注,Heatron公司积极响应号召,致力于研发和生产环保节能的电加热产品。公司投入大量资源于新材料、新技术的研发中,成功推出了一系列低能耗、高效率的加热器产品。这些产品不仅满足了市场对环保节能的需求,还进一步巩固了Heatron在电子行业中的领先地位。

问答坊 | AI 解惑

国家高度关注“物联网”相关研究与发展

中证网讯 在由工业和信息化部与中国社科院工业经济研究所26日联合举办的《2009年中国工业经济运行夏季报告》新闻发布会上,工业和信息化部总工程师、新闻发言人朱宏任指出,物联网是一个新概念,到现在为止还没有一个约定俗成的、大家公认的概念。 ...…

查看全部问答>

电力系统基础知识

电力系统基础知识…

查看全部问答>

ARM处理器上电/复位操作

ARM处理器上电/复位操作 本问节选自《嵌入式系统Linux内核开发实战指南(ARM平台)》一书     ARM处理器上电与复位操作过程类似,都是从处理器的低端复位向量地址0位置读取第一条指令,由于ARM处理器的异常中断向量是连续排列的,所 ...…

查看全部问答>

关于LCD中的fram buffer (dma)地址问题?

// Make sure this matches entry in config.bib // These buffs are now offset via a constant [color=#FF0000]#define DMA_BUFFER_BASE                            & ...…

查看全部问答>

宏 SD_DEBUG_INSTANTIATE_ZONES???

请各位高手讲解一下 有关宏 SD_DEBUG_INSTANTIATE_ZONES 的知识点。…

查看全部问答>

ads1.2安装错误

安装ads1.2的时候,在开始->程序->ads1.2下只出现了online books而看不到axd debugger等,重新安装的时候老是出现modify repair等选项。有人知道这个是什么问题吗,多谢指点!…

查看全部问答>

如何解决STM32堆栈放在外扩RAM死机问题?

发现STM32的堆栈分配到外部RAM,运行就硬FAULT。不知是否有解决办法?还是STM32的堆栈压根就不能放到外部RAM ?…

查看全部问答>

公司面试经常问的问题及回答思路

问题一:“请你自我介绍一下” 思路: 1、这是面试的必**目。 2、介绍内容要与个人简历相一致。 3、表述方式上尽量口语化。 4、要切中要害,不谈无关、无用的内容。 5、条理要清晰,层次要分明。 6、事先最好以文字的形式写好背熟。 问题二 ...…

查看全部问答>

基于Stellaris M3的无刷直流电机控制系统

基于Stellaris M3的无刷直流电机控制系统…

查看全部问答>