STM32利用KEIL5實現(xiàn)無實物串口收發(fā)實驗

  • 文章背景:學(xué)習(xí)到STM32裸板開發(fā)中的串口收發(fā)實驗,苦于沒錢買開發(fā)板,現(xiàn)在的電腦也鮮有自帶串口的,所以想著能否空手套白狼,直接利用KEIL5在線完成仿真。沒想到還確實有辦法!
  • 所需軟件
    • 1 KEIL5
    • 虛擬串口:VSPD
    • 虛擬串口調(diào)試器SSCOM
  • 實驗?zāi)康?/strong>:在KEIL5中完成基于STM32F103開發(fā)板的程序編寫,達到PC機利用串口向開發(fā)板發(fā)送字符串,開發(fā)板通過串口收到數(shù)據(jù)后,再將其原封不動的發(fā)回PC的目的。

1、下載并安裝VSPD(Virtual Serial Port Driver)備用

  • 下載鏈接:
  • 軟件界面:按照下載壓縮包文件的要求完成安裝和破解(建議安裝7.2之前的版本,網(wǎng)上流傳的的較新版本破解不完美,使用了幾天后就提示can not pair port不能使用了),安裝完畢后如下圖所示:
mg-febwq62J-16330591293

]

  • 使用方法

    • 1 選擇 列表中出現(xiàn) 的串口 組對 (只顯示還沒有使用的)
    • 2 點擊 按鈕 Add pair 創(chuàng)建 串口 組對
    • 3 剛創(chuàng)建的 組對 出現(xiàn)在 Virtual ports之下
    • 4 串口列表中,不再有它倆的組對(上圖顯示的即為創(chuàng)建的COM1和COM2串口對)
    • 5 可以在“控制面板”--“設(shè)備管理器”驗證 剛創(chuàng)建成功的虛擬串口 組對
    image-20210930220926122

創(chuàng)建成功后,就可以像物理串口一樣去使用它們。一端使用你的程序打開虛擬串口COM1, 另一端使用 串口助手 打開虛擬串口COM2。 因為 虛擬串口COM2和 COM1是相互關(guān)聯(lián)的一對,所以, 從COM2發(fā)送的數(shù)據(jù),COM1將會接收到, 反之 從COM1發(fā)送的數(shù)據(jù), COM2將會接收到,這樣就可以方便地調(diào)試你的程序了 。

