stm32CUBEIDE 生成的串口初始化代码详解

2023-05-16

static void MX_USART1_UART_Init(void)
{  
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }

}

前面是串口的一些配置。

HAL_UART_Init(&huart1)是真正的初始化函数。
初始化函数定义在\Drivers\Stm32F1xx_HAL_Drivers\Src\stm32f1xx_hal_uart.c 中。

HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
{
  /* Check the UART handle allocation */
  if (huart == NULL)      
  {
    return HAL_ERROR;
  }

  /* Check the parameters */
  if (huart->Init.HwFlowCtl != UART_HWCONTROL_NONE)     //硬件流控制吗
  {
    /* The hardware flow control is available only for USART1, USART2 and USART3 */
    assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance));
    assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl));
  }
  else
  {
    assert_param(IS_UART_INSTANCE(huart->Instance));
  }
  assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));  //检查数据位

#if defined(USART_CR1_OVER8)
  assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling));
#endif /* USART_CR1_OVER8 */

  if (huart->gState == HAL_UART_STATE_RESET)
  {
    /* Allocate lock resource and initialize it */
    huart->Lock = HAL_UNLOCKED;

#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
    UART_InitCallbacksToDefault(huart);

    if (huart->MspInitCallback == NULL)
    {
      huart->MspInitCallback = HAL_UART_MspInit;
    }

    /* Init the low level hardware */
    huart->MspInitCallback(huart);
#else
    /* Init the low level hardware : GPIO, CLOCK */
    HAL_UART_MspInit(huart);         //--->>>跳转到\Src\stm32f1xx_hal_msp.c 
    //在这个函数中初始化了时钟、GPIO、中断
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
  }

  huart->gState = HAL_UART_STATE_BUSY;

  /* Disable the peripheral */
  __HAL_UART_DISABLE(huart);

  /* Set the UART Communication parameters */
  UART_SetConfig(huart);                 //真正配置寄存器

  /* In asynchronous mode, the following bits must be kept cleared:
     - LINEN and CLKEN bits in the USART_CR2 register,
     - SCEN, HDSEL and IREN  bits in the USART_CR3 register.*/
  CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
  CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));

  /* Enable the peripheral */
  __HAL_UART_ENABLE(huart);   //使能串口

  /* Initialize the UART state */
  huart->ErrorCode = HAL_UART_ERROR_NONE;
  huart->gState = HAL_UART_STATE_READY;
  huart->RxState = HAL_UART_STATE_READY;

  return HAL_OK;
}

