使用VSCode和VS2017编译调试STM32程序的实现

使用VSCode和VS2017编译调试STM32程序的实现

本文将介绍如何使用Visual Studio Code和Visual Studio 2017编译和调试STM32程序的实现。

一、开发环境搭建

在开始之前,需要确认电脑上是否已安装以下必要的软件:

  • Visual Studio Code (简称VSCode)
  • Visual Studio 2017 (简称VS2017)
  • GNU ARM Embedded Toolchain
  • ST-Link驱动程序
  • STM32CubeMX

其中,GNU ARM Embedded Toolchain用于生成可执行二进制文件,ST-Link驱动程序用于将生成的二进制文件下载到芯片上,STM32CubeMX用于生成项目代码框架和初始化。

下载完以上软件后,需要将GNU ARM Embedded Toolchain和STM32CubeMX的路径添加到系统环境变量PATH中。例如,假如将这两个软件安装在D:\Program Files目录下,则需要将D:\Program Files\GNU Tools ARM Embedded\7 2018-q2-update\bin和D:\Program Files\STMicroelectronics\STM32Cube\STM32CubeMX\bin路径添加到环境变量PATH中。

二、创建工程

1.打开STM32CubeMX,创建一个新工程。根据实际情况选择芯片类型和工作模式,在"Project Settings"中可以进行更详细的设置。

2.完成工程配置后,点击左上角的"Generate Code"按钮生成项目代码。

3.打开VSCode,从"File"菜单中选择"Open Folder",并打开STM32CubeMX生成的代码所在的文件夹。

4.在VSCode的"Explorer"中打开".vscode"文件夹,创建"launch.json"文件。将以下代码复制粘贴到"launch.json"文件中:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug STM32",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/Debug/${workspaceFolderBasename}.elf",
            "cwd": "${workspaceFolder}",
            "externalConsole": true,
            "debugServerArgs": "-d",
            "linux": {
                "MIMode": "gdb"
            },
            "windows": {
                "MIMode": "gdb"
            },
            "pipeTransport": {
                "pipeCwd": "${workspaceFolder}",
                "pipeProgram": "C:/WinGDB/bin/wingdb-remote.exe",
                "debuggerPath": "arm-none-eabi-gdb.exe",
                "pipeArgs": ["localhost:3333"],
                "filterStderr": true,
                "filterStdout": true,
                "stopOnEntry": false,
                "showDevDebugOutput": true
            },
            "sourceFileMap": { "/mnt/c": "C:"}
        }
    ]
}

该配置文件指示VSCode使用GNU ARM Embedded Toolchain的arm-none-eabi-gdb调试器,并连接到STM32芯片,可以正常执行程序。
注意,需要将"pipeProgram"和"debuggerPath"路径修改为实际路径。

完成"launch.json"文件的编辑后,保存并关闭。

三、编写代码

在VSCode的"Explorer"中,找到"Src"文件夹下的"main.c"文件。本文以一个简单的LED闪烁程序作为示例:

#include "stm32f1xx.h"

int main(void)
{
  RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
  GPIOC->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_MODE13);
  GPIOC->CRH |= GPIO_CRH_MODE13_0;

  while (1)
  {
    GPIOC->BSRR = GPIO_BSRR_BS13;
    for (int i = 0; i < 100000; i++);
    GPIOC->BSRR = GPIO_BSRR_BR13;
    for (int i = 0; i < 100000; i++);
  }
}

该代码实现了一个LED灯的闪烁,使用了STM32F103芯片的GPIOC13引脚输出信号。

完成代码编辑后,保存并关闭。

四、编译和调试

在VSCode中按下F5,或通过"Run"菜单中的"Start Debugging"选项,启动调试。在调试面板的控制台中可以看到调试器与STM32芯片的交互信息。

如果一切正常,程序会开始在芯片上执行,并实现LED灯的闪烁。

由此可见,使用VSCode和VS2017编译调试STM32程序还是比较简单的,只需要安装好相应的软件并进行简单的配置即可。

示例1

下面给出一个简单的USART1串口输出实例,只需在STM32CubeMX中进行USART1初始化配置,然后在main函数中添加如下代码即可:

#include "stm32f1xx.h"
#include <stdio.h>

void USART1_Init(void)
{
  RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN;
  GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_MODE9 | GPIO_CRH_CNF10 | GPIO_CRH_MODE10);
  GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9 | GPIO_CRH_CNF10_0;
  USART1->BRR = 0x341; //115200@72M
  USART1->CR1 |= USART_CR1_RE | USART_CR1_TE | USART_CR1_UE;
}

int _write(int fd, char *ptr, int len)
{
  for (int i = 0; i < len; i++)
  {
    while (!(USART1->SR & USART_SR_TXE));
    USART1->DR = *ptr++;
  }

  return len;
}

int main(void)
{
  USART1_Init();

  printf("Hello, world!\n");

  while (1);
}

示例2

下面给出一个简单的I2C读写实例,只需在STM32CubeMX中进行I2C初始化配置,然后在main函数中添加如下代码即可:

#include "stm32f1xx.h"
#include <stdio.h>

