STM32CubeIDE 串口DMA 代码分析

串口初始化

static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;                        //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;      //过采样设置,8倍或者16倍
  if (HAL_UART_Init(&huart1) != HAL_OK)              //
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */


  /* USER CODE END USART1_Init 2 */

}
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 的定义
    #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) 
    表示参数expr为false,则执行后面的assert_failed()函数,__FILE__, __LINE__是标准库函数中的宏定义,表示文件名和行号;
    如果参数exp为TRUE,则执行((void)0),什么都不做
  */
    assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance));   
   /*
   如果IS_UART_HWFLOW_INSTANCE(huart->Instance)是true,则什么都不做,
   表示IS_UART_HWFLOW_INSTANCE(huart->Instance)为false,则执行后面的assert_failed()函数,  
  */
    assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl));
  }
  else
  {
    assert_param(IS_UART_INSTANCE(huart->Instance));
  }
  /*
  如果有硬件控制,则检查 HARDWARE_FLOW_CONTROL  和 IS_UART_HWFLOW_INSTANCE
 #define IS_UART_HWFLOW_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \
                                           ((INSTANCE) == USART2) || \
                                           ((INSTANCE) == USART3))
  无则检查IS_UART_INSTANCE
  #define IS_UART_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \
                                    ((INSTANCE) == USART2) || \
                                    ((INSTANCE) == USART3) || \
                                    ((INSTANCE) == UART4)  || \
                                    ((INSTANCE) == UART5))  
  */
  assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));        //检查数据位
  /*
  #define IS_UART_WORD_LENGTH(LENGTH) (((LENGTH) == UART_WORDLENGTH_8B) || \
                                     ((LENGTH) == UART_WORDLENGTH_9B))
 */
  
#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,初始化GPIO和时钟
    HAL_UART_MspInit(huart);
#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.*/
     /*
     在异步模式下,必须清除以下位::
    CR2 寄存器中的  LINEN 和 CLKEN 位

    LINEN: LIN模式使能 (LIN mode enable)
                   该位由软件设置或清除。
                 0:禁止LIN模式;
                1:使能LIN模式。
                在LIN模式下,可以用USART_CR1寄存器中的SBK位发送LIN同步断开符(低13位),以及检测LIN同步断开符。

  CLKEN:时钟使能 (Clock enable)
                   该位用来使能CK引脚
                   0:禁止CK引脚;
                   1:使能CK引脚。
  
    CR3 寄存器中SCEN, HDSEL 和 IREN  位
    
    SCEN: 智能卡模式使能 (Smartcard mode enable)
		该位用来使能智能卡模式
		0:禁止智能卡模式;
		1:使能智能卡模式。
		注: UART4和UART5上不存在这一位

	HDSEL:半双工选择 (Half-duplex selection)
	选择单线半双工模式
	0:不选择半双工模式;
	1:选择半双工模式。

	IREN:红外模式使能 (IrDA mode enable)
	该位由软件设置或清除。
	0:不使能红外模式;
	1:使能红外模式。
    
     */
  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;
 /*   gState:全局处理状态,也包括发送状态
 !<
  UART state information related to global Handle management
   and also related to Tx operations.
  This parameter can be a value of @ref HAL_UART_StateTypeDef 
  */
  return HAL_OK;
}

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(huart->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();      //使能USART1时钟
/*  
#define __HAL_RCC_USART1_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN);\
                                        /* Delay after an RCC peripheral clock enabling */\
                                        tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN);\
                                        UNUSED(tmpreg); \
                                      } while(0U)
#define RCC_APB2ENR_USART1EN          0x1UL <<(14U)          第14位置1

*/
    __HAL_RCC_GPIOA_CLK_ENABLE();        //使能GPIOA时钟
/*
#define __HAL_RCC_GPIOA_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);\
                                        /* Delay after an RCC peripheral clock enabling */\
                                        tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);\
                                        UNUSED(tmpreg); \
                                      } while(0U)
