基于STM32F103RCT6实现串口中断发送,使用环形队列

一、开发环境

/***************************************************************
文章名:基于STM32F103RCT6这款MCU实现串口中断发送,使用环形队列
时间:2022年5月27日21:12:58
科室:N/A
员工:N/A
版本:V0
修改记录:N/A
目的:基于STM32F103RCT6这款MCU实现打印。这里的打印使用的非阻塞方式发送,也就是使用中断发送串口数据。并且,发送数据时使用了环形队列这样一种高级数据结构,用于做串口发送的缓冲区。这篇文章会总结实现的硬件平台、软件平台、调试工具、调试手段、心得体会,详细的代码文件也会在文章里展示出来。
硬件平台:基于STM32F103RCT6的开发板,STM32F103RCT6是基于ARM
Cortex M3系列的单片机,外部晶振使用8MHZ,3.3V供电。
软件平台:keil uvision5
下载工具:串口线、stc-isp-15xx-v6.87E
调试工具:XCOM V2.0
***************************************************************/
硬件平台图片:
在这里插入图片描述
软件平台图片:
在这里插入图片描述
下载工具图片:
在这里插入图片描述
调试工具图片:
在这里插入图片描述

二、串口中断发送原理

在正点原子系列教学里,printf的实现是通过如下方式实现的:

int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//Ñ­»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï   
    USART1->DR = (u8) ch;      
	return ch;
}

这种方式打印数据有个特点,就是打印函数里用了while,也就是说每次发送前判断条件“USART1->SR&0X40)==0”,也就是判断一个字节的数据是否发送完毕。以波特率115200,1个起始位,1个停止位,8个数据位,无校验为例,发送这样一个字节的数据耗时10/115200(s)=8.68e(-5) s,也就是0.086ms。如果一次打印50个数据,就是4.3ms,这段时间里,mcu在等待数据发送完毕,没办法执行其他任务。可见这种方式非常耗费资源。
本文介绍另外一种中断方式发送串口数据的方法,每次检测到发送数据寄存器空,就在中断里向数据寄存器写数据,数据发送完毕,发送寄存器又空,又产生中断,循环往复,直到所有数据发送完毕。这种方式的优点在于,串口发送数据的时候是硬件行为,并不需要cpu等待所有数据发送完毕,利用了串口发送数据寄存器空产生中断这个特性。

三、实验现象

在这里插入图片描述

四、完整源码

stm32f10x_it.c

在这里插入代码片

/**
  ******************************************************************************
  * @file    GPIO/IOToggle/stm32f10x_it.c 
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main Interrupt Service Routines.
  *          This file provides template for all exceptions handler and peripherals
  *          interrupt service routine.
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */

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


 
void NMI_Handler(void)
{
}

void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}
 
void MemManage_Handler(void)
{
  /* Go to infinite loop when Memory Manage exception occurs */
  while (1)
  {
  }
}

 
void BusFault_Handler(void)
{
  /* Go to infinite loop when Bus Fault exception occurs */
  while (1)
  {
  }
}
 
void UsageFault_Handler(void)
{
  /* Go to infinite loop when Usage Fault exception occurs */
  while (1)
  {
  }
}
 
void SVC_Handler(void)
{
}
 
void DebugMon_Handler(void)
{
}
 
void PendSV_Handler(void)
{
}
 
void SysTick_Handler(void)
{
}

/******************************************************************************/
/*                 STM32F10x Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f10x_xx.s).                                            */
/******************************************************************************/
system_stm32f10x.c