void I2C_WriteByte(I2C_HandleTypeDef *hi2c, uint8_t addr, uint8_t data)
{
  while (hi2c->State != HAL_I2C_STATE_READY);
  HAL_I2C_Mem_Write(hi2c, addr, 0x00, 1, &data, 1, HAL_MAX_DELAY);
}

uint8_t I2C_ReadByte(I2C_HandleTypeDef *hi2c, uint8_t addr)
{
  uint8_t data = 0;
  while (hi2c->State != HAL_I2C_STATE_READY);
  HAL_I2C_Mem_Read(hi2c, addr, 0x00, 1, &data, 1, HAL_MAX_DELAY);
  return data;
}

int main(void)
{
  HAL_Init();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  __HAL_RCC_I2C1_CLK_ENABLE();

  I2C_HandleTypeDef hi2c1 = {0};
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }

  I2C_WriteByte(&hi2c1, 0x00, 0x01);
  uint8_t data = I2C_ReadByte(&hi2c1, 0x00);

  while (1);

  HAL_I2C_DeInit(&hi2c1);
}

至此,示例代码就讲解完毕了。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用VSCode和VS2017编译调试STM32程序的实现 - Python技术站

(1)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • Objective-C计时器NSTimer学习笔记

    没问题。下面是 “Objective-C计时器NSTimer学习笔记” 的完整攻略: 一、NSTimer概述 NSTimer 是 Foundation 框架提供的一个类,用来实现定时器的功能。使用 NSTimer 可以在程序中实现类似闹铃、计时器等功能。 二、NSTimer使用方法 2.1 创建对象 NSTimer *timer = [NSTimer sch…

    C 2023年5月23日
    00
  • javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair 解决方法总结

    首先,这个错误是由于JDK 8及以上版本中的加密协议更新导致的。要解决这个问题,有两种方法可以尝试。 方法1:强制使用TLSv1协议 这个方法非常简单,只需要在程序中强制使用TLSv1协议即可,特别是对于需要与老版本的服务器进行交互的情况,更是非常适用。 在使用HttpsURLConnection类时,可以通过如下代码强制使用TLSv1协议: System.…

    C 2023年5月22日
    00
  • java异常:异常处理–try-catch结构详解

    Java异常: 异常处理–try-catch结构详解 在Java程序中,异常处理是一个非常重要的方面。Java异常是指程序在运行期间不正常的情况。当程序出现异常时,如果没有恰当的处理,它将使程序崩溃。Java提供了异常处理机制来解决这个问题。 异常 当Java程序在运行过程中遇到了异常时,它会产生一个异常对象。Java中的异常有两种类型: 检查异常和非检查…

    C 2023年5月23日
    00
  • C语言程序环境和预处理详解分析

    C语言程序环境和预处理详解分析 1. 概述 在编写C语言程序时,为了能够在计算机上执行,需要安装对应的开发环境。C语言程序环境由编译器、链接器和运行库组成。在编写C语言程序之前,我们需要先了解预处理的概念和作用。 2. 预处理 在C语言程序中,预处理是在编译之前进行的一项工作,主要包括了宏定义、条件编译、头文件包含等等操作。预处理器会根据程序中的预处理指令,…

    C 2023年5月23日
    00
  • C语言用函数指针实现一个特别的计算器

    C语言用函数指针实现一个特别的计算器 1. 什么是函数指针 在C语言中,函数指针是指向函数的指针变量,也就是说,函数指针存储的是一个函数的地址。通过函数指针,我们可以直接调用该函数,就像调用普通变量一样,这样可以使程序更加灵活。 定义一个函数指针需要注意两点:- 函数指针的声明方式与普通指针有所不同,其声明格式为 返回类型 (*指针变量名)(参数列表);- …

    C 2023年5月23日
    00
  • 解决运行jar包出错:ClassNotFoundException问题

    解决运行jar包出现ClassNotFoundException问题的攻略如下: 确认问题和原因 在运行jar包时,如果出现ClassNotFoundException异常,常见原因可能是以下情况之一: 所需的类文件未包含在jar包中 所需的类文件包含在jar包中,但是无法正确加载 应用程序可能尝试加载未声明依赖项的类 所需的类文件在classpath中不存…

    C 2023年5月22日
    00
  • 使用python获取cpu每秒的使用率

    下面是详细讲解“使用python获取cpu每秒的使用率”的完整攻略。 1. 确认获取CPU使用率的目标平台和Python版本 在开始之前,我们需要确认我们要获取CPU使用率的平台和Python版本。因为不同的平台和Python版本可能有不同的获取方式。例如,Windows和Linux下获取CPU使用率的方式可能就不一样,Python 2.x和Python 3…

    C 2023年5月23日
    00
  • C++分析类的对象作类成员调用构造与析构函数及静态成员

    C++中,类对象也可以充当类的成员,这样的类称为分析类或组合类。在分析类的对象作为其他类的成员变量时,需要注意其构造函数、析构函数及静态成员的调用。 构造函数和析构函数的调用 当组合类的对象作为另一个类的成员时,先调用另一个类的构造函数,再调用组合类的构造函数;在调用析构函数时,先调用组合类的析构函数,再调用另一个类的析构函数。 示例1: class A {…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部