/**
  ******************************************************************************
  * @file    lcm32f06x_usart.c 
  * @author  System R&D Team
  * @version V2.0.2
  * @date    10-April-2025
  * @brief   There are two USART in lcm32f06x USART0 and USART1 .
  ******************************************************************************
  * @attention
  *
  * Copyright (c) Hangzhou Lingxin Microelectronics Co.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "lcm32f06x_usart.h"

/* Private define ------------------------------------------------------------*/

/**
  * @name   USART_DeInit
  * @brief  EN: Deinitializes the USARTx peripheral registers to their default reset values.
  *         CN: 将 USARTx 外设寄存器初始化为其默认重置值。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @retval None
  */
void USART_DeInit(USART_TypeDef *USARTx)
{

  if (USARTx == USART0)
  {
    RCC_APB0PeriphResetCmd(RCC_APB0Periph_USART0, ENABLE);
    RCC_APB0PeriphResetCmd(RCC_APB0Periph_USART0, DISABLE);
  }
  else if (USARTx == USART1)
  {
    RCC_APB0PeriphResetCmd(RCC_APB0Periph_USART1, ENABLE);
    RCC_APB0PeriphResetCmd(RCC_APB0Periph_USART1, DISABLE);
  }
}

/**
  * @name   USART_BaudRateConfig
  * @brief  EN: Serial Port Baud Rate Configuration.
  *         CN: 串口波特率配置。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设
  * @param  Baud:
  *         EN: USART communication baud rate.
  *         CN: USART 通信波特率
  * @retval None
  */
void USART_BaudRateConfig(USART_TypeDef *USARTx, uint32_t Baud)
{
  uint32_t freq;
  RCC_ClocksTypeDef RCC_Clocks;

  uint32_t baud16;
  uint16_t div_int;
  uint32_t div_frac;

  RCC_GetClockFreq(&RCC_Clocks);
  if (USARTx == USART0)
  {
    freq = RCC_Clocks.USART0_Frequency;
  }
  else if (USARTx == USART1)
  {
    freq = RCC_Clocks.USART1_Frequency;
  }
  baud16 = Baud * 16;
  div_int = freq / baud16;
  div_frac = freq - baud16 * div_int;
  div_frac = (div_frac * 64 + baud16 / 2) / baud16;
  USARTx->IBRD = div_int;
  USARTx->FBRD = div_frac;
}

/**
  * @name   USART_Init
  * @brief  EN: Initializes the USARTx peripheral according to the specified.
  *             parameters in the USART_InitStruct.
  *         CN: 根据 USART_InitStruct 中指定的参数初始化 USARTx 外设。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  USART_InitStruct:
  *         EN: pointer to a USART_InitTypeDef structure that contains the 
  *             configuration information for the specified USART peripheral.
  *         CN: 指向 USART_InitTypeDef 结构的指针，该结构包含指定 USART 外设的配置信息。
  * @retval None
  */
void USART_Init(USART_TypeDef *USARTx, USART_InitTypeDef *USART_InitStruct)
{
  uint32_t tmpreg = 0;

  /* Check the parameters */
  assert_param(IS_USART_BAUDRATE(USART_InitStruct->USART_BaudRate));  
  assert_param(IS_USART_WORD_LENGTH(USART_InitStruct->USART_WordLength));
  assert_param(IS_USART_STOPBITS(USART_InitStruct->USART_StopBits));
  assert_param(IS_USART_PARITY(USART_InitStruct->USART_Parity));
  assert_param(IS_USART_MODE(USART_InitStruct->USART_Mode));
  assert_param(IS_USART_HARDWARE_FLOW_CONTROL(USART_InitStruct->USART_HardwareFlowControl));
  
  /* Disable USART */
  USARTx->CR &= (uint32_t)(~USART_CR_USARTEN_Msk);

  USART_BaudRateConfig(USARTx, (USART_InitStruct->USART_BaudRate));

  /* Configure the USART Word Length, Parity and Stop_Bits */
  tmpreg |= ((USART_InitStruct->USART_WordLength) | 
             (USART_InitStruct->USART_StopBits)   | 
             (USART_InitStruct->USART_Parity));
  USARTx->LCR = tmpreg;

  /* Configure the USART USART_HardwareFlowControl and Mode */
  tmpreg = USARTx->CR;
  tmpreg &= 0xffff07ff;
  tmpreg |= USART_InitStruct->USART_HardwareFlowControl;
  USARTx->CR = tmpreg;

  tmpreg = USART_InitStruct->USART_Mode;
  if (tmpreg == (USART_Mode_Rx | USART_Mode_Tx))
  {
    USARTx->CR |= USART_Mode_Rx;
    USARTx->CR |= USART_Mode_Tx;
  }
  else if (tmpreg == USART_Mode_Tx)
  {
    USARTx->CR |= USART_Mode_Tx;
    USARTx->CR &= ~USART_Mode_Rx;
  }
  else
  {
    USARTx->CR |= USART_Mode_Rx;
    USARTx->CR &= ~USART_Mode_Tx;
  }
}

/**
  * @name   USART_StructInit
  * @brief  EN: Fills each USART_InitStruct member with its default value.
  *         CN: 用默认值填充每个 USART_InitStruct 成员。
  * @param  USART_InitStruct:
  *         EN: pointer to a USART_InitTypeDef structure that contains the 
  *             configuration information for the specified USART peripheral.
  *         CN: 指向 USART_InitTypeDef 结构的指针，该结构包含指定 USART 外设的配置信息。
  * @retval None
  */