#define RCC_APB2ENR_IOPAEN    0x1UL <<(2U)          第2位置1
*/
   
    /**USART1 GPIO Configuration    
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    /*将GPIOA9 推挽模式  ,速度高 50MHz , */

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        /*将GPIOA10  浮空输入模式  */

    /* USART1 DMA Init */
    /* USART1_RX Init */
    hdma_usart1_rx.Instance = DMA1_Channel5;  //串口1接收绑定到DMA1_Channel5;
    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;   // 数据BYTE
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;    //数据BYTE
    hdma_usart1_rx.Init.Mode = DMA_NORMAL;                                            //DMA工作模式:普通非循环
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;                             //优先级低
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    { 
      Error_Handler();
    }
/*

*/

    __HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx);
/*#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__)               \
                        do{                                                      \
                              (__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \
                              (__DMA_HANDLE__).Parent = (__HANDLE__);             \
                          } while(0U)

        实际好像没做特别的操作啊?
 */
    /* USART1_TX Init */
    hdma_usart1_tx.Instance = DMA1_Channel4;
    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;
    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(huart,hdmatx,hdma_usart1_tx);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 1, 1);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }

}
static void UART_SetConfig(UART_HandleTypeDef *huart)
{
  uint32_t tmpreg;
  uint32_t pclk;

  /* Check the parameters */
  assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate));   //检查波特率
  assert_param(IS_UART_STOPBITS(huart->Init.StopBits));      //检查停止位
  assert_param(IS_UART_PARITY(huart->Init.Parity));              //检查校验位
  assert_param(IS_UART_MODE(huart->Init.Mode));               //检查工作模式,工作模式在前面已设置为UART_MODE_TX_RX;

  /*-------------------------- USART CR2 Configuration -----------------------*/
  /* Configure the UART Stop Bits: Set STOP[13:12] bits
     according to huart->Init.StopBits value */
  MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits);
  /*修改寄存器CR2中的停止位
  0x3UL <<12U    就是13 12位
 #define UART_STOPBITS_1                     0x00000000U
 将13位、12位置零,就是1个停止位

 位13:12 STOP:停止位 (STOP bits)
 这2位用来设置停止位的位数
      00: 1个停止位;
      01: 0.5个停止位;
     10: 2个停止位;
      11: 1.5个停止位;
  注: UART4和UART5不能用0.5停止位和1.5停止位
*/

  /*-------------------------- USART CR1 Configuration -----------------------*/
  /* Configure the UART Word Length, Parity and mode:
     Set the M bits according to huart->Init.WordLength value
     Set PCE and PS bits according to huart->Init.Parity value
     Set TE and RE bits according to huart->Init.Mode value
     Set OVER8 bit according to huart->Init.OverSampling value */

#if defined(USART_CR1_OVER8)
  tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling;
  MODIFY_REG(huart->Instance->CR1,
             (uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8),
             tmpreg);
#else
  tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode;
  MODIFY_REG(huart->Instance->CR1,
             (uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE),
             tmpreg);
/*计算并修改CR1寄存器值*/
#endif /* USART_CR1_OVER8 */

  /*-------------------------- USART CR3 Configuration -----------------------*/
  /* Configure the UART HFC: Set CTSE and RTSE bits according to huart->Init.HwFlowCtl value */
  MODIFY_REG(huart->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE), huart->Init.HwFlowCtl);
/*修改硬件控制位
RTSE: RTS使能 (RTS enable)
0:禁止RTS硬件流控制;
1: RTS中断使能,只有接收缓冲区内有空余的空间时才请求下一个数据。当前数据发送完成
后,发送操作就需要暂停下来。如果可以接收数据了,将nRTS输出置为有效(拉至低电平)。
注: UART4和UART5上不存在这一位。

CTSE: CTS使能 (CTS enable)
0:禁止CTS硬件流控制;
1: CTS模式使能,只有nCTS输入信号有效(拉成低电平)时才能发送数据。如果在数据传输的
过程中, nCTS信号变成无效,那么发完这个数据后,传输就停止下来。如果当nCTS为无效
时,往数据寄存器里写数据,则要等到nCTS有效时才会发送这个数据。
注: UART4和UART5上不存在这一位


nCTS 是芯片上的一个引脚?
*/


