1. 程式人生 > >給android裝置增加串列埠功能

給android裝置增加串列埠功能

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

給android裝置增加串列埠功能


本文部落格連結:http://blog.csdn.net/jdh99,作者:jdh,轉載請註明.


環境:

主機:WIN7

開發環境:MDK4.23


功能:

開啟Android手機或者平臺的藍芽,通過藍芽連線藍芽轉串列埠板,通過藍芽轉串列埠板的串列埠與需要除錯的串列埠裝置相連


說明:

1.PCB為我同學hunter繪製,他同時是stm32的高手,感謝他提供的支援.

2.製作了一個藍芽轉串列埠的板子,Android裝置連線上這個板子,就相當於增加了一個串列埠.

3.微控制器選用的是STM32F101C8,藍芽模組選用的是HC05.HC05本身就是一個藍芽轉串列埠模組,再增加一個微控制器的作用是可以通過微控制器來配置波特率等引數.

4.藍芽轉串列埠板可以用MINI USB來供電,或者用3.7V鋰電池來供電,板子上帶有充電管理晶片,由於沒鋰電池,充電這塊還沒有測試.

5.上位機程式(Android上的串列埠助手)暫時沒有時間寫,可以在安卓市場上搜索"藍芽串列埠"下一個串列埠助手.

6.在上位機發送指定格式可以配置波特率,例:AT+BAUD9600END


實物圖:



電路圖:

第1部分:

圖片較大,部分沒有顯示.可以在新視窗開啟圖片來看到全部內容

第2部分:


下位機程式:

public.h

#ifndef _PUBLIC_H_#define _PUBLIC_H_//公共標頭檔案#include "main.h"#include "string.h"#include "stdlib.h"#include
"stm32f10x_tim.h"
//巨集定義#define U8 unsigned char#define U16 unsigned short#define U32 unsigned long//藍芽轉串列埠的快取長度#define LEN_BT_STACK  10//藍芽波特率設定命令#define BT_BAUD_4800 "AT+UART=4800,0,0"#define BT_BAUD_9600    "AT+UART=9600,0,0"#define BT_BAUD_19200 "AT+UART=19200,0,0"#define BT_BAUD_38400 "AT+UART=38400,0,0"#define BT_BAUD_57600 "AT+UART=57600,0,0"#define BT_BAUD_115200 "AT+UART=115200,0,0"#define DEFAULT_BAUD 9600//定義flash頁大小#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || (STM32F10X_CL) || defined (STM32F10X_XL)  #define FLASH_PAGE_SIZE    ((uint16_t)0x800)  #define FLASH_PAGES_TO_BE_PROTECTED (FLASH_WRProt_Pages12to13 | FLASH_WRProt_Pages14to15)  #else  #define FLASH_PAGE_SIZE    ((uint16_t)0x400)  //需要關閉防寫的頁面  #define FLASH_PAGES_TO_BE_PROTECTED (FLASH_WRProt_Pages60to63)  #endif//定義操作的flash的始末地址63K-64K  #define BANK1_WRITE_START_ADDR  ((uint32_t)0x0800FC00)#define BANK1_WRITE_END_ADDR    ((uint32_t)0x08010000)//資料結構//通過藍芽發過來的串列埠2的資料堆疊//資料結構為迴圈佇列,讀寫緩衝#define LEN_BUF 512struct _FIFO_Stack{ unsigned char buf[LEN_BUF]; short ptr_r; short ptr_w;};//資料流式符合字串頭檢索#define LEN_MATCH_STRING_HEADER 9struct _match_string_header{ char match[LEN_MATCH_STRING_HEADER]; int state;};//資料流式符合字串尾檢索,並提取資料結構#define LEN_MATCH_STRING_TAIL 3struct _match_string_tail{ char match[LEN_MATCH_STRING_TAIL]; int state;    //當前狀態/下標 int value;    //最後取得的值 int max_len;   //資料最大長度 char capture_string[10]; int capture_index;  //當前捕獲資料下標 struct _match_string_header match_string_header; //用來比較尾是否正確 int flag;    //捕獲資料狀態或是捕獲字元尾狀態};//修改flashstruct _edit_flash{ unsigned short buf[512]; int flag;  //判斷flash是否被修改過 int baud;  //需要寫入/讀出的波特率};//公共變數//宣告串列埠結構體extern USART_InitTypeDef USART_InitStructure;//宣告FIFO堆疊給UART2使用extern struct _FIFO_Stack fifo_uart2;//宣告FIFO堆疊給UART1使用extern struct _FIFO_Stack fifo_uart1;//宣告修改flash結構體extern struct _edit_flash edit_flash;//公共函式//按照藍芽轉串列埠的格式傳送指令void send_bt_cmd(char *str);//迴圈緩衝方法//初始化void init_fifo_stack(struct _FIFO_Stack *stack);//讀取全部//成功返回位元組數,失敗返回-1short read_all_fifo_stack(struct _FIFO_Stack *stack,unsigned char *buf);//寫入1個位元組//失敗返回-1,成功返回1int write_byte_fifo_stack(struct _FIFO_Stack *stack,unsigned char byte);//資料流式符合字串頭檢索方法//初始化//成功返回1,失敗返回0int init_match_string_header(struct _match_string_header *m_str,char *buf);//返回-1失敗,返回0正在執行,返回1成功int match_string_header_state(struct _match_string_header *m_str,char ch);//資料流式符合字串尾檢索,並提取資料結構方法//初始化//成功返回1,失敗返回0int init_match_string_tail(struct _match_string_tail *m_str,char *buf,int max_len);//返回-1失敗,返回0正在執行,成功返回得到的資料int match_string_tail_state(struct _match_string_tail *m_str,char ch);//flash操作//開啟需要操作頁面的防寫void open_write_lock();//向flash中寫入資料,1024位元組,512個半字//成功返回寫入的位元組數,失敗返回-1int write_flash(unsigned short *buf);//讀取flash,讀取1024位元組,512半字//成功返回讀取的位元組數,失敗返回-1int read_flash(unsigned short *buf);//讀取flash,獲得flag和baud//成功返回波特率,失敗返回-1int read_baud(struct _edit_flash *edit);//寫入波特率到flash//成功返回1,失敗返回0int write_baud(struct _edit_flash *edit,int baud);#endif

