历史上的今天
今天是: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);
}
史海拾趣
|
中证网讯 在由工业和信息化部与中国社科院工业经济研究所26日联合举办的《2009年中国工业经济运行夏季报告》新闻发布会上,工业和信息化部总工程师、新闻发言人朱宏任指出,物联网是一个新概念,到现在为止还没有一个约定俗成的、大家公认的概念。 ...… 查看全部问答> |
|
ARM处理器上电/复位操作 本问节选自《嵌入式系统Linux内核开发实战指南(ARM平台)》一书 ARM处理器上电与复位操作过程类似,都是从处理器的低端复位向量地址0位置读取第一条指令,由于ARM处理器的异常中断向量是连续排列的,所 ...… 查看全部问答> |
|
// Make sure this matches entry in config.bib // These buffs are now offset via a constant [color=#FF0000]#define DMA_BUFFER_BASE & ...… 查看全部问答> |
|
安装ads1.2的时候,在开始->程序->ads1.2下只出现了online books而看不到axd debugger等,重新安装的时候老是出现modify repair等选项。有人知道这个是什么问题吗,多谢指点!… 查看全部问答> |
|
问题一:“请你自我介绍一下” 思路: 1、这是面试的必**目。 2、介绍内容要与个人简历相一致。 3、表述方式上尽量口语化。 4、要切中要害,不谈无关、无用的内容。 5、条理要清晰,层次要分明。 6、事先最好以文字的形式写好背熟。 问题二 ...… 查看全部问答> |