#if defined(USART_CR1_OVER8)
  /* Check the Over Sampling */
  if(huart->Init.OverSampling == UART_OVERSAMPLING_8)
  {
    /*-------------------------- USART BRR Configuration ---------------------*/
    if(huart->Instance == USART1)
    {
      pclk = HAL_RCC_GetPCLK2Freq();
      huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate);
    }
    else
    {
      pclk = HAL_RCC_GetPCLK1Freq(); 
      huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate);
    }
  }
  else
  {
    /*-------------------------- USART BRR Configuration ---------------------*/
    if(huart->Instance == USART1)
    {
      pclk = HAL_RCC_GetPCLK2Freq();
      huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
     
    }
    else
    {
      pclk = HAL_RCC_GetPCLK1Freq();
      huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
    }
  }
#else
  /*-------------------------- USART BRR Configuration ---------------------*/
  if(huart->Instance == USART1)
  {
    pclk = HAL_RCC_GetPCLK2Freq();
    huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
     //设置波特率,USART1的时钟来源于PCLK2
  }
  else
  {
    pclk = HAL_RCC_GetPCLK1Freq();
    huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
  }
#endif /* USART_CR1_OVER8 */
}

DMA 初始化:

static void MX_DMA_Init(void) 
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();
/*
#define __HAL_RCC_DMA1_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                       */ /*置1 RCC  AHB外设时钟使能寄存器 (RCC_AHBENR) 中的DMA1EN位,使能DMA1时钟*/
                                        SET_BIT(RCC->AHBENR, RCC_AHBENR_DMA1EN);\               
                                        /* Delay after an RCC peripheral clock enabling */\
                                        tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_DMA1EN);\
                                        /*读取RCC_AHBENR_DMA1EN 位
                                        UNUSED(tmpreg); \
                                        /*unused 属性用于函数和变量,表示该函数或变量可能不使用。*/
                                      } while(0U)
*/

  /* DMA interrupt init */
  /*设置DMA1通道4和5的中断优先级,并使能中断
  /* DMA1_Channel4_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
  /* DMA1_Channel5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);

}

初始化DMA代码:该函数被HAL_UART_MspInit调用

HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)   
{
  uint32_t tmp = 0U;

  /* Check the DMA handle allocation */
  if(hdma == NULL)
  {
    return HAL_ERROR;
  }

  /* Check the parameters */
  /*检查参数*/
/*
    hdma_usart1_rx.Instance = DMA1_Channel5;
    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;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
    */
  assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));                               //DMA1_Channel5
  assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));                              //DMA_PERIPH_TO_MEMORY
  assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));   //DMA_PINC_DISABLE
  assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));            //DMA_MINC_ENABLE
  assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));//DMA_PDATAALIGN_BYTE
  assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));//DMA_MDATAALIGN_BYTE
  assert_param(IS_DMA_MODE(hdma->Init.Mode));                               //DMA_NORMAL
  assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));                  //DMA_PRIORITY_LOW

#if defined (DMA2)
  /* calculation of the channel index */
  /*有DMA2*/
  if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
  {
    /* DMA1 */
    hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
   计算得到 :hdma->ChannelIndex=0x00000010
    hdma->DmaBaseAddress = DMA1;     //DMA1=  0x40020000UL
  //
  }
  else 
  {
    /* DMA2 */
    hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2;
    hdma->DmaBaseAddress = DMA2;
  }
#else
  /* DMA1 */
  hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
  hdma->DmaBaseAddress = DMA1;