public.c:

#include "public.h"//公共變數//定義串列埠結構體USART_InitTypeDef USART_InitStructure;//宣告FIFO堆疊給UART2使用struct _FIFO_Stack fifo_uart2;//宣告FIFO堆疊給UART1使用struct _FIFO_Stack fifo_uart1;//宣告修改flash結構體struct _edit_flash edit_flash;//按照藍芽轉串列埠的格式傳送指令void send_bt_cmd(char *str)while(*str != '\0') {   USART_SendData(USART2,*str++); //傳送一位資料  while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET){} //等待字元傳送完畢  } USART_SendData(USART2,'\r'); //傳送一位資料 while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET){} //等待字元傳送完畢 USART_SendData(USART2,'\n'); //傳送一位資料 while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET){} //等待字元傳送完畢  }//迴圈緩衝方法//初始化void init_fifo_stack(struct _FIFO_Stack *stack)stack->ptr_r = 0stack->ptr_w = 0memset(stack->buf,0,LEN_BUF);}//讀取全部//成功返回位元組數,失敗返回0short read_all_fifo_stack(struct _FIFO_Stack *stack,unsigned char *buf)short i = 0short j = 0short len = 0short len2 = 0//如果已經讀完,則不讀 if (stack->ptr_r - stack->ptr_w == 0 || \  stack->ptr_r - stack->ptr_w == -1) {   return -1; } //如果讀指標小於寫指標 if (stack->ptr_r < stack->ptr_w) {  len =  stack->ptr_w - stack->ptr_r;   for (i = 0;i < len;i++)  {     buf[i] = stack->buf[stack->ptr_r++];  }  return len; } else {   //讀指標大於寫指標的情況  len = (LEN_BUF - 1) - stack->ptr_r + 1;  len2 = stack->ptr_w;     for (i = 0;i < len;i++)  {    buf[j++] = stack->buf[stack->ptr_r++];   }  stack->ptr_r = 0;  for (i = 0;i < len2;i++)  {    buf[j++] = stack->buf[stack->ptr_r++];   }  return (len + len2); }}//寫入1個位元組//失敗返回-1,成功返回1int write_byte_fifo_stack(struct _FIFO_Stack *stack,unsigned char byte)//如果已經寫完,則不寫 if (stack->ptr_w - stack->ptr_r == -1) {   return -1; } stack->buf[stack->ptr_w++] = byte; //判斷是否已經寫滿 if (stack->ptr_w == LEN_BUF) {   stack->ptr_w = 0; }}//資料流式符合字串頭檢索方法//初始化//成功返回1,失敗返回0int init_match_string_header(struct _match_string_header *m_str,char *buf)int len = 0int i = 0;  len = strlen(buf); if (len > LEN_MATCH_STRING_HEADER) {  return 0; }  m_str->state = 0for (i = 0;i < len;i++) {  m_str->match[i] = buf[i]; } m_str->match[i] = '\0';  return 1;}//返回-1失敗,返回0正在執行,返回1成功int match_string_header_state(struct _match_string_header *m_str,char ch)if (ch == m_str->match[m_str->state]) {  m_str->state++;  if (m_str->match[m_str->state] == '\0')  {   m_str->state = 0;      return 1;  }  else  {   return 0;  } } else {  m_str->state = 0;    return -1; }}//資料流式符合字串尾檢索,並提取資料結構方法//初始化//成功返回1,失敗返回0int init_match_string_tail(struct _match_string_tail *m_str,char *buf,int max_len)int len = 0int i = 0;  len = strlen(buf); if (len > LEN_MATCH_STRING_TAIL) {  return 0; }  m_str->state = 0; m_str->value = 0; m_str->max_len = max_len; m_str->capture_index = 0; m_str->flag = 0for (i = 0;i < len;i++) {  m_str->match[i] = buf[i]; } m_str->match[i] = '\0'; init_match_string_header(&(m_str->match_string_header),m_str->match);  return 1;}//返回-1失敗,返回0正在執行,成功返回得到的資料int match_string_tail_state(struct _match_string_tail *m_str,char ch)int flag = 0;  //判斷是否捕獲資料狀態還是捕獲字元尾狀態 if (m_str->flag || ch == 'E') {  //捕獲字元尾狀態  m_str->flag = 1;  flag = match_string_header_state(&(m_str->match_string_header),ch);    if (flag == -1)  {   //初始化資料   m_str->state = 0;   m_str->capture_index = 0;   m_str->flag = 0;  }    if (flag == 1)  {   m_str->capture_string[m_str->capture_index] = '\0';   m_str->value = atoi(m_str->capture_string);      //初始化資料   m_str->state = 0;   m_str->capture_index = 0;   m_str->flag = 0;      return m_str->value;  }    return flag; } else {  //捕獲資料狀態  if (ch < '0' || ch > '9')  {   return -1;  }    //當已經達到最大資料長度且當前資料不是  //當不是資料字元返回錯誤  if (m_str->capture_index >= m_str->max_len)  {   m_str->state = 0;   m_str->capture_index = 0;   m_str->flag = 0;      return -1;  }  else  {   m_str->capture_string[m_str->capture_index++] = ch;      //如果達到最大長度,則置為捕獲字元狀態   if (m_str->capture_index >= m_str->max_len)   {    m_str->flag = 1;   }      return 0;  } }}//開啟需要操作頁面的防寫void open_write_lock()uint32_t WRPR_Value = 0xFFFFFFFF, ProtectedPages = 0x0volatile FLASH_Status FLASHStatus = FLASH_COMPLETE; //解鎖flash控制器 FLASH_Unlock(); //得到所有已經被防寫的頁面號,如果被防寫則置0,沒有則置1 WRPR_Value = FLASH_GetWriteProtectionOptionByte(); //需要防寫的頁面置1,不需要的置0 ProtectedPages = ~(WRPR_Value | FLASH_PAGES_TO_BE_PROTECTED);  //檢查需要的頁是否被防寫 if((WRPR_Value | (~FLASH_PAGES_TO_BE_PROTECTED)) != 0xFFFFFFFF ) {  //擦除小資訊模組,關閉防寫  FLASHStatus = FLASH_EraseOptionBytes();    //如果不是所有頁面都需要開啟防寫  if(ProtectedPages != 0x0)  {    //將其他頁面置位防寫    FLASHStatus = FLASH_EnableWriteProtection(ProtectedPages);  }  //復位系統,重新載入小資訊  NVIC_SystemReset(); }}//向flash中寫入資料,1024位元組,512個半字//成功返回寫入的位元組數,失敗返回-1int write_flash(unsigned short *buf)uint32_t EraseCounter = 0x0,Address = 0x0uint32_t WRPR_Value = 0xFFFFFFFFuint32_t NbrOfPage; volatile FLASH_Status FLASHStatus = FLASH_COMPLETE; int i = 0//得到需要操作的頁面數 NbrOfPage = (BANK1_WRITE_END_ADDR - BANK1_WRITE_START_ADDR) / FLASH_PAGE_SIZE; //得到所有已經被防寫的頁面號,如果被防寫則置0,沒有則置1 WRPR_Value = FLASH_GetWriteProtectionOptionByte();  //判斷此頁面是否被防寫,如果沒有防寫則進行操作 if ( (WRPR_Value & FLASH_PAGES_TO_BE_PROTECTED) != 0x00) {  //清除所有等待標誌位  FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP|FLASH_FLAG_PGERR |FLASH_FLAG_WRPRTERR);     //擦數指定頁面  for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)  {    FLASHStatus = FLASH_ErasePage(BANK1_WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));  }    //得到操作flash的起始地址  Address = BANK1_WRITE_START_ADDR;  //寫flash,每次寫2個位元組  while((Address < BANK1_WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))  {   FLASHStatus = FLASH_ProgramHalfWord(Address, buf[i++]);   Address = Address + 2;  }  return i; } else {   return -1; }}//讀取flash,讀取1024位元組,512半字//成功返回讀取的位元組數,失敗返回-1int read_flash(unsigned short *buf)uint32_t Address = 0x0int i = 0//得到操作flash的起始地址 Address = BANK1_WRITE_START_ADDR; //讀flash,每次讀兩個位元組 while((Address < BANK1_WRITE_END_ADDR)) {  buf[i++] = *(__IO uint16_t*) Address;  Address += 2; } return i;}//修改flash結構的方法//初始化void init_edit_flash(struct _edit_flash *edit){   edit->flag = 0; edit->baud = 0memset(edit->buf,0,512);}//讀取flash,獲得flag和baud//成功返回波特率,失敗返回-1int read_baud(struct _edit_flash *edit){ read_flash(edit->buf); edit->flag = edit->buf[0]; edit->baud = edit->buf[1] << 16; edit->baud += edit->buf[2]; if (edit->flag == 0xa5) {   return (edit->baud); } else {   return -1; }}//寫入波特率到flash//成功返回1,失敗返回0int write_baud(struct _edit_flash *edit,int baud){ edit->buf[0] = 0xa5; edit->buf[1] = baud >> 16; edit->buf[2] = baud & 0xffffif (write_flash(edit->buf) > 0) {  edit->flag = 0xa5;  edit->baud = baud;   return 1; } else {   return 0; }}
stm32f10x_it.c:(串列埠中斷檔案)