```c
/**
  ******************************************************************************
  * @file    GPIO/IOToggle/system_stm32f10x.c
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.
  * 
  * 1.  This file provides two functions and one global variable to be called from 
  *     user application:
  *      - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
  *                      factors, AHB/APBx prescalers and Flash settings). 
  *                      This function is called at startup just after reset and 
  *                      before branch to main program. This call is made inside
  *                      the "startup_stm32f10x_xx.s" file.
  *
  *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
  *                                  by the user application to setup the SysTick 
  *                                  timer or configure other parameters.
  *                                     
  *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
  *                                 be called whenever the core clock is changed
  *                                 during program execution.
  *
  * 2. After each device reset the HSI (8 MHz) is used as system clock source.
  *    Then SystemInit() function is called, in "startup_stm32f10x_xx.s" file, to
  *    configure the system clock before to branch to main program.
  *
  * 3. If the system clock source selected by user fails to startup, the SystemInit()
  *    function will do nothing and HSI still used as system clock source. User can 
  *    add some code to deal with this issue inside the SetSysClock() function.
  *
  * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depedning on
  *    the product used), refer to "HSE_VALUE" define in "stm32f10x.h" file. 
  *    When HSE is used as system clock source, directly or through PLL, and you
  *    are using different crystal you have to adapt the HSE value to your own
  *    configuration.
  *        
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */

/** @addtogroup CMSIS
  * @{
  */

/** @addtogroup stm32f10x_system
  * @{
  */  
  
/** @addtogroup STM32F10x_System_Private_Includes
  * @{
  */

#include "stm32f10x.h"

/**
  * @}
  */

/** @addtogroup STM32F10x_System_Private_TypesDefinitions
  * @{
  */

/**
  * @}
  */

/** @addtogroup STM32F10x_System_Private_Defines
  * @{
  */

/*!< Uncomment the line corresponding to the desired System clock (SYSCLK)
   frequency (after reset the HSI is used as SYSCLK source)
   
   IMPORTANT NOTE:
   ============== 
   1. After each device reset the HSI is used as System clock source.

   2. Please make sure that the selected System clock doesn't exceed your device's
      maximum frequency.
      
   3. If none of the define below is enabled, the HSI is used as System clock
    source.

   4. The System clock configuration functions provided within this file assume that:
        - For Low, Medium and High density Value line devices an external 8MHz 
          crystal is used to drive the System clock.
        - For Low, Medium and High density devices an external 8MHz crystal is
          used to drive the System clock.
        - For Connectivity line devices an external 25MHz crystal is used to drive
          the System clock.
     If you are using different crystal you have to adapt those functions accordingly.
    */
    
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
 #define SYSCLK_FREQ_24MHz  24000000
#else
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz  24000000 */ 
/* #define SYSCLK_FREQ_36MHz  36000000 */
/* #define SYSCLK_FREQ_48MHz  48000000 */
/* #define SYSCLK_FREQ_56MHz  56000000 */
#define SYSCLK_FREQ_72MHz  72000000
#endif

/*!< Uncomment the following line if you need to use external SRAM mounted
     on STM3210E-EVAL board (STM32 High density and XL-density devices) or on 
     STM32100E-EVAL board (STM32 High-density value line devices) as data memory */ 
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
/* #define DATA_IN_ExtSRAM */
#endif

/*!< Uncomment the following line if you need to relocate your vector Table in
     Internal SRAM. */ 
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET  0x0 /*!< Vector Table base offset field. 
                                  This value must be a multiple of 0x200. */


/**
  * @}
  */

/** @addtogroup STM32F10x_System_Private_Macros
  * @{
  */

/**
  * @}
  */

/** @addtogroup STM32F10x_System_Private_Variables
  * @{
  */

/*******************************************************************************
*  Clock Definitions
*******************************************************************************/
#ifdef SYSCLK_FREQ_HSE
  uint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_24MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_36MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_36MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;        /*!< System Clock Frequency (Core Clock) */
#else /*!< HSI Selected as System Clock source */
  uint32_t SystemCoreClock         = HSI_VALUE;        /*!< System Clock Frequency (Core Clock) */
#endif

__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/**
  * @}
  */

/** @addtogroup STM32F10x_System_Private_FunctionPrototypes
  * @{
  */

static void SetSysClock(void);

#ifdef SYSCLK_FREQ_HSE
  static void SetSysClockToHSE(void);
#elif defined SYSCLK_FREQ_24MHz
  static void SetSysClockTo24(void);
#elif defined SYSCLK_FREQ_36MHz
  static void SetSysClockTo36(void);
#elif defined SYSCLK_FREQ_48MHz
  static void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHz
  static void SetSysClockTo56(void);  
#elif defined SYSCLK_FREQ_72MHz
  static void SetSysClockTo72(void);
#endif

#ifdef DATA_IN_ExtSRAM
  static void SystemInit_ExtMemCtl(void); 
#endif /* DATA_IN_ExtSRAM */

/**
  * @}
  */

/** @addtogroup STM32F10x_System_Private_Functions
  * @{
  */

/**
  * @brief  Setup the microcontroller system
  *         Initialize the Embedded Flash Interface, the PLL and update the 
  *         SystemCoreClock variable.
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
void SystemInit (void)
{
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
  RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
  RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   
  
  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC->CFGR &= (uint32_t)0xFF80FFFF;

#ifdef STM32F10X_CL
  /* Reset PLL2ON and PLL3ON bits */
  RCC->CR &= (uint32_t)0xEBFFFFFF;

  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x00FF0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;      
#else
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
    
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl(); 
  #endif /* DATA_IN_ExtSRAM */
#endif 

  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  /* Configure the Flash Latency cycles and enable prefetch buffer */
  SetSysClock();

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

/**
  * @brief  Update SystemCoreClock variable according to Clock Register Values.
  *         The SystemCoreClock variable contains the core clock (HCLK), it can
  *         be used by the user application to setup the SysTick timer or configure
  *         other parameters.
  *           
  * @note   Each time the core clock (HCLK) changes, this function must be called
  *         to update SystemCoreClock variable value. Otherwise, any configuration
  *         based on this variable will be incorrect.         
  *     
  * @note   - The system frequency computed by this function is not the real 
  *           frequency in the chip. It is calculated based on the predefined 
  *           constant and the selected clock source:
  *             
  *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
  *                                              
  *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
  *                          
  *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) 
  *             or HSI_VALUE(*) multiplied by the PLL factors.
  *         
  *         (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value
  *             8 MHz) but the real value may vary depending on the variations
  *             in voltage and temperature.   
  *    
  *         (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value
  *              8 MHz or 25 MHz, depedning on the product used), user has to ensure
  *              that HSE_VALUE is same as the real frequency of the crystal used.
  *              Otherwise, this function may have wrong result.
  *                
  *         - The result of this function could be not correct when using fractional
  *           value for HSE crystal.
  * @param  None
  * @retval None
  */
void SystemCoreClockUpdate (void)
{
  uint32_t tmp = 0, pllmull = 0, pllsource = 0;

#ifdef  STM32F10X_CL
  uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
#endif /* STM32F10X_CL */

#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  uint32_t prediv1factor = 0;
#endif /* STM32F10X_LD_VL or STM32F10X_MD_VL or STM32F10X_HD_VL */
    
  /* Get SYSCLK source -------------------------------------------------------*/
  tmp = RCC->CFGR & RCC_CFGR_SWS;
  
  switch (tmp)
  {
    case 0x00:  /* HSI used as system clock */
      SystemCoreClock = HSI_VALUE;
      break;
    case 0x04:  /* HSE used as system clock */
      SystemCoreClock = HSE_VALUE;
      break;
    case 0x08:  /* PLL used as system clock */

      /* Get PLL clock source and multiplication factor ----------------------*/
      pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;
      pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
      
#ifndef STM32F10X_CL      
      pllmull = ( pllmull >> 18) + 2;
      
      if (pllsource == 0x00)
      {
        /* HSI oscillator clock divided by 2 selected as PLL clock entry */
        SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
      }
      else
      {
 #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
       prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;
       /* HSE oscillator clock selected as PREDIV1 clock entry */
       SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; 
 #else
        /* HSE selected as PLL clock entry */
        if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET)
        {/* HSE oscillator clock divided by 2 */
          SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
        }
        else
        {
          SystemCoreClock = HSE_VALUE * pllmull;
        }
 #endif
      }
#else
      pllmull = pllmull >> 18;
      
      if (pllmull != 0x0D)
      {
         pllmull += 2;
      }
      else
      { /* PLL multiplication factor = PLL input clock * 6.5 */
        pllmull = 13 / 2; 
      }
            
      if (pllsource == 0x00)
      {
        /* HSI oscillator clock divided by 2 selected as PLL clock entry */
        SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
      }
      else
      {/* PREDIV1 selected as PLL clock entry */
        
        /* Get PREDIV1 clock source and division factor */
        prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC;
        prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;
        
        if (prediv1source == 0)
        { 
          /* HSE oscillator clock selected as PREDIV1 clock entry */
          SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;          
        }
        else
        {/* PLL2 clock selected as PREDIV1 clock entry */
          
          /* Get PREDIV2 division factor and PLL2 multiplication factor */
          prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4) + 1;
          pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8 ) + 2; 
          SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;                         
        }
      }
#endif /* STM32F10X_CL */ 
      break;

    default:
      SystemCoreClock = HSI_VALUE;
      break;
  }
  
  /* Compute HCLK clock frequency ----------------*/
  /* Get HCLK prescaler */
  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
  /* HCLK clock frequency */
  SystemCoreClock >>= tmp;  
}

/**
  * @brief  Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
  * @param  None
  * @retval None
  */
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
  SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
  SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
  SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
  SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
  SetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHz
  SetSysClockTo72();
#endif
 
 /* If none of the define above is enabled, the HSI is used as System clock
    source (default after reset) */ 
}

/**
  * @brief  Setup the external memory controller. Called in startup_stm32f10x.s 
  *          before jump to __main
  * @param  None
  * @retval None
  */ 
#ifdef DATA_IN_ExtSRAM
/**
  * @brief  Setup the external memory controller. 
  *         Called in startup_stm32f10x_xx.s/.c before jump to main.
  * 	      This function configures the external SRAM mounted on STM3210E-EVAL
  *         board (STM32 High density devices). This SRAM will be used as program
  *         data memory (including heap and stack).
  * @param  None
  * @retval None
  */ 
void SystemInit_ExtMemCtl(void) 
{
/*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is 
  required, then adjust the Register Addresses */

  /* Enable FSMC clock */
  RCC->AHBENR = 0x00000114;
  
  /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */  
  RCC->APB2ENR = 0x000001E0;
  
/* ---------------  SRAM Data lines, NOE and NWE configuration ---------------*/
/*----------------  SRAM Address lines configuration -------------------------*/
/*----------------  NOE and NWE configuration --------------------------------*/  
/*----------------  NE3 configuration ----------------------------------------*/
/*----------------  NBL0, NBL1 configuration ---------------------------------*/
  
  GPIOD->CRL = 0x44BB44BB;  
  GPIOD->CRH = 0xBBBBBBBB;

  GPIOE->CRL = 0xB44444BB;  
  GPIOE->CRH = 0xBBBBBBBB;

  GPIOF->CRL = 0x44BBBBBB;  
  GPIOF->CRH = 0xBBBB4444;

  GPIOG->CRL = 0x44BBBBBB;  
  GPIOG->CRH = 0x44444B44;
   
/*----------------  FSMC Configuration ---------------------------------------*/  
/*----------------  Enable FSMC Bank1_SRAM Bank ------------------------------*/
  
  FSMC_Bank1->BTCR[4] = 0x00001011;
  FSMC_Bank1->BTCR[5] = 0x00000200;
}
#endif /* DATA_IN_ExtSRAM */

#ifdef SYSCLK_FREQ_HSE
/**
  * @brief  Selects HSE as System clock source and configure HCLK, PCLK2
  *          and PCLK1 prescalers.
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
static void SetSysClockToHSE(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {

#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 0 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);

#ifndef STM32F10X_CL
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
#else
    if (HSE_VALUE <= 24000000)
	{
      FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
	}
	else
	{
      FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
	}
#endif /* STM32F10X_CL */
#endif
 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
    
    /* Select HSE as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE;    

    /* Wait till HSE is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  }  
}
#elif defined SYSCLK_FREQ_24MHz
/**
  * @brief  Sets System clock frequency to 24MHz and configure HCLK, PCLK2 
  *          and PCLK1 prescalers.
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
static void SetSysClockTo24(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL 
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 0 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;    
#endif
 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
    
#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL configuration: PLLCLK = PREDIV1 * 6 = 24 MHz */ 
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL6); 

    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */       
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }   
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
    /*  PLL configuration:  = (HSE / 2) * 6 = 24 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6);
#else    
    /*  PLL configuration:  = (HSE / 2) * 6 = 24 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL6);
#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }

    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  } 
}
#elif defined SYSCLK_FREQ_36MHz
/**
  * @brief  Sets System clock frequency to 36MHz and configure HCLK, PCLK2 
  *          and PCLK1 prescalers. 
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
static void SetSysClockTo36(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 1 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;    
 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
    
#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    
    /* PLL configuration: PLLCLK = PREDIV1 * 9 = 36 MHz */ 
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL9); 

	/*!< PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
    
#else    
    /*  PLL configuration: PLLCLK = (HSE / 2) * 9 = 36 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }

    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  } 
}
#elif defined SYSCLK_FREQ_48MHz
/**
  * @brief  Sets System clock frequency to 48MHz and configure HCLK, PCLK2 
  *          and PCLK1 prescalers. 
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
static void SetSysClockTo48(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 1 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;    
 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
    
#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
    
   
    /* PLL configuration: PLLCLK = PREDIV1 * 6 = 48 MHz */ 
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL6); 
#else    
    /*  PLL configuration: PLLCLK = HSE * 6 = 48 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);
#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }

    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  } 
}

#elif defined SYSCLK_FREQ_56MHz
/**
  * @brief  Sets System clock frequency to 56MHz and configure HCLK, PCLK2 
  *          and PCLK1 prescalers. 
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
static void SetSysClockTo56(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 2 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    
 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
    
   
    /* PLL configuration: PLLCLK = PREDIV1 * 7 = 56 MHz */ 
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL7); 
#else     
    /* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL7);

#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }

    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  } 
}

#elif defined SYSCLK_FREQ_72MHz
/**
  * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2 
  *          and PCLK1 prescalers. 
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 2 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    

 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
    
   
    /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL9); 
#else    
    /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
    
    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  }
}
#endif

/**
  * @}
  */

/**
  * @}
  */
  
/**
  * @}
  */    
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

uartsend_use_int.c

```c
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "stm32f10x_usart.h"
#include "misc.h"
#include "string.h"
#include "timer.h"
#include "test.h"

