STM32
直播中

南风一号

8年用户 961经验值
擅长:EMC/EMI设计
私信 关注
[问答]

如何去实现STM32F103的USART3使用DMA模块的程序代码

如何去实现STM32F103的USART3使用DMA模块的程序代码?

回帖(1)

金鼎

2021-12-13 15:07:53
以USART3为例,
(1)首先在【stm32f1xx_hal_conf.h】中使能DMA模块,工程增加stm32f1xx_hal_dma.c。
(2)main.c中头部增加以下声明

UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma1_uart3;
(3)main.c中增加USART的初始化


/* USART3 init function */
static void MX_USART3_UART_Init(void)
{
        huart3.Instance = USART3;
        huart3.Init.BaudRate = 115200;
        huart3.Init.WordLength = UART_WORDLENGTH_8B;
        huart3.Init.StopBits = UART_STOPBITS_1;
        huart3.Init.Parity = UART_PARITY_NONE;
        huart3.Init.Mode = UART_MODE_TX_RX;
        huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        huart3.Init.OverSampling = UART_OVERSAMPLING_16;
        if (HAL_UART_Init(&huart3) != HAL_OK)
        {
                Error_Handler();
        }
}
(4)stm32f1xx_hal_msp.c增加


extern  UART_HandleTypeDef huart3;
extern DMA_HandleTypeDef hdma1_uart3;

......................

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

        GPIO_InitTypeDef GPIO_InitStruct;
       
        if (huart->Instance == USART3)
        {
                /* USER CODE BEGIN USART3_MspInit 0 */

                /* USER CODE END USART3_MspInit 0 */
                /* Peripheral clock enable */
                __HAL_RCC_USART3_CLK_ENABLE();
                __HAL_RCC_DMA1_CLK_ENABLE();

                /**USART3 GPIO Configuration
                PB10     ------> USART3_TX
                PB11     ------> USART3_RX
                */
                GPIO_InitStruct.Pin = GPIO_PIN_10;
                GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
                GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
                HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

                GPIO_InitStruct.Pin = GPIO_PIN_11;
                GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
                GPIO_InitStruct.Pull = GPIO_NOPULL;
                HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
               
               
                hdma1_uart3.Instance = DMA1_Channel2;
                hdma1_uart3.Init.Direction = DMA_MEMORY_TO_PERIPH;
                hdma1_uart3.Init.PeriphInc = DMA_PINC_DISABLE;
                hdma1_uart3.Init.MemInc = DMA_MINC_ENABLE;
                hdma1_uart3.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
                hdma1_uart3.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
                hdma1_uart3.Init.Mode = DMA_NORMAL;
                hdma1_uart3.Init.Priority = DMA_PRIORITY_LOW;
                HAL_DMA_DeInit(&hdma1_uart3);
                HAL_DMA_Init(&hdma1_uart3);
               
                __HAL_LINKDMA(huart, hdmatx, hdma1_uart3);       

                HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 2, 0);
                HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);               
               
                /* Peripheral interrupt init */
                HAL_NVIC_SetPriority(USART3_IRQn, USART_IRQn_PP, 0);
                HAL_NVIC_EnableIRQ(USART3_IRQn);
               
                __HAL_UART_ENABLE_IT(&huart3, USART_IT_RXNE);//使能串口3  读数据寄存器非空中断RXNE
                /* USER CODE BEGIN USART3_MspInit 1 */

                /* USER CODE END USART3_MspInit 1 */
        }

}

void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{

        if (huart->Instance == USART3)
        {
                /* USER CODE BEGIN USART3_MspDeInit 0 */

                /* USER CODE END USART3_MspDeInit 0 */
                /* Peripheral clock disable */
                __HAL_RCC_USART3_CLK_DISABLE();
                __HAL_RCC_DMA1_CLK_DISABLE();
               
                /**USART3 GPIO Configuration
                PB10     ------> USART3_TX
                PB11     ------> USART3_RX
                */
                HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10 | GPIO_PIN_11);
                HAL_DMA_DeInit(&hdma1_uart3);
                /* Peripheral interrupt DeInit*/
                HAL_NVIC_DisableIRQ(USART3_IRQn);
                HAL_NVIC_DisableIRQ(DMA1_Channel2_IRQn);
               
                __HAL_UART_DISABLE_IT(&huart3, USART_IT_RXNE);
                /* USER CODE BEGIN USART3_MspDeInit 1 */

                /* USER CODE END USART3_MspDeInit 1 */
        }

}
(5)stm32f1xx_it.c增加


extern UART_HandleTypeDef huart3;
extern DMA_HandleTypeDef hdma1_uart3;

.............................

/******************************************************
函数名称:USART3_Own_IRQHandler
函数描述:USART3中断服务自定义代码部分
输入参数:pLinuxClass:传入LINUX_OBJECT
返回值:无
******************************************************/
void USART3_Own_IRQHandler(LINUX_CLASS *pLinuxClass)
{
        unsigned char  ucValue;

        // 使用了DMA发送,一定要加UART_FLAG_RXNE判断,否则成功回复一次后,会一直进下面这段,不知道原因
        if ((__HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE)!= RESET))// 接收中断
        {                                                               
                pLinuxClass->Rx_FROM_linux[pLinuxClass->Rx_FROM_linux_Counter] = (uint8_t)(huart3.Instance->DR & 0x00FF);
                pLinuxClass->Rx_FROM_linux_Counter++;
               
                if (pLinuxClass->Rx_FROM_linux_Counter >= RX_LINUX_MAX)
                {
                        pLinuxClass->Rx_FROM_linux_Counter = 0;
                }
               
                pLinuxClass->RX_BYTE_TimeoutCounter_Lock = 0;                // 接收数据字节间超时计时器开启
                pLinuxClass->RX_BYTE_TimeoutCounter = 0;
               
                __HAL_UART_CLEAR_FLAG(&huart3, UART_FLAG_RXNE );
        }
       
        if ((__HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_TC) != RESET) && (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_TC)!= RESET))
        {
                huart3.State = HAL_UART_STATE_BUSY_RX;
               
                __HAL_UART_CLEAR_FLAG(&huart3, UART_FLAG_TC );               
               
                WRITE_485UN; // 485通讯方式
        }
       
                // 溢出-如果发生溢出需要先读SR,再读DR寄存器 则可清除不断入中断的问题
        if (__HAL_UART_GET_FLAG(&huart3,USART_FLAG_ORE) != RESET)
        {
                __HAL_UART_CLEAR_FLAG(&huart3,USART_FLAG_ORE);  // read SR                                                                                                                                                                               
                       
                ucValue = (uint8_t)( huart3.Instance->DR & (uint8_t)0x00FF); // read DR
        }
       
        (void)ucValue;
}

void USART3_IRQHandler(void)
{
        /* USER CODE BEGIN USART3_IRQn 0 */
        USART3_Own_IRQHandler(&LINUX_OBJECT);       
        /* USER CODE END USART3_IRQn 0 */

        /* USER CODE BEGIN USART3_IRQn 1 */

        /* USER CODE END USART3_IRQn 1 */
}

void DMA1_Channel2_IRQHandler(void)
{
        HAL_DMA_IRQHandler(&hdma1_uart3);
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分