void USART_StructInit(USART_InitTypeDef *USART_InitStruct)
{
  /* USART_InitStruct members default value */
  USART_InitStruct->USART_BaudRate = 115200;

  USART_InitStruct->USART_WordLength = USART_WordLength_8b;

  USART_InitStruct->USART_StopBits = USART_StopBits_1;

  USART_InitStruct->USART_Parity = USART_Parity_No;

  USART_InitStruct->USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  
  USART_InitStruct->USART_HardwareFlowControl = USART_HardwareFlowControl_None;
}

/**
  * @name   USART_Cmd
  * @brief  EN: Enables or disables the specified USARTx peripheral.
  *         CN: 启用或禁用指定的 USARTx 外设。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void USART_Cmd(USART_TypeDef *USARTx, FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    USARTx->CR |= USART_CR_USARTEN_Msk;
  }
  else
  {
    USARTx->CR &= ~USART_CR_USARTEN_Msk;
  }
}

/**
  * @name   USART_DirectionModeCmd
  * @brief  EN: Enables or disables the specified USARTx peripheral.
  *         CN: 启用或禁用 USARTx 的发送或接收。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  USART_DirectionMode: 
  *         EN: Specify the USART direction that needs to be closed.
  *         CN: 指定需要关闭的 USART 方向。
  *             @arg USART_Direction_Tx
  *             @arg USART_Direction_Rx
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void USART_DirectionModeCmd(USART_TypeDef *USARTx, uint32_t USART_DirectionMode, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_USART_DIRECTION(USART_DirectionMode));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != ENABLE)
  {
    USARTx->CR &= ~USART_DirectionMode;
  }
  else
  {
    USARTx->CR |= USART_DirectionMode;
  }
}

/**
  * @name   USART_SendData
  * @brief  EN: Transmits single data through the USARTx peripheral.
  *         CN: 通过 USARTx 外设传输单个数据。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  Data: 
  *         EN: One byte of data to be sent.
  *         CN: 要发送的一字节数据。
  * @retval None
  */
void USART_SendData(USART_TypeDef *USARTx, uint8_t Data)
{
  
  USARTx->DR = Data;
}

/**
  * @name   USART_ReceiveData
  * @brief  EN: Returns the most recent received data by the USARTx peripheral.
  *         CN: 返回 USARTx 外设最近接收到的数据。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @retval EN: The received data.
  *         CN: 接收到的数据。
  */
uint16_t USART_ReceiveData(USART_TypeDef *USARTx)
{
  uint32_t tmpreg = 0;
  tmpreg = USARTx->DR;
  return (uint16_t)(tmpreg & 0xff);
}

/**
  * @name   USART_SendBreak
  * @brief  EN: Break the transmission of USARTx peripheral.
  *         CN: 打断 USARTx 外设的发送。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @retval None
  */
void USART_SendBreak(USART_TypeDef *USARTx)
{
  /* set and cleared by software */
  USARTx->LCR |= USART_LCR_BRK_Msk;
}

/**
  * @name   USART_HalfDuplesCmd
  * @brief  EN: Enable or disable USARTx peripheral single line half duplex mode.
  *         CN: 启用或禁用 USARTx 外设单线半双工模式。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  OutputMode_Sel: 
  *         EN: Half duplex mode output mode selection.
  *         CN: 半双工模式输出模式选择。
  *             @arg ENABLE
  *             @arg DISABLE
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  * @note   LIN mode half duplex mode and USART synchronization mode can only be activated once.
  */
void USART_HalfDuplesCmd(USART_TypeDef *USARTx,uint32_t OutputMode_Sel, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  USARTx->CR2 &=(~(USART_CR2_HDOD_Msk | USART_CR2_HDSEL_Msk));

  if (NewState != ENABLE)
  {
    USARTx->CR2 &= ~(USART_CR2_HDSEL_Msk);
  }
  else
  {
    USARTx->CR2 |= (OutputMode_Sel | USART_CR2_HDSEL_Msk);
  }
}

/**
  * @name   USART_SynchronousModeCmd
  * @brief  EN: Enable or disable USARTx Synchronous mode and CK pin.
  *         CN: 启用或禁用 USARTx 同步模式和CK引脚。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  CPHA_Mode_Sel: 
  *         EN: Select synchronous clock phase.
  *         CN: 选择同步时钟相位。
  * @param  CPOL_Mode_Sel: 
  *         EN: Select synchronization clock polarity.
  *         CN: 选择同步时钟极性。
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral Synchronous mode.
  *         CN: USARTx 外设同步模式的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void USART_SynchronousModeCmd(USART_TypeDef *USARTx, uint32_t CPHA_Mode_Sel, uint32_t CPOL_Mode_Sel,FunctionalState NewState)
{
  USARTx->CR2 &=(~(USART_CR2_CPHA_Msk | USART_CR2_CPOL_Msk | USART_CR2_CLKEN_Msk));
  if (NewState != ENABLE)
  {
    USARTx->CR2 &= ~(USART_CR2_CLKEN_Msk);
  }
  else
  {
    USARTx->CR2 |= USART_CR2_CLKEN_Msk | CPHA_Mode_Sel | CPOL_Mode_Sel;
  }
}
/**
  * @name   USART_LPUSARTCmd
  * @brief  EN: Enable or disable USARTx low-power mode LPUSART.
  *         CN: 启用或禁用 USARTx 低功耗模式 LPUSART。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void USART_LPUSARTCmd(USART_TypeDef *USARTx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != ENABLE)
  {
    USARTx->CR3 &= 0X00;
  }
  else
  {
    USARTx->CR3 |= 0x01;
  }
}

/**
  * @name   USART_LowPowerWakeConfig
  * @brief  EN: Select USARTx peripheral low-power wake-up event.
  *         CN: 选择 USARTx 外设低功耗唤醒事件。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  Event: 
  *         EN: USARTx peripheral low-power wake-up event.
  *         CN: USARTx 外设低功耗唤醒事件。
  *             @arg USART_WUS_ADDRSS
  *             @arg USART_WUS_START_BIT
  * @retval None
  */
