zoukankan      html  css  js  c++  java
  • [STM32F429-DISCO-HAL]4.Uart 的使用

    今天来学习一下最常用的外设之一USART。

    首先是硬件的连接,我们需要至少三根线,GND,TX,RX。参阅datasheet。默认的USART1_TX和USART1_RX的引脚如下图

    image

    关于HAL drivers的文档 尽量多查阅【UM1725】 User Manual Description of STM32F4xx HAL drivers和 STM32Cube_FW_F4_V1.5.0DriversSTM32F4xx_HAL_DriverSTM32F439xx_User_Manual.chm。

    首先我们用最简单的查询方式来使用UART

    1.定义好UART_HandleTypeDef结构体。因为Polling模式,只需指定UART的实例和配置参数即可。即UART_HandleTypeDef结构体前两个变量定义好。

    2.配置IO口,在stm32f4xx_hal_msp.c中定义好HAL_UART_MspInit()回调函数后,在初始化外设时,系统会自动调用它,因此我们利用这个函数来配置我们的GPIO。

    ///////////////////Uart.c///////////////////////
    UART_HandleTypeDef UartHandle;
    void init_Uart(void)
    {
        UartHandle.Instance      = USART1;
        UartHandle.Init.BaudRate     = 115200;
        UartHandle.Init.WordLength   = UART_WORDLENGTH_8B;
        UartHandle.Init.StopBits     = UART_STOPBITS_1;
        UartHandle.Init.Parity       = UART_PARITY_NONE;
        UartHandle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
        UartHandle.Init.Mode         = UART_MODE_TX_RX;
        UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
        
        if(HAL_UART_Init(&UartHandle) != HAL_OK)
        {
            LCD_TEXT_STRINGLINE("error with USART Init");
        }
    
    }
    
    ///////////////stm32f4xx_hal_msp.c///////////////////////
    void HAL_UART_MspInit(UART_HandleTypeDef *huart)
    {  
      GPIO_InitTypeDef  GPIO_InitStruct;
      
      /******Enable peripherals and GPIO Clocks ***/
      /* Enable GPIO TX/RX clock */
      __HAL_RCC_GPIOA_CLK_ENABLE();
      /* Enable USART1 clock */
      __HAL_RCC_USART1_CLK_ENABLE();
      
      /**** Configure peripheral GPIO *****/  
      /* UART TX GPIO pin configuration  */
      GPIO_InitStruct.Pin       = GPIO_PIN_9;
      GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull      = GPIO_NOPULL;
      GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;
      GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
      
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        
      /* UART RX GPIO pin configuration  */
      GPIO_InitStruct.Pin = GPIO_PIN_10;
      GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
        
      HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    }

    然后调用HAL_UART_Init(&UartHandle) 成功返回HAL_OK,我们的UART1就可以用了

    对于查询方式,UART的发送接受数据我们仅使用两个函数 HAL_UART_Transmit()、 HAL_UART_Receive() 来实现就可以了

    一个例子:HAL_UART_Transmit(&UartHandle, txbuf, size, 5000);这里的参数:UartHandle就是我们刚刚定义的uart实例,txbuf为字符串,size为字符串长度。5000为等待超时时间。

    OK使用就这么简单。对于大部分的应用来说,都可以满足了。

    使用DMA来完成传输

    如果使用DMA来传输的话,我们需要做一下修改了,首先是要配置一下DMA模块,我们使用同一个DMA通道的两个流来分别做为TX、RX的传输路径。

    HAL_UART_MspInit()函数中添加如下代码

    void HAL_UART_MspInit(UART_HandleTypeDef *huart)
    { 
      static DMA_HandleTypeDef hdma_tx;
      static DMA_HandleTypeDef hdma_rx;    
      GPIO_InitTypeDef  GPIO_InitStruct;
    
        /******Enable peripherals and GPIO Clocks ***/
        /* Enable GPIO TX/RX clock */
        __HAL_RCC_GPIOA_CLK_ENABLE();
        /* Enable USART1 clock */
        __HAL_RCC_USART1_CLK_ENABLE();
        /* Enable DMA2 Clock*/
        __HAL_RCC_DMA2_CLK_ENABLE();
        /**** Configure peripheral GPIO *****/  
        /* UART TX GPIO pin configuration  */
        GPIO_InitStruct.Pin       = GPIO_PIN_9;
        GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull      = GPIO_NOPULL;
        GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;
        GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
      
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        
        /* UART RX GPIO pin configuration  */
        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
        
        HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
        
        
        ////////////////////////configure the DMA///////////////
        hdma_tx.Instance                 = DMA2_Stream7;
      
        hdma_tx.Init.Channel             = DMA_CHANNEL_4;
        hdma_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
        hdma_tx.Init.PeriphInc           = DMA_PINC_DISABLE;    
        hdma_tx.Init.MemInc              = DMA_MINC_ENABLE;
        hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
        hdma_tx.Init.Mode                = DMA_NORMAL;
        hdma_tx.Init.Priority            = DMA_PRIORITY_LOW;
        hdma_tx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
        hdma_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
        hdma_tx.Init.MemBurst            = DMA_MBURST_INC4;
        hdma_tx.Init.PeriphBurst         = DMA_PBURST_INC4;
      
        HAL_DMA_Init(&hdma_tx);   
      
        /* Associate the initialized DMA handle to the the UART handle */
        __HAL_LINKDMA(huart, hdmatx, hdma_tx);
        
        /* Configure the DMA handler for Transmission process */
        hdma_rx.Instance                 = DMA2_Stream5;
      
        hdma_rx.Init.Channel             = DMA_CHANNEL_4;
        hdma_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
        hdma_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
        hdma_rx.Init.MemInc              = DMA_MINC_ENABLE;
        hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
        hdma_rx.Init.Mode                = DMA_NORMAL;
        hdma_rx.Init.Priority            = DMA_PRIORITY_HIGH;
        hdma_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;         
        hdma_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
        hdma_rx.Init.MemBurst            = DMA_MBURST_INC4;
        hdma_rx.Init.PeriphBurst         = DMA_PBURST_INC4; 
    
        HAL_DMA_Init(&hdma_rx);
        
        /* Associate the initialized DMA handle to the the UART handle */
        __HAL_LINKDMA(huart, hdmarx, hdma_rx);
            
        /*Configure the NVIC for DMA*/
        /* NVIC configuration for DMA transfer complete interrupt (USARTx_TX) */
        HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 1);
        HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
        
        /* NVIC configuration for DMA transfer complete interrupt (USARTx_RX) */
        HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0, 0);   
        HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
      
        /* NVIC configuration for USART TC interrupt */
        HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
        
    }

    这段代码添加了 hdma_tx,hdama_rx的数据结构来初始化分别初始化发送、接收的dma初始化,启动了dma2的时钟,连接uart1与dma,并且启动了两个DMA流和USART1的中断。

    中断服务函数的文件stm32f4xx_it.c中添加相关的ISR

    void DMA2_Stream5_IRQHandler(void)
    {
        HAL_DMA_IRQHandler(UartHandle.hdmarx);
    }
    
    
    void DMA2_Stream7_IRQHandler(void)
    {
      HAL_DMA_IRQHandler(UartHandle.hdmatx);
    }
    
    
    void USART1_IRQHandler(void)
    {
      HAL_UART_IRQHandler(&UartHandle);
    }

    这样我们就可以直接使用

    HAL_UART_Transmit_DMA、HAL_UART_Recieve_DMA函数来完成uart数据传输了。

    初步的尝试结果得出,HAL让我们不必关心太多底层的细节,比较适合快速的开发。但是要想熟练的使用,我们还是要学会使用固件库以及一些寄存器的配制方法,不可巧取。

  • 相关阅读:
    寄存器英文全称
    汇编指令介绍
    汇编指令的基本知识
    第一篇
    Windows下让Git记住用户名密码(https)
    javascript 汉字拼音排序
    KO.js学习笔记(一)
    学javascript突发奇想,只用浏览器就能转换进制
    谨此纪念我的技术成长之路
    委托与事件
  • 原文地址:https://www.cnblogs.com/priestyoyo/p/4430325.html
Copyright © 2011-2022 走看看