/*
没有定义DMA2
*/
#endif /* DMA2 */

  /* Change DMA peripheral state */
  hdma->State = HAL_DMA_STATE_BUSY;          //将hdma状态设置为忙

  /* Get the CR register value */
  tmp = hdma->Instance->CCR;              //读取CCR寄存器值

  /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */
 /*把          DMA_CCR_PL    | DMA_CCR_MSIZE  | DMA_CCR_PSIZE  | \
                      DMA_CCR_MINC  | DMA_CCR_PINC   | DMA_CCR_CIRC   | \
                      DMA_CCR_DIR  取反,然后再与运算,将这些位全部置0了    */
  tmp &= ((uint32_t)~(DMA_CCR_PL    | DMA_CCR_MSIZE  | DMA_CCR_PSIZE  | \
                      DMA_CCR_MINC  | DMA_CCR_PINC   | DMA_CCR_CIRC   | \
                      DMA_CCR_DIR));

  /* Prepare the DMA Channel configuration */
  tmp |=  hdma->Init.Direction        |
          hdma->Init.PeriphInc           | hdma->Init.MemInc           |
          hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
          hdma->Init.Mode                | hdma->Init.Priority;


  /* Write to DMA Channel CR register */
  hdma->Instance->CCR = tmp;
/*
将CCR寄存器:
位14     MEM2MEM:     清0
位6       PINC(外设地址增量模式 (Peripheral increment mode) )              清0
位7       MINC:存储器地址增量模式 (Memory increment mode)                 置1
位9:8             PSIZE[1:0]:外设数据宽度 (Peripheral size)                          清为00: 8位
位11:10         MSIZE[1:0]:存储器数据宽度 (Memory size)                         清为00: 8位 
位5                CIRC:循环模式 (Circular mode)                                           清0:不执行循环操作
位13:12          PL[1:0]:通道优先级 (Channel priority level)                        清为00: 低
 */
  /* Initialise the error code */
  hdma->ErrorCode = HAL_DMA_ERROR_NONE;                   //无错误   

  /* Initialize the DMA state*/
  hdma->State = HAL_DMA_STATE_READY;                          //准备好
  /* Allocate lock resource and initialize it */
  hdma->Lock = HAL_UNLOCKED;                                        //解锁状态

  return HAL_OK;
}

从以上代码可以看出,串口没有开启任何的中断;

串口中断服务函数:

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 */
}
/**
  * @brief  This function handles UART interrupt request.
  * @param  huart  Pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval None
  */
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)
  {
    /* 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中断。
        
        //如果没有设置RXNEIE 中断,就不会运行下面的代码
      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)))
  {
    /* 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 --------------------------------------*/
            /*发生过载错误 (Overrun error)
           如果没使能错误中断,不会运行下面的代码
          */
          
    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 -----------------------------------------------*/
      /*
                //RXNE:读数据寄存器非空 ,0:数据没有收到;1:收到数据,可以读出。  
         //RXNEIE:接收缓冲区非空中断使能 (RXNE interrupt enable)   该位由软件设置或清除。
        //0:禁止产生中断;
        //1:当USART_SR中的ORE或者RXNE为’1’时,产生USART中断。
        
        //如果没有设置RXNEIE 中断,就不会运行下面的代码
        */
      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 */
/*  
   如果OVERRUN 错误发生了 或者 在DMA接收模式下发生了任何错误
	将错误视为阻塞
*/         
      dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);  
      //如果运行了HAL_UART_Receive_DMA,那么dmarequest =TRUE
      //我运行了HAL_UART_Receive_DMA
      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);    
/*
static void UART_EndRxTransfer(UART_HandleTypeDef *huart)
{
  /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
  /*清除RXNEIE(OVERRUN中断)、PEIE(奇偶中断)、EIE(错误中断)这些中断 */
  CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
  CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);

  /* At end of Rx process, restore huart->RxState to Ready */
  /*接收状态为准备好*/
  huart->RxState = HAL_UART_STATE_READY;
}
*/
        /* 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); //清除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;  //将收到和发送的数据都清为0
            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;
  }
}

你可能感兴趣的:(stm32)