void USART_LowPowerWakeConfig(USART_TypeDef *USARTx, uint32_t Event)
{
  /* Check the parameters */
  assert_param(IS_USART_WUS(Event));

  USARTx->CR3 |= Event;
}

/**
  * @name   USART_FIFOLevelConfig
  * @brief  EN: Select USARTx to send and receive FIFO depth.
  *         CN: 选择 USARTx 发送和接收 FIFO 深度。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  RXIFLSelect: 
  *         EN: USARTx peripheral receiving FIFO selection.
  *         CN: USARTx 外设接收 FIFO 选择。
  *             @arg USART_RXIFLSEL_LEAVEL_0_16
  *             @arg USART_RXIFLSEL_LEAVEL_1_16
  *             @arg ...
  *             @arg USART_RXIFLSEL_LEAVEL_14_16
  *             @arg USART_RXIFLSEL_LEAVEL_15_16
  * @param  TXIFLSelect: 
  *         EN: USARTx peripheral sends FIFO selection.
  *         CN: USARTx 外设发送 FIFO 选择。
  *             @arg USART_TXIFLSEL_LEAVEL_0_16
  *             @arg USART_TXIFLSEL_LEAVEL_1_16
  *             @arg ...
  *             @arg USART_TXIFLSEL_LEAVEL_14_16
  *             @arg USART_TXIFLSEL_LEAVEL_15_16
  * @retval None
  */
void USART_FIFOLevelConfig(USART_TypeDef *USARTx, uint32_t RxFIFO, uint32_t TxFIFO)
{
  /* Check the parameters */
  assert_param(IS_USART_RXIFLSEL_LEAVEL(RxFIFO));
  assert_param(IS_USART_TXIFLSEL_LEAVEL(TxFIFO));

  USARTx->IFLS &= 0xFFFFFF00;
  USARTx->IFLS |= TxFIFO | RxFIFO;
}

/**
  * @name   USART_DMACmd
  * @brief  EN: Enable or disable USARtx peripheral DAM sending FIFO and receiving FIFO.
  *         CN: 启用或禁止 USARtx 外设 DAM 发送 FIFO 和接收 FIFO。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  USART_DMAReq: 
  *         EN: Select USARTx DAM request.
  *         CN: 选择 USARTx DAM 请求。
  *             @arg USART_DMAReq_Rx
  *             @arg USART_DMAReq_Tx
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void USART_DMACmd(USART_TypeDef *USARTx, uint32_t USART_DMAReq, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_USART_DMAREQ(USART_DMAReq));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (USART_DMAReq == USART_DMAReq_Rx)
  {
    (NewState != DISABLE) ? (USARTx->DMACR |= USART_DMAReq_Rx) : (USARTx->DMACR &= ~USART_DMAReq_Rx);
  }
  else
  {
    (NewState != DISABLE) ? (USARTx->DMACR |= USART_DMAReq_Tx) : (USARTx->DMACR &= ~USART_DMAReq_Tx);
  }
}

/**
  * @name   USART_ITConfig
  * @brief  EN: Configure USARTx peripheral interrupt.
  *         CN: 配置 USARTx 外设中断。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  USART_IT: 
  *         EN: Specify USARTx peripheral interrupt.
  *         CN: 指定 USARTx 外设中断。
  *             @arg USART_IT_CERIS  : Detect error interrupt bit.
  *             @arg USART_IT_WUFRIS : Wake up event bit in low-power mode.
  *             @arg USART_IT_LINE   : Receive header interrupt bit in LIN mode.
  *             @arg USART_IT_OE     : Overflow error interrupt bit.
  *             @arg USART_IT_BE     : Break error interrupt bit.
  *             @arg USART_IT_PE     : Parity error interrupt bit.
  *             @arg USART_IT_FE     : Frame error interrupt bit.
  *             @arg USART_IT_RT     : Receive stop interrupt bit.
  *             @arg USART_IT_TX     : Send interrupt bit.
  *             @arg USART_IT_RX     : Receive interrupt bit.
  *             @arg USART_IT_CTS    : Hard control flow interrupt shielding bit.
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void USART_ITConfig(USART_TypeDef *USARTx, uint32_t USART_IT, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_USART_IT(USART_IT));

  if (NewState == ENABLE)
  {
    USARTx->IMSC |= USART_IT;
  }
  else
  {
    USARTx->IMSC &= ~USART_IT;
  }
}

/**
  * @name   USART_GetFlagStatus
  * @brief  EN: Read the running status of USARTx.
  *         CN: 读取 USARTx 运行状态。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  USART_FLAG: 
  *         EN: USARTx flag.
  *         CN: USARTx 标志位。
  *             @arg USART_FLAG_RXBUSY : Receive busy
  *             @arg USART_FLAG_TXFE   : Send FIFO empty
  *             @arg USART_FLAG_RXFF   : Receive FIFO full
  *             @arg USART_FLAG_TXFF   : Send FIFO full
  *             @arg USART_FLAG_RXFE   : Receive FIFO empty
  *             @arg USART_FLAG_BUSY   : Usart busy
  *             @arg USART_FLAG_CTS    : nUSARTCTS
  * @retval EN: USARTx running status
  *         CN: USARTx 运行状态
  */