#define TxBufferSize1   (countof(TxBuffer1) - 1)
#define RxBufferSize1   (countof(TxBuffer1) - 1)
#define countof(a)   (sizeof(a) / sizeof(*(a)))      //表示数组a中元素的个数 

#ifndef true 
#define true 1
#endif

#ifndef false 
#define false 0
#endif	

typedef unsigned char uint8_t ; 
uint8_t TxBuffer1[] = "USART Interrupt Example: This is USART1 DEMO,SUCCESS\n";
uint8_t RxBuffer1[RxBufferSize1],rec_f;
uint8_t TxCounter1 = 0x00;
uint8_t RxCounter1 = 0x00;
uint8_t NbrOfDataToTransfer1 = TxBufferSize1;
uint8_t NbrOfDataToRead1 = RxBufferSize1;

#define DEBUG_STRING "HELLO_WORLD\n"

#ifndef TRUE
#define TRUE 1U
#endif
#ifndef FALSE
#define FALSE 0U
#endif

//#define USE_NONBLOCK_USART
#ifndef USE_NONBLOCK_USART
//#define USE_BLOCK_USART
#endif


#define BAUDRATE_115200 115200U

typedef struct
{
	u8 UartSendData_Indixcation;
	u8 local_uart_transmit_buf[50];
	
}G_UART_Context_Var_t;

