STM32利用KEIL5实现无实物串口收发实验

  • 文章背景:学习到STM32裸板开发中的串口收发实验,苦于没钱买开发板,现在的电脑也鲜有自带串口的,所以想着能否空手套白狼,直接利用KEIL5在线完成仿真。没想到还确实有办法!
  • 所需软件
    • 1 KEIL5
    • 虚拟串口:VSPD
    • 虚拟串口调试器SSCOM
  • 实验目的:在KEIL5中完成基于STM32F103开发板的程序编写,达到PC机利用串口向开发板发送字符串,开发板通过串口收到数据后,再将其原封不动的发回PC的目的。

1、下载并安装VSPD(Virtual Serial Port Driver)备用

  • 下载链接:
  • 软件界面:按照下载压缩包文件的要求完成安装和破解(建议安装7.2之前的版本,网上流传的的较新版本破解不完美,使用了几天后就提示can not pair port不能使用了),安装完毕后如下图所示:
mg-febwq62J-16330591293

]

  • 使用方法

    • 1 选择 列表中出现 的串口 组对 (只显示还没有使用的)
    • 2 点击 按钮 Add pair 创建 串口 组对
    • 3 刚创建的 组对 出现在 Virtual ports之下
    • 4 串口列表中,不再有它俩的组对(上图显示的即为创建的COM1和COM2串口对)
    • 5 可以在“控制面板”--“设备管理器”验证 刚创建成功的虚拟串口 组对
    image-20210930220926122

创建成功后,就可以像物理串口一样去使用它们。一端使用你的程序打开虚拟串口COM1, 另一端使用 串口助手 打开虚拟串口COM2。 因为 虚拟串口COM2和 COM1是相互关联的一对,所以, 从COM2发送的数据,COM1将会接收到, 反之 从COM1发送的数据, COM2将会接收到,这样就可以方便地调试你的程序了 。