FlagStatus USART_GetFlagStatus(USART_TypeDef *USARTx, uint32_t USART_Flag)
{
  /* Check the parameters */
  assert_param(IS_USART_STATUSFLAG(USART_Flag));

  if (USARTx->FR & USART_Flag)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

/**
  * @name   USART_GetITStatus
  * @brief  EN: Read USARTx masked interrupt status.
  *         CN: 读取 USARTx 屏蔽中断状态。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  USART_IT: 
  *         EN: Specify USARTx peripheral interrupt.
  *         CN: 指定 USARTx 外设中断。
  *             @arg USART_IT_CERIS  : Detect error interrupt bit.
  *             @arg USART_IT_WUFRIS : Wake up event bit in low-power mode.
  *             @arg USART_IT_LINE   : Receive header interrupt bit in LIN mode.
  *             @arg USART_IT_OE     : Overflow error interrupt bit.
  *             @arg USART_IT_BE     : Break error interrupt bit.
  *             @arg USART_IT_PE     : Parity error interrupt bit.
  *             @arg USART_IT_FE     : Frame error interrupt bit.
  *             @arg USART_IT_RT     : Receive stop interrupt bit.
  *             @arg USART_IT_TX     : Send interrupt bit.
  *             @arg USART_IT_RX     : Receive interrupt bit.
  *             @arg USART_IT_CTS    : Hard control flow interrupt shielding bit.
  * @retval EN: USARTx masked interrupt status
  *         CN: USARTx 屏蔽中断状态
  */
ITStatus USART_GetITStatus(USART_TypeDef *USARTx, uint32_t USART_IT)
{
  /* Check the parameters */
  assert_param(IS_USART_IT(USART_IT));

  if (USARTx->MIS & USART_IT)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

/**
  * @name   USART_GetRawITStatus
  * @brief  EN: Read USARTx raw interrupt status.
  *         CN: 读取 USARTx 原始中断状态。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  USART_IT: 
  *         EN: Specify USARTx peripheral interrupt.
  *         CN: 指定 USARTx 外设中断。
  *             @arg USART_IT_CERIS  : Detect error interrupt bit.
  *             @arg USART_IT_WUFRIS : Wake up event bit in low-power mode.
  *             @arg USART_IT_LINE   : Receive header interrupt bit in LIN mode.
  *             @arg USART_IT_OE     : Overflow error interrupt bit.
  *             @arg USART_IT_BE     : Break error interrupt bit.
  *             @arg USART_IT_PE     : Parity error interrupt bit.
  *             @arg USART_IT_FE     : Frame error interrupt bit.
  *             @arg USART_IT_RT     : Receive stop interrupt bit.
  *             @arg USART_IT_TX     : Send interrupt bit.
  *             @arg USART_IT_RX     : Receive interrupt bit.
  *             @arg USART_IT_CTS    : Hard control flow interrupt shielding bit.
  * @retval EN: USARTx raw interrupt status
  *         CN: USARTx 原始中断状态
  */
ITStatus USART_GetRawITStatus(USART_TypeDef *USARTx, uint32_t USART_IT)
{
  /* Check the parameters */
  assert_param(IS_USART_IT(USART_IT));

  if (USARTx->RIS & USART_IT)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

/**
  * @name   USART_ClearITPendingBit
  * @brief  EN: CLear USARTx interrupt bit.
  *         CN: 清除 USARTx 中断位。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  USART_IT: 
  *         EN: Specify USARTx peripheral interrupt.
  *         CN: 指定 USARTx 外设中断。
  *             @arg USART_IT_CERIS  : Detect error interrupt bit.
  *             @arg USART_IT_WUFRIS : Wake up event bit in low-power mode.
  *             @arg USART_IT_LINE   : Receive header interrupt bit in LIN mode.
  *             @arg USART_IT_OE     : Overflow error interrupt bit.
  *             @arg USART_IT_BE     : Break error interrupt bit.
  *             @arg USART_IT_PE     : Parity error interrupt bit.
  *             @arg USART_IT_FE     : Frame error interrupt bit.
  *             @arg USART_IT_RT     : Receive stop interrupt bit.
  *             @arg USART_IT_TX     : Send interrupt bit.
  *             @arg USART_IT_RX     : Receive interrupt bit.
  *             @arg USART_IT_CTS    : Hard control flow interrupt shielding bit.
  * @retval None
  */
void USART_ClearITPendingBit(USART_TypeDef *USARTx, uint32_t USART_IT)
{
  /* Check the parameters */
  assert_param(IS_USART_IT(USART_IT));

  USARTx->ICR |= USART_IT;
}

/**
  * @name   USART_FIFOEnable
  * @brief  EN: Enable or disable USARTx peripheral FIFO.
  *         CN: 启用或禁止 USARTx 外设 FIFO。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void USART_FIFOEnable(USART_TypeDef *USARTx, uint32_t NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    USARTx->LCR |= 0X10;
  }
  else
  {
    USARTx->LCR &= 0XEF;
  }
}

/** 
  * @name   USART_LIN_Init
  * @brief  EN: Initialize LIN based on the parameters specified in LIN-InitStruct
  *         CN: 根据 LIN_InitStruct 中指定的参数初始化 LIN
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  LIN_InitStruct:
  *         EN: Pointer to a LIN_InitStruct structure that contains the 
  *             configuration information for the specified LIN peripheral.
  *         CN: 指向 LIN_InitStruct 结构的指针，该结构包含指定 LIN 外设的配置信息。
  * @retval None
*/
void USART_LIN_Init(USART_TypeDef *USARTx, LIN_InitTypeDef *LIN_InitStruct)
{
  /* Check the parameters */
  assert_param(IS_LIN_MODE(LIN_InitStruct->LIN_Mode));
  assert_param(IS_LIN_RESPONSE_LENGTH(LIN_InitStruct->LIN_ResponseLen));
  assert_param(IS_LIN_CHECKSELECT(LIN_InitStruct->LIN_ChecksunStore));
  assert_param(IS_LIN_BITERROR(LIN_InitStruct->LIN_BitErrorCheck));
  assert_param(IS_LIN_BREAK_LENGTH(LIN_InitStruct->LIN_BreakSyncGap));
  assert_param(IS_LIN_TRANS_LENGTH(LIN_InitStruct->LIN_TransmissionGap));
  assert_param(IS_LIN_USAGE(LIN_InitStruct->LIN_ResponseRole));
  assert_param(IS_LIN_PARITYTYPE(LIN_InitStruct->LIN_ParityType));

  uint32_t temp = 0;

  temp = USARTx->LINCON1;
  temp &= 0xFFFFFFDE;
  temp =  temp | LIN_InitStruct->LIN_Mode | LIN_InitStruct->LIN_ChecksunStore;
  USARTx->LINCON1 =  temp;

  temp = USARTx->FRAMECON;
  temp &= 0x00;
  temp =  temp |
          LIN_InitStruct->LIN_BitErrorCheck | \
          LIN_InitStruct->LIN_BreakSyncGap  | \
          LIN_InitStruct->LIN_TransmissionGap;
  USARTx->FRAMECON = temp;
                      
  temp = USARTx->DATCON;
  temp &= 0xFFC0;
  temp = temp |
         LIN_InitStruct->LIN_ParityType   | \
         LIN_InitStruct->LIN_ResponseRole | \
         LIN_InitStruct->LIN_ResponseLen;
  USARTx->DATCON = temp;

}

/**
  * @name   LIN_StructInit
  * @brief  EN: Fills each LIN_InitStruct member with its default value.
  *         CN: 用默认值填充每个 LIN_InitStruct 成员。
  * @param  LIN_InitStruct:
  *         EN: pointer to a LIN_InitTypeDef structure that contains the 
  *             configuration information for the specified LIN peripheral.
  *         CN: 指向 LIN_InitTypeDef 结构的指针，该结构包含指定 LIN 外设的配置信息。
  * @retval None
  */
void LIN_StructInit(LIN_InitTypeDef *LIN_InitStruct)
{
  /* Check the parameters */
  assert_param(IS_LIN_MODE(LIN_InitStruct->LIN_Mode));
  assert_param(IS_LIN_RESPONSE_LENGTH(LIN_InitStruct->LIN_ResponseLen));
  assert_param(IS_LIN_CHECKSELECT(LIN_InitStruct->LIN_ChecksunStore));
  assert_param(IS_LIN_BITERROR(LIN_InitStruct->LIN_BitErrorCheck));
  assert_param(IS_LIN_BREAK_LENGTH(LIN_InitStruct->LIN_BreakSyncGap));
  assert_param(IS_LIN_TRANS_LENGTH(LIN_InitStruct->LIN_TransmissionGap));
  assert_param(IS_LIN_USAGE(LIN_InitStruct->LIN_ResponseRole));
  assert_param(IS_LIN_PARITYTYPE(LIN_InitStruct->LIN_ParityType));

  /* LIN_InitStruct members default value */
  LIN_InitStruct->LIN_Mode = LIN_Mode_Master;
  LIN_InitStruct->LIN_ResponseLen = LIN_ResponseLength_1b;
  LIN_InitStruct->LIN_ChecksunStore = LIN_None_Write_RXFIFO;
  LIN_InitStruct->LIN_BitErrorCheck = LIN_BitErrorCheck_Disable;
  LIN_InitStruct->LIN_BreakSyncGap = LIN_BreakSyncGap_1b;
  LIN_InitStruct->LIN_TransmissionGap = LIN_TransmissionGap_0b;
  LIN_InitStruct->LIN_ResponseRole = LIN_Freme_Timeout;
  LIN_InitStruct->LIN_ParityType = LIN_Classic_Checck;
}

/**
  * @name   USART_LINCmd
  * @brief  EN: Enable or disable USARTx peripheral LIN receiving header detection.
  *         CN: 启用或禁止 USARTx 外设 LIN 接收报头检测。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  Type:
  *         EN: Choose software or hardware to implement LIN
  *         CN: 选择软件或硬件实现 LIN 
  *             @arg LIN_Hardware
  *             @arg LIN_Software
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  * @note   Only for slave mode the host does not have hardware logic.
  */
void USART_LINCmd(USART_TypeDef *USARTx, uint8_t Type, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_USART_LIN_FUNCTION_TYPE(Type));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    USARTx->CR_b.LINEN |= 1;
    if(Type == LIN_Software)
    {
      USARTx->LINCON1_b.SCM |= 1;
    }
    else
    {
      USARTx->LINCON1_b.SCM &= 0;
    }
  }
  else
  {
    USARTx->CR_b.LINEN &= 0;
  }
}

/**
  * @name   BandrateClockMeasure
  * @brief  EN: Configure baud rate detection upper and lower limits.
  *         CN: 配置波特率侦测上下限。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  UpperLimitClock: 
  *         EN: Upper limit of baud rate measurement clock count.
  *         CN: 波特率测量时钟数上限。
  * @param  LowerLimitClock: 
  *         EN: Lower limit of baud rate measurement clock count.
  *         CN: 波特率测量时钟数下限。
  * @retval None
  */
void BandrateClockMeasure(USART_TypeDef *USARTx, uint32_t UpperLimitClock, uint32_t LowerLimitClock)
{
  USARTx->BRDUPPER_b.UPPERLIMIT = UpperLimitClock;

  USARTx->BRDLOWER_b.LOWERLIMIT = LowerLimitClock;
}

/**
  * @name   LIN_CurrentStatus
  * @brief  EN: Configure the current working status of the LIN network.
  *         CN: 配置 LIN 网络当前的工作状态。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  LIN_CurrentStatus: 
  *         EN: Specify the current working status of LIN.
  *         CN: 指定 LIN 当前的工作状态。
  *             @arg LIN_CURRENT_Work_ACTIVE
  *             @arg LIN_CURRENT_Work_SLEEP
  * @retval None
  */
void LIN_CurrentStatus(USART_TypeDef *USARTx, uint32_t LIN_CurrentStatus)
{
  /* Check the parameters */
  assert_param(IS_USART_LIN_CURRENT_STATUS(LIN_CurrentStatus));
  
  if (LIN_CurrentStatus == LIN_CURRENT_Work_SLEEP)
  {
    USARTx->LINCON1_b.LINSLP |= 1;
  }
  else
  {
    USARTx->LINCON1_b.LINSLP &= 0;
  }
}

/** 
  * @name   LIN_Bus_LongZero_Check
  * @brief  EN: Enable or disable bus long zero detection
  *         CN: 使能或禁用总线长零检测
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
*/
void LIN_Bus_LongZero_Check(USART_TypeDef *USARTx, uint32_t NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    USARTx->LINCON1_b.LZEN |= 1;
  }
  else
  {
    USARTx->LINCON1_b.LZEN &= 0;
  }
}