G_UART_Context_Var_t  G_UART_Context_Var = {0};

void Set_UartSendData_Indixcation(u8 status);
u8 Get_UartSendData_Indixcation(void);


void Set_UartSendData_Indixcation(u8 status)
{
	G_UART_Context_Var.UartSendData_Indixcation = status;
}

u8 Get_UartSendData_Indixcation(void)
{
	return G_UART_Context_Var.UartSendData_Indixcation;
}

void bsp_init(u32 uart_baudrate)
{
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;

	//1 gpio init
		/* Enable USART1, GPIOA, GPIOD and AFIO clocks */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA , ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;		   //USART1 TX
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//A端口
	 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;			   //USART1 RX
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//复用开漏输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);				 //A端口

	//2 open clock
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//ÇÀÕ¼ÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//×ÓÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQͨµÀʹÄÜ
	NVIC_Init(&NVIC_InitStructure);	//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷


	//3 init usart1
	/* Enable USART1, GPIOA, GPIOD and AFIO clocks */
	if((uart_baudrate) == 115200)
		USART_InitStructure.USART_BaudRate = uart_baudrate;
	else
		USART_InitStructure.USART_BaudRate = 		USART_InitStructure.USART_BaudRate = uart_baudrate;

	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No; 	 //设置奇校验时,通信出现错误
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	 /* Configure the USART1 */
	USART_Init(USART1, &USART_InitStructure);
	 /* Enable the USART Transmoit interrupt: this interrupt is generated when the
	USART1 transmit data register is empty */ 
	//USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
	 /* Enable the USART Receive interrupt: this interrupt is generated when the
	  USART1 receive data register is not empty */
	//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//Usart1 NVIC ÅäÖÃ
  
	
	
	 /* Enable USART1 */
	USART_Cmd(USART1, ENABLE);
					

}

void SoftTimer_Init(void)
{

}


/*串口中断服务程序*/
//void USART1_IRQHandler(void)
//{
//  //unsigned int i;
//  /*接收中断*/
//#if 0
//  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
//  {   
//    /* Read one byte from the receive data register */
//    RxBuffer1[RxCounter1++] = USART_ReceiveData(USART1);
//    if(RxCounter1 == NbrOfDataToRead1)  //接收数据达到需要长度,则将数据复制到发送数组中,并置标志
//    {                     
//      /* Disable the USART1 Receive interrupt */
//      //USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
//        for(i=0; i< RxCounter1; i++) TxBuffer1[i]  = RxBuffer1[i];
//        rec_f=1;
//        RxCounter1=0;
//        TxCounter1=0;
//        USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  //打开发送中断,这句是关键
//    }
//  }
//#endif
//	
//  /*发送中断*/
//  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
//  {  
//#if 1
//    USART_SendData(USART1, TxBuffer1[TxCounter1++]);
//	Set_UartSendData_Indixcation(true);
//
// 
//    if(TxCounter1 == NbrOfDataToTransfer1)//发送数据完成
//    {   
//			TxCounter1 = 0;
//			Set_UartSendData_Indixcation(false);
//			//memset(TxBuffer1,0x0,sizeof(TxBuffer1));
//      USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //关闭发送中断
//    }
//#endif		
//  }   
//} 

#ifdef USE_BLOCK_USART
void Send_DebugData(char *p)
{	
	while((*p != '\0'))
	{
		while (!(USART1->SR & USART_FLAG_TXE))          // wait for TX buffer to empty
		continue;                           		// also either WDOG() or swap()
		USART_SendData(USART1,*p);
		while((USART1->SR&0X40)==0);
		p++;
	}		
}
#endif

void Send_DebugData_UseNoBlock(char *p,u8 length)
{
	if((NULL == p) && (length > 50))
	{
		return;
	}

	if((TxCounter1 == 0) && (false == Get_UartSendData_Indixcation()))
	{
		USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
	}
	else
	{
		
		return;
	}
}


int main(void)
{
 unsigned char cnt = 0;
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
 //bsp_init(BAUDRATE_115200);
 delay_init();
 //Set_UartSendData_Indixcation(FALSE);
 LED_Init();
 TIM3_Int_Init(5000,7199);
 //test_uart_init();
 test_init();
 test_printf(1,"UART SEND use interrupt and ringbuffer V0\r\n");

 while (1)
 {
 #ifdef USE_NONBLOCK_USART
	Send_DebugData_UseNoBlock(TxBuffer1,sizeof(TxBuffer1));
 	delay_ms(1000); 
 #endif

 #ifdef USE_BLOCK_USART
	 delay_ms(5000);

	 if(FALSE == Get_UartSendData_Indixcation())
	 {
		Send_DebugData(DEBUG_STRING);
		delay_ms(10000);
		USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
		Set_UartSendData_Indixcation(TRUE);		
	 }
#endif
	 delay_ms(500);
	 LED0 = !LED0;
	 if(cnt++ >= 65535)
	 {
		cnt = 0;
	 }
	 
	 test_printf(1,"DEBUG INFO:cnt = %d\r\n",cnt); 
	 __asm("nop");
 }
}


ringbuf.c

//*****************************************************************************
// file		: ringbuf.c
// 
// Copyright (c) 2011-2014 HUAWEI co. Ltd. All rights reserved
// 
// Change Logs:
// Date				Author		Note	
// 2015/04/02    	chc			
// 
//*****************************************************************************