//中断服务函数,在\Src\stm32f1xx_it.c中定义

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}
//中断服务函数,在\Drivers\Stm32F1xx_HAL_Drivers\Src\stm32f1xx_hal_uart.c中给定义好了
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
  uint32_t isrflags   = READ_REG(huart->Instance->SR);         //读取SR寄存器
  uint32_t cr1its     = READ_REG(huart->Instance->CR1);      //读取CR1寄存器
  uint32_t cr3its     = READ_REG(huart->Instance->CR3);    //读取CR3寄存器
  uint32_t errorflags = 0x00U;   
  uint32_t dmarequest = 0x00U;

  /* If no error occurs */
  errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));  
   //如果出现错误:PE校验错误;FE: 帧错误;ORE:过载错误;NE: 噪声错误
  if (errorflags == RESET)     //RESET=0 ;如果没错误
  {
    /* UART in mode Receiver -------------------------------------------------*/
    if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))   
    //RXNE:读数据寄存器非空 ,0:数据没有收到;1:收到数据,可以读出。  
    //RXNEIE:接收缓冲区非空中断使能 (RXNE interrupt enable)   该位由软件设置或清除。
    //0:禁止产生中断;
    //1:当USART_SR中的ORE或者RXNE为’1’时,产生USART中断。
    {
      UART_Receive_IT(huart);                        //处理函数
      return;
    }
  }

  /* If some errors occur */
  /*如果有错误发生*/
  if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
     //EIE:错误中断使能 (Error interrupt enable)
    //在多缓冲区通信模式下,当有帧错误、过载或者噪声错误时(USART_SR中的FE=1,或者
    //ORE=1,或者NE=1)产生中断。
    //0:禁止中断;
    //1:只要USART_CR3中的DMAR=1,并且USART_SR中的FE=1,或者ORE=1,或者NE=1,
    //则产生中断
    
   //RXNEIE:接收缓冲区非空中断使能 (RXNE interrupt enable)
  //该位由软件设置或清除。
  //0:禁止产生中断;
  //1:当USART_SR中的ORE或者RXNE为’1’时,产生USART中断。
  // PEIE: PE中断使能 (PE interrupt enable)
 //该位由软件设置或清除。
 //0:禁止产生中断;
 //1:当USART_SR中的PE为’1’时,产生USART中断
  {
    /* UART parity error interrupt occurred ----------------------------------*/
    if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_PE;
    }

    /* UART noise error interrupt occurred -----------------------------------*/
    if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_NE;
    }

    /* UART frame error interrupt occurred -----------------------------------*/
    if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_FE;
    }

    /* UART Over-Run interrupt occurred --------------------------------------*/
    if (((isrflags & USART_SR_ORE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_ORE;
    }

    /* Call UART Error Call back function if need be --------------------------*/
    if (huart->ErrorCode != HAL_UART_ERROR_NONE)
    {
      /* UART in mode Receiver -----------------------------------------------*/
      if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
      {
        UART_Receive_IT(huart);
      }

      /* If Overrun error occurs, or if any error occurs in DMA mode reception,
         consider error as blocking */
      dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
      if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
      {
        /* Blocking error : transfer is aborted
           Set the UART state ready to be able to start again the process,
           Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
        UART_EndRxTransfer(huart);

        /* Disable the UART DMA Rx request if enabled */
        if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
        {
          CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);

          /* Abort the UART DMA Rx channel */
          if (huart->hdmarx != NULL)
          {
            /* Set the UART DMA Abort callback :
               will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
            huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
            if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
            {
              /* Call Directly XferAbortCallback function in case of error */
              huart->hdmarx->XferAbortCallback(huart->hdmarx);
            }
          }
          else
          {
            /* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
            /*Call registered error callback*/
            huart->ErrorCallback(huart);
#else
            /*Call legacy weak error callback*/
            HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
          }
        }
        else
        {
          /* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
          /*Call registered error callback*/
          huart->ErrorCallback(huart);
#else
          /*Call legacy weak error callback*/
          HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
        }
      }
      else
      {
        /* Non Blocking error : transfer could go on.
           Error is notified to user through user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /*Call registered error callback*/
        huart->ErrorCallback(huart);
#else
        /*Call legacy weak error callback*/
        HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */

        huart->ErrorCode = HAL_UART_ERROR_NONE;
      }
    }
    return;
  } /* End if some error occurs */

  /* UART in mode Transmitter ------------------------------------------------*/
  if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
  {
    UART_Transmit_IT(huart);
    return;
  }

  /* UART in mode Transmitter end --------------------------------------------*/
  if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
  {
    UART_EndTransmit_IT(huart);
    return;
  }
}
//中断接收
/**
  * @brief  Receives an amount of data in non blocking mode
  * @param  huart  Pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval HAL status
  */
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
  uint16_t *tmp;

  /* Check that a Rx process is ongoing */
  if (huart->RxState == HAL_UART_STATE_BUSY_RX)   //如果忙
  {
    if (huart->Init.WordLength == UART_WORDLENGTH_9B)  //  1:一个起始位, 9个数据位, n个停止位。
    {
      tmp = (uint16_t *) huart->pRxBuffPtr;                //tmp =pRxBuffPtr,接收缓冲器
      if (huart->Init.Parity == UART_PARITY_NONE)//无奇偶校验
      {
        *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
        huart->pRxBuffPtr += 2U; 
      }
      else
      {
        *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
        huart->pRxBuffPtr += 1U;
      }
    }
    else    //数据位8位7位小于等于8位....
    {
      if (huart->Init.Parity == UART_PARITY_NONE) 
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);//没有奇偶校验,全部为数据
      }
      else
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);//有奇偶校验,除掉第8位,取得7位数据
      }
    }

    if (--huart->RxXferCount == 0U)
    {
      /* Disable the UART Data Register not empty Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);  //关闭中断

      /* Disable the UART Parity Error Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_PE);   //关闭中断

      /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
      __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);  //关闭中断

      /* Rx process is completed, restore huart->RxState to Ready */
      huart->RxState = HAL_UART_STATE_READY;    //接收完成

#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
      /*Call registered Rx complete callback*/
      huart->RxCpltCallback(huart);
#else
      /*Call legacy weak Rx complete callback*/
      HAL_UART_RxCpltCallback(huart);      //中断服务函数
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */

      return HAL_OK;
    }
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)   //本函数是__weak ,需要重写。
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_UART_RxCpltCallback could be implemented in the user file
   */
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