/** 
  * @name   LIN_Baudrate_Read
  * @brief  EN: Read the baud rate detected by the LIN slave
  *         CN: 读取 LIN 从机侦测到的波特率
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @retval uint16_t
  *         EN: LIN slave baud rate self calibration value
  *         CN: LIN 从机波特率自校准值
*/
uint16_t LIN_Baudrate_Read(USART_TypeDef *USARTx)
{
  return ((USARTx->BRDMSU) & 0xFFFF);
}

/** 
  * @name   LIN_AutoBaudrateSync
  * @brief  EN: Enable or disable automatic baud rate synchronization
  *         CN: 使能或禁止自动波特率同步
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
*/
void LIN_AutoBaudrateSync(USART_TypeDef *USARTx, uint32_t NewState)
{
  if (NewState != DISABLE)
  {
    USARTx->LINCON1_b.ABD |= 1;
  }
  else
  {
    USARTx->LINCON1_b.ABD &= 0;
  }
}

/** 
  * @name   LIN_HardwareCheckSum
  * @brief  EN: Enable or disable hardware checksum
  *         CN: 启用或禁用硬件 checksum 
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
*/
void LIN_HardwareCheckSum(USART_TypeDef *USARTx, uint32_t NewState)
{
  if (NewState != DISABLE)
  {
    USARTx->LINCON1_b.CSEN |= 1;
  }
  else
  {
    USARTx->LINCON1_b.CSEN &= 0;
  }
}