创建后的虚拟串口将会一直存在, 如果不再使用,可以删除它们。(先在左侧选择要删除的串口对,而后右侧点击按钮 Delete pair 删除。删除串口对后设备管理器中也将没有它们。

2、程序编写

  • 创建工程文件夹Usart,并建立CMSIS、FWLib、User三个文件夹:

    • 复制STM32Fx标准外设库(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\CMSIS\CM3\CoreSupport\中的core_cm3.ccore_cm3.h这2个文件到Usart\CMSIS\中;
    • 复制STM32Fx标准外设库(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\中的stm32f10x.h、system_stm32f10x.c、system_stm32f10x.h3个文件到Usart\CMSIS\中;
    • 复制STM32Fx标准外设库(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\中的arm文件夹到Usart\CMSIS\StartUp\中;
    • 复制STM32Fx标准外设库(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\STM32F10x_StdPeriph_Driver\中的incsrc两个文件夹到Usart\FWLib\中;
    • 复制STM32Fx标准外设库(STM32F10x_StdPeriph_Lib_V3.5.0)中的Libraries\Project\STM32F10x_StdPeriph_Template\中的stm32f10x_conf.hstm32f10x_it.cstm32f10x.hmain.csystem_stm32f10x.c这几个文件复制到Usart\User\中;
  • 打开KEIL5,点击Project—new uVision Project,选择刚才建立的Usart文件夹,为工程创建工程名Usart后,点击保存后,建立工程(选择STM32F103RB开发板)。

  • 在左侧工程树中,右击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
  • 配置目标工程1:左侧结构树下右击Target1,选择Option for Target选项,选择C\C++选项卡,如图所示定义两个预处理符号:USE_STDPERIPH_DRIVER,STM32F10X_MD

  • img-juvWdMC6-1633059129325
  • 配置目标工程2:设置头文件搜索路径。选择C\C++选项卡,如图所示定义3个搜索路径:.\CMSIS;.\FWlib\inc;.\User:

  • 633059129327
  • 编辑main.c函数,构建USART收发主函数:

  • /*
      ******************************************************************************
      * @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****/
    
    
  • 中断处理函数文件stm32f10x_it.c不用修改,因为本程序中未使用到中断。

  • 点击编译按钮(Rebuilde:编译工程下的所有文件;Builde:编译当前文件),使之达到error 0,warning 0 的编译结果。

  • image-20210930235422693

3、KEIL中关于串口的设置

  • 1 创建调试初始化的ini文件

在Keil uVision5开发工具的文件夹 D:\Keil_v5之下新建一个配置文件map_com.ini(利用txt文档建立后更改后缀为ini),内容为:

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

意思为:将 COM1 设置为 9600 波特率,无奇偶校验,8 位数据位,1位停止位(要和KEIL工程中程序里设置的一致)。这是针对ARM系列的。但如果是C51的开发板,上述配置文件的第二行的<SIN>和SOUT就不需要添加数字了,因为一般C51只有一个串口,不需要利用数字来区分是开发板上的哪一个串口。

  • 将KEIL软件仿真器的串口映射到 COM1(加载配置文件)

    • 1)在 Keil 软件内,点击菜单的 Project -- Options for Target(Alt+F7),或者工具条的【配置选型】图标

      2)点选 Debug 选项页, 点选 左上侧的 Use simulator

      3)Initialization File 框之后的 ... 按钮,选择 初始化文件 map_com.ini , 点击 打开 -- OK 返回。

    img-o7U5GpqU-1633059129331

4、启动调试

  • 先点 菜单 Debug -- Start/Stop Debug Session(Ctrl+F5) , 再点 Debug -- Run(F5) 或者工具条上的 Debug ,进入调试界面,然后点击工具条上的全速运行,启动调试运行。
img-pALvVWxw-1633059719773
  • 打开串口调试助手,选择COM2(因为我们KEIL里设置的开发板上使用的串口为COM1,之前已经通过虚拟串口驱动VSPD建立了COM1和COM2的连接,所以串口间才可以相互发送数据)

  • image-20210930235959423
  • 在菜单栏“端口号“中选择COM2(注意:波特率一定要是 9600,与程序映射的 COM1 保持一致),而后点击打开串口。之后会如上图显示

  • 在右下角文本输入框中,输入字符A,并点击发送,可在输出窗口中看到接收到的字符A

  • img-vHPRBqza-1633059129
  • 可以在KEIL中打开USART1串口观察窗,查看由PC机发给STM32的数据

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

    • 菜单 Peripherals -- General Purpose I/O -- GPIO
    • 在 GPIO ODR 右侧,可以看到 按实际电平,具体位的 勾选与否。
    33059129337
  • 逻辑分析仪查看端口的图形显示

    • 点击工具栏 的 启动调试 -- 逻辑分析仪 -- Logic Analyzer -- Setup... -- 新加图标
    • 输入 PORTE.6 , 选择 Bit ,就可以查看其电平变化的以及求得时差
  • mg-GMzfZhV0-163305912

5、实物下载

当你有实际的开发板和调试线(USB转串口驱动)的时候,又怎么实现程序的下载和调试呢?

  • 利用**st-link 调试线 **
    • 安装驱动程序后,连接设备与计算机,点击菜单的 Project -- Options for Target
    • 1) 在 Debug 选项页
      • (1)勾选右侧的 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 图标,即可下载
D1oEenha-16330591293
  • 利用USB转串口线
    • 1) 下载安装 CH340驱动(USB串口驱动)_XP_WIN7共用驱动程序
    • 2) 使用USB线连接设备,下载启动 FlyMcu 下载工具
    • 3)点击菜单上的 搜索串口,找到COMx:空闲的USB-SERIAL CH340 (自己的线)
    • 4)点击 按钮 ... ,找到生成的 .hex 文件
    • 5)点击 开始编程, 直到完成即可。
mg-MdOYtHca-16330591293
  • 以上就是利用KEIL5完成STM编程、调试和下载的所有有实物和无实物的编程调试办法。需要注意的是我们在线仿真调试好的程序可能和程序下载到实际板子上进行运行的结果不同,原因在于仿真时候速度比较慢,而实际运行速度比较快,所以如有需要可以在适当语句后面加入延时函数来解决速度匹配问题。

参考资料:无实物Keil软件仿真与串口助手的联机调试吴超新浪博客 (sina.com.cn)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容