/**  ******************************************************************************  * @file    SysTick/stm32f10x_it.c   * @author  MCD Application Team  * @version V3.4.0  * @date    10/15/2010  * @brief   Main Interrupt Service Routines.  *          This file provides template for all exceptions handler and peripherals  *          interrupt service routine.  ******************************************************************************  * @copy  *  * 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>© COPYRIGHT 2010 STMicroelectronics</center></h2>  */ /* Includes ------------------------------------------------------------------*/#include "stm32f10x_it.h"#include "main.h"#include "public.h"/** @addtogroup STM32F10x_StdPeriph_Examples  * @{  *//** @addtogroup SysTick  * @{  *//* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*//* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*//* Private function prototypes -----------------------------------------------*//* Private functions ---------------------------------------------------------*//******************************************************************************//*            Cortex-M3 Processor Exceptions Handlers                         *//******************************************************************************//**  * @brief  This function handles NMI exception.  * @param  None  * @retval None  */void NMI_Handler(void){}/**  * @brief  This function handles Hard Fault exception.  * @param  None  * @retval None  */void HardFault_Handler(void)/* Go to infinite loop when Hard Fault exception occurs */  while (1)  {  }}/**  * @brief  This function handles Memory Manage exception.  * @param  None  * @retval None  */void MemManage_Handler(void)/* Go to infinite loop when Memory Manage exception occurs */  while (1)  {  }}/**  * @brief  This function handles Bus Fault exception.  * @param  None  * @retval None  */void BusFault_Handler(void)/* Go to infinite loop when Bus Fault exception occurs */  while (1)  {  }}/**  * @brief  This function handles Usage Fault exception.  * @param  None  * @retval None  */void UsageFault_Handler(void)/* Go to infinite loop when Usage Fault exception occurs */  while (1)  {  }}/**  * @brief  This function handles SVCall exception.  * @param  None  * @retval None  */void SVC_Handler(void){}/**  * @brief  This function handles Debug Monitor exception.  * @param  None  * @retval None  */void DebugMon_Handler(void){}/**  * @brief  This function handles PendSV_Handler exception.  * @param  None  * @retval None  */void PendSV_Handler(void){}/**  * @brief  This function handles SysTick Handler.  * @param  None  * @retval None  */void SysTick_Handler(void){  TimingDelay_Decrement();}/******************************************************************************//*                 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).                                            *//******************************************************************************//**  * @brief  This function handles PPP interrupt request.  * @param  None  * @retval None  *//*void PPP_IRQHandler(void){}*//**  * @}  */ /**  * @}  */    //串列埠1接收中斷 //與真實串列埠通訊 void USART1_IRQHandler(void)                              {  unsigned char rx_dat;        if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)       //判斷髮生接收中斷  {   USART_ClearITPendingBit(USART1,    USART_IT_RXNE);          //清除中斷標誌   rx_dat = USART_ReceiveData(USART1);                        //接收資料,整理除去前兩位   //寫入fifo   write_byte_fifo_stack(&fifo_uart1,rx_dat);  } }//返回src中dst字串的標號,正確返回標號,失敗返回-1//src:源字串//dst:目標字串//len:源字串比較的長度int index_of_string(char *src,char *dst,int len)int size_dst = 0int i = 0int j = 0;  //獲得目標字串長度 size_dst = strlen(dst); //如果len小於目標字串長度,返回失敗 if (len < size_dst) {  return 0; }  for (i = 0;i <= len - size_dst;i++) {  for (j = 0;j < size_dst;j++)  {   if (src[i + j] != dst[j])   {    break;   }  }  if (j == size_dst)  {   return i;  } }  return -1;}//串列埠2接收中斷//與藍芽串列埠模組通訊void USART2_IRQHandler(void)                             unsigned char rx_dat;      if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)       //判斷髮生接收中斷 {  //清除中斷標誌  USART_ClearITPendingBit(USART2,    USART_IT_RXNE);         //接收資料     rx_dat = USART_ReceiveData(USART2);                          //寫入fifo  write_byte_fifo_stack(&fifo_uart2,rx_dat); }}/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/