//*****************************************************************************
//
//! \addtogroup 
//! @{
//
//*****************************************************************************
#include "ringbuf.h"

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void ringbuf_init(tRingBuf *pRingBuf, unsigned char *pBuf, unsigned char size)
{
    pRingBuf->head = pRingBuf->tail = 0;
    pRingBuf->pBuf = pBuf;
    pRingBuf->size = size;
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_empty(tRingBuf *pRingBuf)
{
    return (pRingBuf->head == pRingBuf->tail);
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_full(tRingBuf *pRingBuf)
{
    return (((pRingBuf->tail + 1) % pRingBuf->size) == pRingBuf->head);
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_avail(tRingBuf *pRingBuf)
{
    return pRingBuf->size - pRingBuf->head + pRingBuf->tail;
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_size(tRingBuf *pRingBuf)
{
    return pRingBuf->size;
}

/**
  * \brief Returns number of bytes stored in ring buffer.
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_used(tRingBuf *pRingBuf)
{
    unsigned char tail, head;

    tail = pRingBuf->tail;
    head = pRingBuf->head;

    return((head >= tail) ? (head - tail) :
        (pRingBuf->size - (tail - head))); 
}

/**
  * \brief Returns number of bytes available in a ring buffer.
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_free(tRingBuf *pRingBuf)
{
    return((pRingBuf->size - 1) - ringbuf_used(pRingBuf));
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void ringbuf_write_one(tRingBuf *pRingBuf, unsigned char data)
{
    if (ringbuf_avail(pRingBuf) != 0)
    {
        pRingBuf->pBuf[pRingBuf->head] = data;
        pRingBuf->head++;

        if (pRingBuf->head >= pRingBuf->size)
        {
            pRingBuf->head = 0;
        }
    }
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void ringbuf_write(tRingBuf *pRingBuf, unsigned char *pData, unsigned char len)
{
    unsigned char i;

    for (i = 0; i < len; i++)
    {
        ringbuf_write_one(pRingBuf, pData[i]);
    }
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_read_one(tRingBuf *pRingBuf)
{
    unsigned char data;

    data = pRingBuf->pBuf[pRingBuf->tail++];

    if (pRingBuf->tail >= pRingBuf->size)
    {
        pRingBuf->tail = 0;
    }

    return data;
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void ringbuf_read(tRingBuf *pRingBuf, unsigned char *pData, unsigned char len)
{
    unsigned char i;

    for (i = 0; i < len; i++)
    {
        pData[i] = ringbuf_read_one(pRingBuf);
    }
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************

//*****************************************************************************
// file		: ringbuf.c
// 
// Copyright (c) 2011-2014 HUAWEI co. Ltd. All rights reserved
// 
// Change Logs:
// Date				Author		Note	
// 2015/04/02    	chc			
// 
//*****************************************************************************

//*****************************************************************************
//
//! \addtogroup 
//! @{
//
//*****************************************************************************
#include "ringbuf.h"

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void ringbuf_init(tRingBuf *pRingBuf, unsigned char *pBuf, unsigned char size)
{
    pRingBuf->head = pRingBuf->tail = 0;
    pRingBuf->pBuf = pBuf;
    pRingBuf->size = size;
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_empty(tRingBuf *pRingBuf)
{
    return (pRingBuf->head == pRingBuf->tail);
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_full(tRingBuf *pRingBuf)
{
    return (((pRingBuf->tail + 1) % pRingBuf->size) == pRingBuf->head);
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_avail(tRingBuf *pRingBuf)
{
    return pRingBuf->size - pRingBuf->head + pRingBuf->tail;
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_size(tRingBuf *pRingBuf)
{
    return pRingBuf->size;
}

/**
  * \brief Returns number of bytes stored in ring buffer.
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_used(tRingBuf *pRingBuf)
{
    unsigned char tail, head;

    tail = pRingBuf->tail;
    head = pRingBuf->head;

    return((head >= tail) ? (head - tail) :
        (pRingBuf->size - (tail - head))); 
}

/**
  * \brief Returns number of bytes available in a ring buffer.
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_free(tRingBuf *pRingBuf)
{
    return((pRingBuf->size - 1) - ringbuf_used(pRingBuf));
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void ringbuf_write_one(tRingBuf *pRingBuf, unsigned char data)
{
    if (ringbuf_avail(pRingBuf) != 0)
    {
        pRingBuf->pBuf[pRingBuf->head] = data;
        pRingBuf->head++;

        if (pRingBuf->head >= pRingBuf->size)
        {
            pRingBuf->head = 0;
        }
    }
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void ringbuf_write(tRingBuf *pRingBuf, unsigned char *pData, unsigned char len)
{
    unsigned char i;

    for (i = 0; i < len; i++)
    {
        ringbuf_write_one(pRingBuf, pData[i]);
    }
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
unsigned char ringbuf_read_one(tRingBuf *pRingBuf)
{
    unsigned char data;

    data = pRingBuf->pBuf[pRingBuf->tail++];

    if (pRingBuf->tail >= pRingBuf->size)
    {
        pRingBuf->tail = 0;
    }

    return data;
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void ringbuf_read(tRingBuf *pRingBuf, unsigned char *pData, unsigned char len)
{
    unsigned char i;

    for (i = 0; i < len; i++)
    {
        pData[i] = ringbuf_read_one(pRingBuf);
    }
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************


test.c

//*****************************************************************************
// file		: test.c
// test module
// Copyright (c) 2011-2014 HUAWEI co. Ltd. All rights reserved
// 
// Change Logs:
// Date				Author		Note	
// 2014/01/21    	chc			
// 
//*****************************************************************************

//*****************************************************************************
//
//! \addtogroup 
//! @{
//
//*****************************************************************************
#include "test.h"
#include "test_uart.h"
//#include "test_msgproc.h"
#include "stdarg.h"
#include "stdio.h"
#include "string.h"
//#include "UnitCheck\BattCheck.h"
//#include "SystemManage\SystemStateManage\SystemStateManage.h"
//#include "SoftTimer\Manage_SoftTimer.h"
//#include "CarSignalManage\CarSignalManage.h"
//#include "Debug_Uart.h"
//#include "MX51\MX51MsgProcess.h"


//#define cmdMAX_INPUT_SIZE		128
//
//unsigned char cInputIndex = 0;
//static char cInputString[ cmdMAX_INPUT_SIZE ], cLastInputString[ cmdMAX_INPUT_SIZE ];
//
//
//unsigned char DEBUG_CanInfo = 0;		//CAN print
//unsigned char DEBUG_UartRec = 0;		//uart print
//unsigned char DEBUG_UartSend = 0;
//unsigned char DEBUG_ResendInfo = 0; 	//Resend Print
//unsigned char DEBUG_KeyInfo = 0;
//
//unsigned char DEBUG_KernelInfo = 0;
//
//
//extern unsigned char gHeartEnableFlag;
//extern unsigned char Mx51_CurrentState;
//extern Type_SystemState G_SystemState;
//extern unsigned char AMP_MuteState;
//extern unsigned char AutoTestRecved;
//
//tPrintLevel s_printlevel;
static unsigned char AutoTestRecved = 0;

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void test_init(void)
{
	test_uart_init();
//	test_set_printlevel(TEST_PRINT_LEVEL_DEFAULT);
//	Debug_uart_init();
}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
//void test_set_printlevel(tPrintLevel level)
//{
//	s_printlevel = level;
//}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
//void test_process_per10ms(void)
//{
//	test_msgproc_rcvmsg();
//	test_rcv_timeout_process();
//}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
//void test_print_array(unsigned char *pByte, unsigned char len, tPrintLevel level)
//{
//	if (level >= s_printlevel)
//	{
//		test_uart_send(pByte, len);
//	}
//}

/**
  * \brief 
  *
  * \param None
  *   
  * \return None
  */
void test_printf(unsigned char printFlags, const char *fmt, ...)
{
		if((printFlags == 1) && (AutoTestRecved == 0)) /*Ìí¼Ó×Ô¶¯²âÊÔ¼ìÑé*/
    {
		va_list args;
		unsigned char length;
		char buf[100];
		
		va_start(args, fmt);
		length = vsprintf(buf, fmt, args);

	    // auto testÒѾ­ÓÃÁË´®¿Ú£¬¹Ê֮ǰ´òÓ¡ÆÁ±Î modify by kuan 2017Äê11ÔÂ20ÈÕ15:54:04
		test_uart_send((unsigned char *)buf, strlen(buf));
		
		va_end(args);
	}
}

/******************************************************************************
** Function    : getConsoleData
** Description : debug uart
** Input       : None
** Output      : None
** Author      : xuany
** Date        : 20180202
*******************************************************************************/
//unsigned char getConsoleData(char* pBuf, char* returnbuf,unsigned char bufSize)
//{
//    unsigned char i = 0;
//    unsigned char iPos = 0;
//
//    for ( ; i < bufSize; i++)
//    {
//        if((*(pBuf + i) == ' ')||(*(pBuf + i) == '-')||(*(pBuf + i) == ':'))
//        {
//            break;
//        }
//        else
//        {
//            returnbuf[iPos ++] = *(pBuf + i);
//        }
//    }
//    returnbuf[iPos ++] = '\0'; /*end*/
//    return iPos;
//}

//void  ConsoleDataInfo(char* pSourceBuf, char* pDestBuf)
//{	
//	unsigned char  index =0,iPos = 0;
//	unsigned char  ConsoleStatus = 0;  /*open : 1   close : 0*/
//	unsigned char  ConfigVehicleBuf[5]= {0x00};
//	unsigned long  EEpromAddr = 0;
//	unsigned char  ReadEEpromBuf[9]= {0x00};
//	unsigned char  i = 0;
//	
//	iPos = getConsoleData((char *)(pSourceBuf+index), (char *)pDestBuf, strlen(pSourceBuf)-index);/*open or close*/	
//
//	if(strcmp(pDestBuf,"init") == 0)
//	{
//		test_printf(0,"error\r\n");
//	}
//	
//	else if(strcmp(pDestBuf,"Open")==0)
//	{
//		ConsoleStatus = 1;
//	}
//	else if(strcmp(pDestBuf,"Close")==0)
//	{
//		ConsoleStatus = 0;
//	}
//	else if (strcmp(pDestBuf, "Reset") == 0)
//	{
//		SystemGotoRestart(5);
//	}
//
//	index += iPos;
//	iPos = getConsoleData((char *)(pSourceBuf+index), (char *)pDestBuf, strlen(pSourceBuf)-index);
//
//	if(strcmp(pDestBuf,"Can")==0)
//	{
//			if(ConsoleStatus)  DEBUG_CanInfo=1;
//			else               DEBUG_CanInfo=0;	
//	}
//	else if(strcmp(pDestBuf,"UartRec")==0)
//	{
//		if(ConsoleStatus)  DEBUG_UartRec=1;
//		else               DEBUG_UartRec=0;
//	}
//	else if(strcmp(pDestBuf,"UartSend")==0)
//	{
//		if(ConsoleStatus)  DEBUG_UartSend=1;
//		else               DEBUG_UartSend=0;
//	}
//	else if(strcmp(pDestBuf,"Resend")==0)
//	{
//			if(ConsoleStatus)  DEBUG_ResendInfo=1;
//			else               DEBUG_ResendInfo=0;	
//	}
//	else if(strcmp(pDestBuf,"Key")==0)
//	{
//			if(ConsoleStatus)  DEBUG_KeyInfo=1;
//			else               DEBUG_KeyInfo=0;	
//	}
//	else if(strcmp(pDestBuf,"Heart")==0)/*Heart*/
//	{
//		if(ConsoleStatus)  gHeartEnableFlag = 1;
//		else               gHeartEnableFlag = 0;
//	}
//	else if(strcmp(pDestBuf,"Vat")==0)/*Battery*/
//	{
//		test_printf(1,"Vat:%d\r\n",sBattManage.ad_val);
//	}
//	else if(strcmp(pDestBuf,"ShakeHand")==0)/*ShakeHand*/
//	{
//		test_printf(1,"ShakeHand:%x,%x,%x,%x\r\n",Mx51_CurrentState,G_SystemState.CurrentState,AMP_MuteState,CarSignal_ACCState_Inquire());
//	}
//	else if(strcmp(pDestBuf,"Bsp")==0)
//	{
//		test_printf(1,"BspHeartCount:%d\r\n",ReceiveBspCount);
//	}
//	else if(strcmp(pDestBuf,"Kernel")==0)
//	{
//		DEBUG_KernelInfo = 1;
//	}
//}


//void GetShellDada(unsigned char RcvedChar)
//{
//
///* Was it the end of the line? */
//	if( RcvedChar == '\n' || RcvedChar == '\r' )
//	{
//		/* Just to space the output from the input. */
//		test_printf(1,"\r\n");
//		test_printf(1,">");
//
//		/*analyze uart data*/		
//		ConsoleDataInfo( ( char * ) cInputString, ( char * ) cLastInputString );
//
//		/* All the strings generated by the input command have been sent.
//		Clear the input string ready to receive the next command.  Remember
//		the command that was just processed first in case it is to be
//		processed again. */
//		cInputIndex = 0;
//		memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
//		memset( cLastInputString, 0x00, cmdMAX_INPUT_SIZE );
		DebugUart_PutString(">");
//		/* xPrintf( pcEndOfOutputMessage ); */
//	}
//	else
//	{
//		if( RcvedChar == '\r' )
//		{
//			/* Ignore the character. */
//		}
//		else if( (RcvedChar == '\b') || ((RcvedChar == (char)127)) )
//		{	/* Key BackSpace Value is 127 from minicom */
//			/* Backspace was pressed.  Erase the last character in the
//			string - if any. */
//			if( cInputIndex > 0 )
//			{
//				cInputIndex--;
//				cInputString[ cInputIndex ] = '\0';
//				/* ease one char on the uart console */
//				
//				test_printf(1,"\b");
//				test_printf(1," ");
//				test_printf(1,"\b");
//			}
//		}
//		else
//		{
//			/* A character was entered.  Add it to the string
//			entered so far.  When a \n is entered the complete
//			string will be passed to the command interpreter. */
//			if( ( RcvedChar >= ' ' ) && ( RcvedChar <= '~' ) )
//			{
//				/* Echo the character back. */
//				test_printf(1,"%c",RcvedChar);
//
//				if( cInputIndex < cmdMAX_INPUT_SIZE )
//				{
//					cInputString[ cInputIndex ] = RcvedChar;
//					cInputIndex++;
//				}
//			}
//		}
//	}
//}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************


test_uart.c

//*****************************************************************************
// file		: test_uart.c
// process data communication with test
// Copyright (c) 2006-2012 HUAWEI co. Ltd. All rights reserved
//
// Change Logs:
// Date				Author		Note
// 2013/08/27    	chc
//
//*****************************************************************************

//*****************************************************************************
//
//! \addtogroup test
//! @{
//
//*****************************************************************************
#include "test_uart.h"
//#include "MX51\MX51Uart.h"
//#include "McuConfig_PinAssign.h"
//#include "driverlib\clock.h"
//#include "driverlib\uart.h"
//#include "platform\vectors.h"
#include "ringbuf.h"
#include "stm32f10x_usart.h"
#include "stm32f10x.h"


#define TEST_TXD_BUF_LEN					100



//
//! receive buffer struct
//
typedef struct
{
    unsigned char buf[TEST_RCV_BUF_LEN];	/**< store the received data */
    unsigned char cnt;						/**< receive data count */
    unsigned char len;						/**< packet length */
    unsigned char state;					/**< receive state */
    unsigned char timeout;					/**< check if has timeout */
}
tTestRxBuf;

//
//! send buffer struct
//
typedef struct
{
    unsigned char buf[TEST_TXD_BUF_LEN];	/**< store the transmitted data */
    unsigned char num;						/**< number of byte to send */
    unsigned char cnt;						/**< number of byte has sent */
}
tTestTxBuf;

//
//! define receive buffer
//
static tTestRxBuf sTestRcvBuf;

//
//! define tx buffer
//
static tTestTxBuf sTestTxdBuf;

//
//! store the data to upper layer
//
tTestComBuf TestRcvBuf[TEST_RCV_NUM];

//
//! tx ringbuf
//
tRingBuf s_tx_ringbuf;

unsigned char AutoTestFlag = 0;


//
//! tx buffer space
//
unsigned char tx_buf[TX_RINGBUF_SIZE];

/**
  * \brief
  *
  * \param None
  *
  * \return None
  */
void test_uart_init(void)
{
//    vector_SetIrq(ICR_LINT1, ILM_Level_5);
//    vector_SetIrq(ICR_LINR1, ILM_Level_5);
	  bsp_init(115200);


//    UART_Open(1,
//              BR_115200,
//              DATA_LEN_8BIT,
//              STOP_BIT_1,
//              PARITY_NONE);
//
//    UART_SetRxInterrupt(1, 1);
    ringbuf_init(&s_tx_ringbuf, tx_buf, TX_RINGBUF_SIZE);
}

/**
  * \brief
  *
  * \param None
  *
  * \return None
  */
unsigned char test_uart_send(unsigned char *pData, unsigned char len)
{
    if (ringbuf_free(&s_tx_ringbuf) < len)
    {
        return 0;
    }

    //UART_SetTxInterrupt(1, 0);
    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    ringbuf_write(&s_tx_ringbuf, pData, len);
	//UART_SetTxInterrupt(1, 1);
	USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
}

/**
  * \brief
  *
  * \param None
  *
  * \return None
  */
int test_uart_checkbuf(unsigned char state)
{
    int i;

    for (i = 0; i < TEST_RCV_NUM; i++)
    {
        if (TestRcvBuf[i].newflag == state)
        {
            return i;
        }
    }

    return -1;
}

/**
  * \brief
  *
  * \param None
  *
  * \return None
  */
void test_uart_bufset(unsigned char idx, unsigned char state)
{
    TestRcvBuf[idx].newflag = state;
}

/**
  * \brief
  *
  * \param None
  *
  * \return None
  */
void test_uart_fillbuf(unsigned char *pSrc, unsigned char len, unsigned char idx)
{
    unsigned char i;

    for (i = 0; i < len; i++)
    {
        TestRcvBuf[idx].buf[i] = pSrc[i];
    }

    TestRcvBuf[idx].newflag = 1;
}

/**
  * \brief
  *
  * \param None
  *
  * \return None
  */
unsigned char * test_uart_getbuf(unsigned char idx)
{
    unsigned char *pBuf;

    pBuf = TestRcvBuf[idx].buf;
    return pBuf;
}

/**
  * \brief
  *
  * \param None
  *
  * \return None
  */
//__interrupt void test_rcv_isr(void)
//{
//    unsigned char rb;
//
//    sTestRcvBuf.timeout	= 5;
//
//    if(UART1_SSR1_ORE == 1 || UART1_SSR1_FRE == 1 || UART1_SSR1_PE == 1)
//    {
//        UART1_SCR1_CRE = 1;
//    }
//    else
//    {
//        rb = UART1_RDR1;
//		
//        switch(sTestRcvBuf.state)
//        {
//        case 0: // head flag check
//            if(rb == 0xAA)
//            {
//                AutoTestFlag = 1; // auto test command
//                sTestRcvBuf.state = 1;
//                sTestRcvBuf.cnt = 0;
//                sTestRcvBuf.buf[sTestRcvBuf.cnt++] = rb;
//            }
//	     else
//     	     {
//     	         AutoTestFlag = 0;
//     	     }
//            break;
//
//        case 1: 		// Frame Counter
//            //airRcvPnt		=	0;
//            sTestRcvBuf.buf[sTestRcvBuf.cnt++] = rb;
//            sTestRcvBuf.state = 2;
//            break;
//
//        case 2: 		//package length
//            if(sTestRcvBuf.cnt < TEST_RCV_BUF_LEN)
//            {
//                sTestRcvBuf.buf[sTestRcvBuf.cnt++] = rb;
//            }
//            else		// package's length is too long
//            {
//                sTestRcvBuf.state = 0;
//            }
//
//            if(rb <= (TEST_RCV_BUF_LEN - 3))
//            {
//                sTestRcvBuf.state = 3;
//            }
//            else
//            {
//                sTestRcvBuf.state = 0;
//            }
//            break;
//
//        case 3: 		// data field
//        
//            sTestRcvBuf.buf[sTestRcvBuf.cnt++] = rb;
//            if(sTestRcvBuf.cnt >= (sTestRcvBuf.buf[2] + 3)) 	//check sum
//            {
//                int bufIdx =test_uart_checkbuf(0);
//
//                if(bufIdx >= 0)
//                {
//                    test_uart_fillbuf(sTestRcvBuf.buf, sTestRcvBuf.buf[2]+3, bufIdx);
//                }
//                sTestRcvBuf.timeout =	0;//Õý³£½ÓÊÕÕýÈ·
//                sTestRcvBuf.state	=	0;
//                sTestRcvBuf.cnt 	=	0;
//            }
//            break;
//
//        default:
//            sTestRcvBuf.state = 0;
//            break;
//        }
//	if(AutoTestFlag != 1) // filter 0x0A and 0x0D
//	{
//		GetShellDada(rb);
//	}
//    }
//}

/**
  * \brief
  *
  * \param None
  *
  * \return None
  */
//__interrupt void test_snd_isr(void)
//{
//    if (ringbuf_empty(&s_tx_ringbuf))
//    {
//        UART_SetTxInterrupt(1, 0);
//    }
//    else
//    {
//        UART1_TDR1 = ringbuf_read_one(&s_tx_ringbuf);
//    }
//}

void USART1_IRQHandler(void)
{
	if (ringbuf_empty(&s_tx_ringbuf))
    {
        //UART_SetTxInterrupt(1, 0);
		USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    }
    else
    {
        //UART1_TDR1 = ringbuf_read_one(&s_tx_ringbuf);
        if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
        {
			USART_SendData(USART1, ringbuf_read_one(&s_tx_ringbuf));
		}
    }
}


/**
  * \brief
  *
  * \param None
  *
  * \return None
  */
void test_rcv_timeout_process(void)
{
    if(sTestRcvBuf.timeout > 0)
    {
        sTestRcvBuf.timeout--;

        if(sTestRcvBuf.timeout == 1)
        {
            sTestRcvBuf.state = 0;
            sTestRcvBuf.cnt = 0;
            sTestRcvBuf.timeout	=	0;
        }
    }
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************

led.c

#include "led.h"

//	 
//±¾³ÌÐòÖ»¹©Ñ§Ï°Ê¹Óã¬Î´¾­×÷ÕßÐí¿É£¬²»µÃÓÃÓÚÆäËüÈκÎÓÃ;
//ALIENTEK mini¢SSTM32¿ª·¢°å
//LEDÇý¶¯´úÂë	   
//ÕýµãÔ­×Ó@ALIENTEK
//¼¼ÊõÂÛ̳:www.openedv.com
//ÐÞ¸ÄÈÕÆÚ:2012/9/2
//°æ±¾£ºV1.0
//°æȨËùÓУ¬µÁ°æ±Ø¾¿¡£
//Copyright(C) ¹ãÖÝÊÐÐÇÒíµç×ӿƼ¼ÓÐÏÞ¹«Ë¾ 2009-2019
//All rights reserved									  
// 	   

//³õʼ»¯PB5ºÍPE5ΪÊä³ö¿Ú.²¢Ê¹ÄÜÕâÁ½¸ö¿ÚµÄʱÖÓ		    
//LED IO³õʼ»¯


注意:主函数位于uartsend_use_int.c。先bsp_init,然后就可以调用test_printf了,岂不妙哉,不占用宝贵的cpu资源。

五、后记

本文章简要记录基于stm32单片机实现串口非阻塞打印的的全过程,并附带图片以及代码片。因为时间和篇幅有限,秉着开源的精神,特此把代码工程的压缩包一并上传。防止有同学移植困难,解压缩直接编译。在csdn搜索“使用非阻塞方式实现串口打印,stm32f103rct6”,这个资源下载设置的0积分。如果找不到,发函qp_linux_mcu@163.com.有感兴趣的欢迎留言、转发、评论收藏。QQ:1066312378欢迎技术交流合作,you know。

————————————————
版权声明:本文为CSDN博主「qp_12」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qp_12/article/details/117264618

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32F103RCT6是一款微控制器,具有串口模块和空闲中断功能。串口空闲中断是指在接收数据后,在数据总线上的一个字节时间内,没有接收到数据时触发的中断。这个中断可以用来检测是否接收完整的数据帧或者判断是否有新的数据到达。通过使用串口空闲中断,可以实现高效的数据接收和处理。 在使用STM32F103RCT6的串口DMA空闲中断接收数据时,可以使用DMA(直接内存访问)功能来实现数据的传输。DMA可以在不依赖CPU的情况下,直接在外设和内存之间进行数据传输,提高了数据传输的效率和性能。而且通过修改对应的宏定义,可以方便地修改串口的设置,使得串口的配置更加灵活和方便。 同时,STM32F103RCT6还可以输出到不同的时钟信号,如HCLK、FCLK和SDIOCLK等。这些时钟信号可以用于控制和同步其他外设的工作,如存储器控制器等。因此,在使用STM32F103RCT6的串口空闲中断时,可以通过设置时钟信号来满足不同的应用需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [stm32f103rct6最小系统原理图](https://blog.csdn.net/weixin_39618806/article/details/111737621)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [STM32F103USART+DMA收发空闲中断方式 - 副本.zip](https://download.csdn.net/download/xu_bk/11660640)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值