/**
  * @name   LIN_GetModeStatus
  * @brief  EN: Read the mode status of the LIN.
  *         CN: 读取 LIN 模式状态。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  LIN_ModeStatus: 
  *         EN: Specify to read LIN mode status.
  *         CN: 指定读取 LIN 模式状态。
  *             @arg LIN_MODE_IDLE
  *             @arg LIN_MODE_BREAK
  *             @arg LIN_MODE_BREAKDELIMITER
  *             @arg LIN_MODE_SYNCHFIELD
  *             @arg LIN_MODE_PARITYFIELD
  *             @arg LIN_MODE_HEADRECEPTION
  *             @arg LIN_MODE_DATARECEPTION
  *             @arg LIN_MODE_CHECKSUM
  *             @arg LIN_MODE_WAKEUPFIELD
  * @retval EN: Specify flag status
  *         CN: 指定标志位状态
  */
FlagStatus LIN_GetModeStatus(USART_TypeDef *USARTx, uint32_t LIN_ModeStatus)
{
  /* Check the parameters */
  assert_param(IS_USART_LIN_MODE_STATUS(LIN_ModeStatus));
  
  if ((USARTx->LINSTS & USART_LINSTS_STS_Msk) == LIN_ModeStatus)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

/**
  * @name   LIN_GetPinLeaveStatus
  * @brief  EN: Read the LIN receiving pin level status.
  *         CN: 读取 LIN 接收引脚电平状态。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  LIN_PinStatus: 
  *         EN: Specify to read LIN level status.
  *         CN: 指定读取 LIN 电平状态。
  *             @arg LIN_PIN_LEVEL_LOW
  *             @arg LIN_PIN_LEVEL_HIGH
  * @retval EN: Specify flag status.
  *         CN: 指定标志位状态。
  */
FlagStatus LIN_GetPinLeaveStatus(USART_TypeDef *USARTx, uint32_t LIN_PinStatus)
{
  /* Check the parameters */
  assert_param(IS_USART_LIN_LEVEL_STATUS(LIN_PinStatus));
  
  if ((USARTx->LINSTS & USART_LINSTS_PS_Msk) == LIN_PinStatus)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

/** 
  * @name   LIN_ResponseTimeoutSet
  * @brief  EN: Set frame or response timeout threshold
  *         CN: 设置帧或应答超时阈值
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  LIN_ResponseTime
  *         EN: The frame or response timeout threshold to be set
  *         CN: 要设置的帧或应答超时阈值
  * @retval None
*/
void LIN_ResponseTimeoutSet(USART_TypeDef *USARTx, uint32_t LIN_ResponseTime)
{
  if(LIN_ResponseTime != 0xFF)
  {
    USARTx->DATCON_b.RESPONSE = LIN_ResponseTime;
  }
  else
  {
    USARTx->DATCON_b.RESPONSE = 0xFF;
  }
}

/**
  * @name   LIN_SetBreakPulse
  * @brief  EN: Configure the number of break pulses generated or detected.
  *         CN: 配置生成或侦测 break 脉冲数。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  LIN_BreakTime: 
  *         EN: Specify break pulse value.
  *         CN: 指定 break 脉冲值。
  * @retval None
  * @note   The LIN slave mode defines the break pulse detection threshold in this bit field.
  *         The LIN host mode defines the duration of the break pulse in this field.
  *         LIN host mode typical value is 13
  *         LIN slave mode typical value is 11
  */
void LIN_SetBreakPulse(USART_TypeDef *USARTx, uint32_t LIN_BreakTime)
{
  if(LIN_BreakTime != 0xD)
  {
    USARTx->LINBTIMER = LIN_BreakTime;
  }
  else /* default break vlaue is 0xD */
  {
    USARTx->LINBTIMER = 0xD;
  }
}

/**
  * @name   LIN_FrameHeadTimeOut
  * @brief  EN: Set frame header timeout threshold.
  *         CN: 设置帧头超时阈值。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  TimeOut: 
  *         EN: Specify frame header timeout value.
  *         CN: 指定帧头超时值。
  * @retval None
  */
void LIN_FrameHeadTimeOut(USART_TypeDef *USARTx, uint32_t TimeOut)
{
  if(TimeOut != 0xFF)
  {
    USARTx->LINHTIMER = TimeOut;
  }
  else /* default break vlaue is 0xFF */
  {
    USARTx->LINHTIMER = 0xFF;
  }
}

/**
  * @name   LIN_ITConfig
  * @brief  EN: Configure USARTx peripheral LIN mode interrupt.
  *         CN: 配置 USARTx 外设 LIN 模式中断。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  LIN_IT: 
  *         EN: Specify USARTx peripheral LIN mode interrupt.
  *         CN: 指定 USARTx 外设 LIN 模式中断。
  *             @arg LIN_IT_SFI  : LIN synchronization segment error interrupt bit
  *             @arg LIN_IT_LZI  : LIN Long zero interrupt bit
  *             @arg LIN_IT_REDI : LINRX rising edge detection interrupt status bit
  *             @arg LIN_IT_FEDI : LINRX falling edge detection interrupt status bit
  *             @arg LIN_IT_LPI  : LIN identifier parity interrupt bit
  *             @arg LIN_IT_LCI  : LIN checksum error interrupt bit
  *             @arg LIN_IT_LAI  : LIN automatic baud rate detection error interrupt bit
  *             @arg LIN_IT_RTI  : LIN response timeout interrupt bit
  *             @arg LIN_IT_HTI  : LIN frame header timeout interrupt bit
  *             @arg LIN_IT_TRI  : LIN response sending interrupt bit
  *             @arg LIN_IT_THI  : LIN frame sending interrupt blocking bit
  *             @arg LIN_IT_RRI  : LIN response receive interrupt bit
  *             @arg LIN_IT_RHI  : LIN frame header receive interrupt bit
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: USARTx 外设的新状态
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void LIN_ITConfig(USART_TypeDef *USARTx, uint32_t LIN_IT, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_LIN_IT(LIN_IT));

  if (NewState == ENABLE)
  {
    USARTx->USARTIMSC1 |= LIN_IT;
  }
  else
  {
    USARTx->USARTIMSC1 &= ~LIN_IT;
  }
}

/**
  * @name   LIN_GetRawITStatus
  * @brief  EN: Read USARTx LIN mode raw interrupt status.
  *         CN: 读取 USARTx LIN 模式原始中断状态。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  LIN_IT: 
  *         EN: Specify USARTx peripheral LIN mode interrupt.
  *         CN: 指定 USARTx 外设 LIN 模式中断。
  *             @arg LIN_IT_SFI  : LIN synchronization segment error interrupt bit
  *             @arg LIN_IT_LZI  : LIN Long zero interrupt bit
  *             @arg LIN_IT_REDI : LINRX rising edge detection interrupt status bit
  *             @arg LIN_IT_FEDI : LINRX falling edge detection interrupt status bit
  *             @arg LIN_IT_LPI  : LIN identifier parity interrupt bit
  *             @arg LIN_IT_LCI  : LIN checksum error interrupt bit
  *             @arg LIN_IT_LAI  : LIN automatic baud rate detection error interrupt bit
  *             @arg LIN_IT_RTI  : LIN response timeout interrupt bit
  *             @arg LIN_IT_HTI  : LIN frame header timeout interrupt bit
  *             @arg LIN_IT_TRI  : LIN response sending interrupt bit
  *             @arg LIN_IT_THI  : LIN frame sending interrupt blocking bit
  *             @arg LIN_IT_RRI  : LIN response receive interrupt bit
  *             @arg LIN_IT_RHI  : LIN frame header receive interrupt bit
  * @retval EN: USARTx LIN mode raw interrupt status
  *         CN: USARTx LIN 模式原始中断状态
  */
ITStatus LIN_GetRawITStatus(USART_TypeDef *USARTx, uint32_t LIN_IT)
{
  /* Check the parameters */
  assert_param(IS_LIN_IT(LIN_IT));

  if (USARTx->USARTRIS1 & LIN_IT)
  {
    return SET;
  }
  else 
  {
    return RESET;
  }
}

/**
  * @name   LIN_GetITStatus 
  * @brief  EN: Read USARTx LIN mode masked interrupt status.
  *         CN: 读取 USARTx LIN 模式屏蔽中断状态。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  USART_IT: 
  *         EN: Specify USARTx peripheral interrupt.
  *         CN: 指定 USARTx 外设中断。
  *             @arg LIN_IT_SFI  : LIN synchronization segment error interrupt bit
  *             @arg LIN_IT_LZI  : LIN Long zero interrupt bit
  *             @arg LIN_IT_REDI : LINRX rising edge detection interrupt status bit
  *             @arg LIN_IT_FEDI : LINRX falling edge detection interrupt status bit
  *             @arg LIN_IT_LPI  : LIN identifier parity interrupt bit
  *             @arg LIN_IT_LCI  : LIN checksum error interrupt bit
  *             @arg LIN_IT_LAI  : LIN automatic baud rate detection error interrupt bit
  *             @arg LIN_IT_RTI  : LIN response timeout interrupt bit
  *             @arg LIN_IT_HTI  : LIN frame header timeout interrupt bit
  *             @arg LIN_IT_TRI  : LIN response sending interrupt bit
  *             @arg LIN_IT_THI  : LIN frame sending interrupt blocking bit
  *             @arg LIN_IT_RRI  : LIN response receive interrupt bit
  *             @arg LIN_IT_RHI  : LIN frame header receive interrupt bit
  * @retval EN: USARTx LIN mode masked interrupt status
  *         CN: USARTx LIN 模式屏蔽中断状态
  */
ITStatus LIN_GetITStatus(USART_TypeDef *USARTx, uint32_t LIN_IT)
{
  /* Check the parameters */
  assert_param(IS_LIN_IT(LIN_IT));

  if (USARTx->USARTMIS1 & LIN_IT)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

/**
  * @name   LIN_ClearITPendingBit
  * @brief  EN: CLear USARTx LIN mode interrupt bit.
  *         CN: 清除 USARTx LIN 模式中断位。
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  LIN_IT: 
  *         EN: Specify USARTx peripheral iLINnterrupt.
  *         CN: 指定 USARTx LIN 模式外设中断。
  *             @arg LIN_IT_SFI  : LIN synchronization segment error interrupt bit
  *             @arg LIN_IT_LZI  : LIN Long zero interrupt bit
  *             @arg LIN_IT_REDI : LINRX rising edge detection interrupt status bit
  *             @arg LIN_IT_FEDI : LINRX falling edge detection interrupt status bit
  *             @arg LIN_IT_LPI  : LIN identifier parity interrupt bit
  *             @arg LIN_IT_LCI  : LIN checksum error interrupt bit
  *             @arg LIN_IT_LAI  : LIN automatic baud rate detection error interrupt bit
  *             @arg LIN_IT_RTI  : LIN response timeout interrupt bit
  *             @arg LIN_IT_HTI  : LIN frame header timeout interrupt bit
  *             @arg LIN_IT_TRI  : LIN response sending interrupt bit
  *             @arg LIN_IT_THI  : LIN frame sending interrupt blocking bit
  *             @arg LIN_IT_RRI  : LIN response receive interrupt bit
  *             @arg LIN_IT_RHI  : LIN frame header receive interrupt bit
  * @retval None
  */
void LIN_ClearITPendingBit(USART_TypeDef *USARTx, uint32_t LIN_IT)
{
  /* Check the parameters */
  assert_param(IS_LIN_IT(LIN_IT));

  USARTx->USARTICR1 |= LIN_IT;
}

/** 
  * @name   LIN_Request
  * @brief  EN: LIN sends and responds to requests
  *         CN: LIN 发送和应答请求
  * @param  USARTx: 
  *         EN: where x can be from 0 or 1 to select the USART peripheral.
  *         CN: 其中 x 可以是 0 或 1 以选择 USART 外设。
  * @param  Request
  *         EN: Configuration request
  *         CN: 配置请求
  *             @arg LIN_Master_Only_Header
  *             @arg LIN_Master_Send_Response
  *             @arg LIN_Master_Recv_Response
  *             @arg LIN_Slave_Recv_Data
  *             @arg LIN_Slave_Send_Data
  *             @arg LIN_Slave_None_Response
  *             @arg LIN_Stop_Response
  *             @arg LIN_Wake_Up
  * @retval None
*/
void LIN_Request(USART_TypeDef *USARTx, uint32_t Request)
{
  /* Check the parameters */
  assert_param(IS_LIN_REQUEST(Request));
  

  if ((Request == (LIN_Master_Only_Header)) || (Request == (LIN_Slave_None_Response)))
  {
    USARTx->DATCON_b.HO |= 1;
  }
  else
  {
    USARTx->DATCON_b.HO &= 0;
  }

  USARTx->LINCON2 = Request;
}