main.c:(主檔案)

/*   功能:藍芽轉串列埠模組   作者:jdh 時間:2012-2-27 */#include "public.h"static __IO uint32_t TimingDelay;//定義GPIO結構體GPIO_InitTypeDef GPIO_InitStructure;/* Private function prototypes -----------------------------------------------*/void Delay(__IO uint32_t nTime);//初始化內部晶振static void RCC_Config(void)//將外設 RCC暫存器重設為預設值  RCC_DeInit();  //內部晶振使能  RCC_HSICmd(ENABLE);  //使能外部晶振  //SystemInit();  //等待工作穩定  while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);  if(1)  {    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);    FLASH_SetLatency(FLASH_Latency_2); //高速時鐘    RCC_HCLKConfig(RCC_SYSCLK_Div1);    RCC_PCLK2Config(RCC_HCLK_Div1);    RCC_PCLK1Config(RCC_HCLK_Div2);    //設定 PLL 時鐘源及倍頻係數    RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);    //使能或者失能 PLL,這個引數可以取:ENABLE或者DISABLE    RCC_PLLCmd(ENABLE);//如果PLL被用於系統時鐘,那麼它不能被失能    //等待指定的 RCC 標誌位設定成功 等待PLL初始化成功    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);    //設定系統時鐘(SYSCLK) 設定PLL為系統時鐘源    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);    //等待PLL成功用作於系統時鐘的時鐘源    //  0x00:HSI 作為系統時鐘     //  0x04:HSE作為系統時鐘     //  0x08:PLL作為系統時鐘      while(RCC_GetSYSCLKSource() != 0x08);  }} //設定串列埠波特率void set_uart_baud(int num,int baud)if (num == 1) {  //更新串列埠波特率  USART_Cmd(USART1,DISABLE);  USART_InitStructure.USART_BaudRate = baud;  USART_Init(USART1,&USART_InitStructure);  USART_Cmd(USART1, ENABLE); } if (num == 2) {  //更新串列埠波特率  USART_Cmd(USART2,DISABLE);  USART_InitStructure.USART_BaudRate = baud;  USART_Init(USART2,&USART_InitStructure);  USART_Cmd(USART2, ENABLE); }}//初始化void init()//定義中斷結構體 NVIC_InitTypeDef NVIC_InitStructure; //初始化結構體   GPIO_StructInit(&GPIO_InitStructure); //初始化uart2的接收fifo init_fifo_stack(&fifo_uart2); //初始化uart1的接收fifo init_fifo_stack(&fifo_uart1);  //中斷NVIC設定:允許中斷,設定優先順序  NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;    //更新事件  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //搶佔優先順序0  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;          //響應優先順序1  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允許中斷  NVIC_Init(&NVIC_InitStructure);                             //寫入設定   //RCC_Config(); //開啟串列埠對應的外設時鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);  //初始化引數 USART_InitStructure.USART_BaudRate = DEFAULT_BAUD; 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; //初始化串列埠 USART_Init(USART1,&USART_InitStructure); //初始化引數 USART_InitStructure.USART_BaudRate = DEFAULT_BAUD; USART_Init(USART2,&USART_InitStructure); //TXE傳送中斷,TC傳輸完成中斷,RXNE接收中斷,PE奇偶錯誤中斷,可以是多個  USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); USART_ITConfig(USART2,USART_IT_RXNE,ENABLE); //配置UART1中斷 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;    //通道設定為串列埠1中斷 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //中斷佔先等級0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;              //中斷響應優先順序0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //開啟中斷 NVIC_Init(&NVIC_InitStructure);                                 //初始化 //配置UART2中斷 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;    //通道設定為串列埠1中斷 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //中斷佔先等級0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;              //中斷響應優先順序0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //開啟中斷 NVIC_Init(&NVIC_InitStructure);                                 //初始化 //啟動串列埠 USART_Cmd(USART1, ENABLE);  USART_Cmd(USART2, ENABLE);  //設定IO口時鐘   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);   //串列埠1的管腳初始化      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                       //管腳9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;                //選擇GPIO響應速度 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //複用推輓輸出    GPIO_Init(GPIOA, &GPIO_InitStructure);                          //TX初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                      //管腳10 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;       //選擇GPIO響應速度 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    //浮空輸入    GPIO_Init(GPIOA, &GPIO_InitStructure);                          //RX初始化       //設定IO口時鐘   //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);   //串列埠2的管腳初始化      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                       //管腳9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;                //選擇GPIO響應速度 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //複用推輓輸出    GPIO_Init(GPIOA, &GPIO_InitStructure);                          //TX初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;                      //管腳10 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;       //選擇GPIO響應速度 GPIO_InitStru