stm32CUBEIDE 生成的串口初始化代码详解 的相关文章

  • 基于ESP32四旋翼无人机同蓝牙遥控器通信处理方式

    1 蓝牙初始化 在app main调用函数初始化蓝牙 inf ble gatt init 2 判断蓝牙是否链接 在dandelion task中调用函数inf ble gatt connected 判断蓝牙是否链接 xff0c 进而调用da
  • 论文Handheld Multi-Frame Super-Resolution的相关学习笔记

    导语 这里汇总了阅读这篇论文可能会参考到的相关知识汇总 xff0c 这篇主要为了让自己查找方便 但是也希望阅读这篇博文的你能够通过我的笔记更快理解 上手这篇论文 文章题目 xff1a Hand held Multi frame super
  • ASP读EXCEL2000的文章!!!

    由于工作需要 要用ASP读取EXCEL的工资单 所以在网上找了些资料 写了以下程序 送给大家 xff1a xff09 lt 39 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 6
  • Linux下软件安装方法

    对于Linux初学者来说 xff0c 安装一个很小的软件恐怕都是一件很让人头疼的事 xff0c 因为在Linux下安装软件不像在 Windows中那样简单 在Linux中大多数软件提供的是源代码 xff0c 而不是现成的可执行文件 xff0
  • linux指令大全(二)

    cat cd chmod chown cp cut 名称 xff1a cat 使用权限 xff1a 所有使用者 使用方式 xff1a cat AbeEnstTuv help version fileName 说明 xff1a 把档案串连接后
  • 详解C++STL容器系列(一)—— vector的详细用法和底层原理

    目录 一 介绍二 vector的创建和方法创建vector方法 三 vector的具体用法3 1 遍历vector3 1 1 迭代器访问3 1 2 下标访问3 1 3 范围for循环 3 2 vector 容量和大小3 3 vector 常
  • FTP的命令行格式

    From LinuxSir org 非常感谢javalee大哥 FTP的命令行格式为 xff1a ftp v d i n g 主机名 xff0c 其中 v 显示远程服务器的所有响应信息 xff1b n 限制ftp的自动登录 xff0c 即不
  • 一句话问答(网络无关篇+网络相关篇)

    一句话问答 网络无关篇 43 网络相关篇 网络无关篇 0001 修改主机名 vi etc sysconfig network xff0c 修改HOSTNAME一行为HOSTNAME 61 主机名 xff0c 重启后也能生效 0002 Ret
  • linux下各种分区的自动挂载和卸载.

    目前实现分区自动挂载 卸载的方法 我知道的 有两种 一种是supermount 一种是automount supermount要重新编译内核 而且不稳定 这里就不介绍了 我介绍一下automount的使用方法 首先确认你的linux已经安装
  • Linux 挂载文件系统

    1 挂载点必须是一个目录 2 一个分区挂载在一个已存在的目录上 xff0c 这个目录可以不为空 xff0c 但挂载后这个目录下以前的内容将不可用 对于其他操作系统建立的文件系统的挂载也是这样 但是需要理解的是 xff1a 光盘 软盘 其他操
  • 新浪网人力资源总监段冬聊企业对人才的需求

    http edu sina com cn l 2004 12 02 ba93631 shtml 新浪网人力资源总监段冬聊企业对人才的需求 http www sina com cn 2004 12 02 21 03 新浪教育 图为新浪网人力资
  • RESIN FAQ

    RESIN FAQ 环境变量设置 CLASSPATH C j2sdk lib dt jar C j2sdk lib tools jar JAVA HOME C j2sdk PATH C j2sdk bin 61 61 61 61 61 61
  • 研究基于PX4平台的Ardupilot代码工程的makefile结构

    最近有空 xff0c 于是想花时间好好研究下ardupilot的软件架构 xff0c 经过对ardupilot一段时间的熟悉和使用后 xff0c 对其软件架构已经有了一定的理解 xff0c 但还称不上特别完备 xff0c 所以想把每一部分的
  • Px4固件升级流程。

    PX4飞控的固件升级可以简单的分为6步 xff0c 具体如下 xff1a 1 重启飞控 重启飞控 xff0c APP发送指令mavlink飞控重启指令 等待0 5s后进入下一步 xff1b 2 识别bootloader APP发送 0x21
  • pixhawk入门知识

    Pixhawk是一种先进的自动驾驶仪 xff0c 由PX4开放硬件项目设计和3D机器人制造 它具有来自ST公司先进的处理器和传感器技术 xff0c 以及NuttX实时操作系统 xff0c 能够实现惊人的性能 xff0c 灵活性和可靠性控制任
  • MDK 注册机下载路径

    MDK下载路径 https editor csdn net md articleId 61 115338061
  • MathJax 3.0 配置方法,上手配置

    说明 网上很多MathJax 的配置方法适用于旧版本 新版的MathJax做了一些改进 配置方式也做了调整 最简单的方案 方便起见 最简单的方案如下 span class token tag span class token tag spa
  • VsCode+LaTexWorkshop外置PDF预览配置(2021.3.3)

    随着插件版本的升级有些配置命令发生了改变 xff0c 这里只是做个简单记录 xff0c 写的比较粗糙 后面有闲工夫再来做做美工 VsCode一侧配置 34 latex workshop view pdf viewer 34 34 exter
  • MATLAB批量为png透明(抠图)图片替换添加背景

    MATLAB批量为png透明 抠图 图片替换添加背景 说明 最近有个小需求 需要抠图后将抠图的背景替换为指定图片 如果一张一张做 图片多了实在是不好用 前提 准备好背景图片 一张准备好目标图片 很多张可以利用powertoys将目标图片统一
  • PilotPi:树莓派运行PX4配置方法

    直接看最后 即可 前言 PX4开源飞控固件支持很多款硬件 包括pixhawk cuav 和 cube等 在1 12版本中px4官方开始实验性的支持树莓派直接运行 这样我们就可以在树莓派上直接运行飞控程序 考虑到树莓派处理器的性能 那么就算可

随机推荐