創(chuàng)建后的虛擬串口將會一直存在, 如果不再使用,可以刪除它們。(先在左側(cè)選擇要刪除的串口對,而后右側(cè)點擊按鈕 Delete pair 刪除。刪除串口對后設(shè)備管理器中也將沒有它們。

2、程序編寫

  • 創(chuàng)建工程文件夾Usart,并建立CMSIS、FWLib、User三個文件夾:

    • 復(fù)制STM32Fx標(biāo)準(zhǔn)外設(shè)庫(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\CMSIS\CM3\CoreSupport\中的core_cm3.ccore_cm3.h這2個文件到Usart\CMSIS\中;
    • 復(fù)制STM32Fx標(biāo)準(zhǔn)外設(shè)庫(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\中的stm32f10x.h、system_stm32f10x.c、system_stm32f10x.h3個文件到Usart\CMSIS\中;
    • 復(fù)制STM32Fx標(biāo)準(zhǔn)外設(shè)庫(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\中的arm文件夾到Usart\CMSIS\StartUp\中;
    • 復(fù)制STM32Fx標(biāo)準(zhǔn)外設(shè)庫(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\STM32F10x_StdPeriph_Driver\中的incsrc兩個文件夾到Usart\FWLib\中;
    • 復(fù)制STM32Fx標(biāo)準(zhǔn)外設(shè)庫(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\Project\STM32F10x_StdPeriph_Template\中的stm32f10x_conf.h、stm32f10x_it.c、stm32f10x.h、main.c、system_stm32f10x.c這幾個文件復(fù)制到Usart\User\中;
  • 打開KEIL5,點擊Project—new uVision Project,選擇剛才建立的Usart文件夾,為工程創(chuàng)建工程名Usart后,點擊保存后,建立工程(選擇STM32F103RB開發(fā)板)。

  • 在左側(cè)工程樹中,右擊Target 1,選擇Manerge Project Items

(img-0QBgkUR8-1633059129318)
  • 為Target1建立FWLIB、STARTUP、CMSIS、USER四個組,并分別添加如下文件:
    • FWLIB中添加Usart\FWLib\src\中的所有文件;
    • STARTUP中添加3種類型的板子的啟動文件:startup_stm32f10x_hd.s,startup_stm32f10x_md.s,startup_stm32f10x_ld.s;
    • CMSIS中添加core_cm3.c文件;
    • USER中添加Usart\User中的所有文件。
image-20210930232306465
  • 配置目標(biāo)工程1:左側(cè)結(jié)構(gòu)樹下右擊Target1,選擇Option for Target選項,選擇C\C++選項卡,如圖所示定義兩個預(yù)處理符號:USE_STDPERIPH_DRIVER,STM32F10X_MD

  • img-juvWdMC6-1633059129325
  • 配置目標(biāo)工程2:設(shè)置頭文件搜索路徑。選擇C\C++選項卡,如圖所示定義3個搜索路徑:.\CMSIS;.\FWlib\inc;.\User:

  • 633059129327
  • 編輯main.c函數(shù),構(gòu)建USART收發(fā)主函數(shù):

  • /*
      ******************************************************************************
      * @file    main.c 
      * @author  Leon
      * @version V1.0
      * @date    2021-9-28
      * @brief   PC send data to STM32 with USART, then STM32 send the data back to PC
      ******************************************************************************
    */  
    
    /* Includes ------------------------------------------------------------------*/
    #include "stm32f10x.h"
    #include <stdio.h>
    
    /* Private typedef -----------------------------------------------------------*/
    
    /* Private define ------------------------------------------------------------*/
    
    /* Private macro -------------------------------------------------------------*/
    
    /* Private variables ---------------------------------------------------------*/
    
    /* Private function prototypes -----------------------------------------------*/
    void RCC_Configuration(void);
    void GPIO_Configuration(void);
    void USART_Configuration(void);
    /* Private functions ---------------------------------------------------------*/
    
    /**
      * @brief  Main program.
      * @param  None
      * @retval None
      */
    int main(void)
    {
      vu16 i = 0;
      RCC_Configuration();
        GPIO_Configuration();
      USART_Configuration();
      
      while(1){
          /*Wait for USART1 to receive over*/
          if(USART_GetFlagStatus(USART1, USART_IT_RXNE) == SET){
              /* Send data received to USART1 */
              USART_SendData(USART1, USART_ReceiveData(USART1));
              /* Short delay */
              for(i = 0; i<500; i++);
              //while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);                           
          }
      }
    }
    
    /**
      * @brief  RCC configuration program, enable USART and GPIOA.
      * @param  None
      * @retval None
      */
    void RCC_Configuration(void)
    {
      ErrorStatus HSEStartUpStatus;
      RCC_DeInit();
      RCC_HSEConfig(RCC_HSE_ON);
      HSEStartUpStatus = RCC_WaitForHSEStartUp();
      
      if(HSEStartUpStatus == SUCCESS)
      {
          RCC_HCLKConfig(RCC_SYSCLK_Div1);
          RCC_PCLK2Config(RCC_HCLK_Div1);
          RCC_PCLK1Config(RCC_HCLK_Div2);
          FLASH_SetLatency(FLASH_Latency_2);
          FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
          /* PLL CLK Source is HSE, Mull 9, PLL = 8M * 9 = 72M */
          RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
          RCC_PLLCmd(ENABLE);
          while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
          RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
          while(RCC_GetSYSCLKSource() != 0x8);
      }
      
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
    }
    
    /**
      * @brief  Config USATR1 Pin which Tx(GPIOA.9), Rx(GPIOA.10).
      * @param  None
      * @retval None
      */
    void GPIO_Configuration(void)
    {
      GPIO_InitTypeDef GPIO_InitStructure;
      
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOA, &GPIO_InitStructure);
      
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(GPIOA, &GPIO_InitStructure);
    }
    
    /**
      * @brief  Config USART1(Baund=9600, DataLen=8,StopBit=1, No ECC,)
                Disable USART CLK, CLK Polar low, Catch data at second edage
              LastBit clk not from SCLK.
      * @param  None
      * @retval None
      */
    void USART_Configuration(void)
    {
      USART_InitTypeDef USART_InitStructure;
      USART_ClockInitTypeDef USART_ClockInitStructure;
      
      USART_InitStructure.USART_BaudRate = 9600;
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
      USART_InitStructure.USART_Parity = USART_Parity_No;
      USART_InitStructure.USART_StopBits = USART_StopBits_1;
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
      USART_Init(USART1, &USART_InitStructure);
      
      USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
      USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
      USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
      USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
      USART_ClockInit(USART1, &USART_ClockInitStructure);
      
      USART_Cmd(USART1, ENABLE);
    }
    
    /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
    
  • 輯配置文件stm32f10x_conf.h,使能工程用到的GPIO、RCC、USART、FLASH模塊:

  • /**
      **************************************************************************** 
      * @file    stm32f10x_conf.h 
      * @author  leon
      * @version V1.0
      * @date    2021/9/18
      * @brief   Library configuration file.
      ******************************************************************************
      * @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>
      ******************************************************************************
      */
    
    /* Define to prevent recursive inclusion -------------------------------------*/
    #ifndef __STM32F10x_CONF_H
    #define __STM32F10x_CONF_H
    
    /* Includes ------------------------------------------------------------------*/
    /* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */
    //#include "stm32f10x_adc.h"
    //#include "stm32f10x_bkp.h"
    //#include "stm32f10x_can.h"
    //#include "stm32f10x_cec.h"
    //#include "stm32f10x_crc.h"
    //#include "stm32f10x_dac.h"
    //#include "stm32f10x_dbgmcu.h"
    //#include "stm32f10x_dma.h"
    //#include "stm32f10x_exti.h"
    #include "stm32f10x_flash.h"
    //#include "stm32f10x_fsmc.h"
    #include "stm32f10x_gpio.h"
    //#include "stm32f10x_i2c.h"
    //#include "stm32f10x_iwdg.h"
    //#include "stm32f10x_pwr.h"
    #include "stm32f10x_rcc.h"
    //#include "stm32f10x_rtc.h"
    //#include "stm32f10x_sdio.h"
    //#include "stm32f10x_spi.h"
    //#include "stm32f10x_tim.h"
    #include "stm32f10x_usart.h"
    //#include "stm32f10x_wwdg.h"
    //#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
    
    /* Exported types ------------------------------------------------------------*/
    /* Exported constants --------------------------------------------------------*/
    /* Uncomment the line below to expanse the "assert_param" macro in the 
       Standard Peripheral Library drivers code */
    /* #define USE_FULL_ASSERT    1 */
    
    /* Exported macro ------------------------------------------------------------*/
    #ifdef  USE_FULL_ASSERT
    
    /**
      * @brief  The assert_param macro is used for function's parameters check.
      * @param  expr: If expr is false, it calls assert_failed function which reports 
      *         the name of the source file and the source line number of the call 
      *         that failed. If expr is true, it returns no value.
      * @retval None
      */
      #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
    /* Exported functions ------------------------------------------------------- */
      void assert_failed(uint8_t* file, uint32_t line);
    #else
      #define assert_param(expr) ((void)0)
    #endif /* USE_FULL_ASSERT */
    
    #endif /* __STM32F10x_CONF_H */
    
    /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
    
    
  • 中斷處理函數(shù)文件stm32f10x_it.c不用修改,因為本程序中未使用到中斷。

  • 點擊編譯按鈕(Rebuilde:編譯工程下的所有文件;Builde:編譯當(dāng)前文件),使之達到error 0,warning 0 的編譯結(jié)果。

  • image-20210930235422693

3、KEIL中關(guān)于串口的設(shè)置

  • 1 創(chuàng)建調(diào)試初始化的ini文件

在Keil uVision5開發(fā)工具的文件夾 D:\Keil_v5之下新建一個配置文件map_com.ini(利用txt文檔建立后更改后綴為ini),內(nèi)容為:

MODE COM1 9600,0,8,1
ASSIGN COM1 <S1IN> S1OUT

意思為:將 COM1 設(shè)置為 9600 波特率,無奇偶校驗,8 位數(shù)據(jù)位,1位停止位(要和KEIL工程中程序里設(shè)置的一致)。這是針對ARM系列的。但如果是C51的開發(fā)板,上述配置文件的第二行的<SIN>和SOUT就不需要添加數(shù)字了,因為一般C51只有一個串口,不需要利用數(shù)字來區(qū)分是開發(fā)板上的哪一個串口。

  • 將KEIL軟件仿真器的串口映射到 COM1(加載配置文件)

    • 1)在 Keil 軟件內(nèi),點擊菜單的 Project -- Options for Target(Alt+F7),或者工具條的【配置選型】圖標(biāo)

      2)點選 Debug 選項頁, 點選 左上側(cè)的 Use simulator

      3)Initialization File 框之后的 ... 按鈕,選擇 初始化文件 map_com.ini , 點擊 打開 -- OK 返回。

    img-o7U5GpqU-1633059129331

4、啟動調(diào)試

  • 先點 菜單 Debug -- Start/Stop Debug Session(Ctrl+F5) , 再點 Debug -- Run(F5) 或者工具條上的 Debug ,進入調(diào)試界面,然后點擊工具條上的全速運行,啟動調(diào)試運行。
img-pALvVWxw-1633059719773
  • 打開串口調(diào)試助手,選擇COM2(因為我們KEIL里設(shè)置的開發(fā)板上使用的串口為COM1,之前已經(jīng)通過虛擬串口驅(qū)動VSPD建立了COM1和COM2的連接,所以串口間才可以相互發(fā)送數(shù)據(jù))

  • image-20210930235959423
  • 在菜單欄“端口號“中選擇COM2(注意:波特率一定要是 9600,與程序映射的 COM1 保持一致),而后點擊打開串口。之后會如上圖顯示

  • 在右下角文本輸入框中,輸入字符A,并點擊發(fā)送,可在輸出窗口中看到接收到的字符A

  • img-vHPRBqza-1633059129
  • 可以在KEIL中打開USART1串口觀察窗,查看由PC機發(fā)給STM32的數(shù)據(jù)

  • mg-gV2ThQX4-163305912
  • 具體查看端口信息

    • 菜單 Peripherals -- General Purpose I/O -- GPIO
    • 在 GPIO ODR 右側(cè),可以看到 按實際電平,具體位的 勾選與否。
    33059129337
  • 邏輯分析儀查看端口的圖形顯示

    • 點擊工具欄 的 啟動調(diào)試 -- 邏輯分析儀 -- Logic Analyzer -- Setup... -- 新加圖標(biāo)
    • 輸入 PORTE.6 , 選擇 Bit ,就可以查看其電平變化的以及求得時差
  • mg-GMzfZhV0-163305912

5、實物下載

當(dāng)你有實際的開發(fā)板和調(diào)試線(USB轉(zhuǎn)串口驅(qū)動)的時候,又怎么實現(xiàn)程序的下載和調(diào)試呢?

  • 利用**st-link 調(diào)試線 **
    • 安裝驅(qū)動程序后,連接設(shè)備與計算機,點擊菜單的 Project -- Options for Target
    • 1) 在 Debug 選項頁
      • (1)勾選右側(cè)的 Use ST-Link Debugger
      • (2) 點擊 Setting 按鈕
      • (3) 在 Debug選項頁的 選擇 ort: SW Max:1.8MHz
      • (4) 在 Flash Download 選項頁
        • 勾選 Program, Verify, Reset and Run
        • 選擇 STM32F10x High-density... 512k
    • 2) 在 Utilities 選項頁
      • 勾選 Use Debug Driver
      • 勾選 Update Target before Debugging
    • 3)點擊 工具欄的 load 圖標(biāo),即可下載
D1oEenha-16330591293
  • 利用USB轉(zhuǎn)串口線
    • 1) 下載安裝 CH340驅(qū)動(USB串口驅(qū)動)_XP_WIN7共用驅(qū)動程序
    • 2) 使用USB線連接設(shè)備,下載啟動 FlyMcu 下載工具
    • 3)點擊菜單上的 搜索串口,找到COMx:空閑的USB-SERIAL CH340 (自己的線)
    • 4)點擊 按鈕 ... ,找到生成的 .hex 文件
    • 5)點擊 開始編程, 直到完成即可。
mg-MdOYtHca-16330591293
  • 以上就是利用KEIL5完成STM編程、調(diào)試和下載的所有有實物和無實物的編程調(diào)試辦法。需要注意的是我們在線仿真調(diào)試好的程序可能和程序下載到實際板子上進行運行的結(jié)果不同,原因在于仿真時候速度比較慢,而實際運行速度比較快,所以如有需要可以在適當(dāng)語句后面加入延時函數(shù)來解決速度匹配問題。

參考資料:無實物Keil軟件仿真與串口助手的聯(lián)機調(diào)試吳超新浪博客 (sina.com.cn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容