使用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日

相关文章

  • C语言实现爆炸展开的扫雷详解

    C语言实现爆炸展开的扫雷详解 什么是扫雷游戏? 扫雷是一款非常经典的单机游戏,也是Windows操作系统自带的经典小游戏之一。在游戏中,玩家需要打开一个地图,为了避免触雷,需要根据数字提示来判断周围的方块是否是地雷,最终将地图上的所有地雷都标记出来。 怎么实现爆炸展开? “爆炸展开”是扫雷游戏中非常重要的一步,也是难度比较大的一部分。如果一个方块周围没有地雷…

    C 2023年5月23日
    00
  • QT设计秒表功能(跑步计时器)

    下面是关于QT设计秒表功能的完整攻略: 准备工作 安装QT开发环境 打开QT Creator,新建一个Qt Widgets Application项目 实现步骤 在项目中添加两个 Label 控件,一个用于显示当前计时的时间,另一个用于显示跑步时间,并设置好它们的位置和大小。 添加两个按钮,一个用于开始/暂停计时,另一个用于清零并停止计时。 对按钮和 Lab…

    C 2023年5月22日
    00
  • 荣耀畅玩8c手机如何录屏?荣耀畅玩8c录屏教程

    针对您的问题,“荣耀畅玩8c手机如何录屏?荣耀畅玩8c录屏教程”,我为您提供以下完整攻略,希望能帮到您。 荣耀畅玩8c手机录屏 荣耀畅玩8c手机自带录屏功能,可以通过系统自带工具实现录屏。 步骤: 打开手机,确保进入主界面。 打开需要录制的APP,例如微信或者游戏。 下拉状态栏,点击“录屏”按钮,开始录屏。 在录制期间,可以进行操作,并进行操作演示。 可以在…

    C 2023年5月23日
    00
  • Python列表嵌套常见坑点及解决方案

    下面就是对“Python列表嵌套常见坑点及解决方案”的详细讲解。 1. 什么是Python列表嵌套? Python中的列表是一种可以存储多个元素的数据结构,而列表嵌套则是指把一个或多个列表作为元素存储在另一个列表中。例如,以下是一个简单的列表嵌套的示例: nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 以上示例…

    C 2023年5月22日
    00
  • C语言 按值函数调用

    C语言 按值函数调用 在 C 语言中,函数可以按值调用(也称为传值调用)或按引用调用(也称为传引用调用)。 按值调用函数时,函数会使用参数的值进行计算,并在函数中对其进行修改不会影响原始值。 下面是一个按值调用的例子: #include <stdio.h> // 定义一个函数,输入两个整数并返回它们的和 int add(int a, int b)…

    C 2023年5月9日
    00
  • C语言内存分布与heap空间分别详细讲解

    针对这个问题,我根据如下步骤进行讲解: 1. C语言内存分布 C语言是一种直接操作内存的语言,因此内存管理对于程序的运行效率和安全性都非常重要。C语言内存分布主要包括以下几个部分: 栈区(Stack) 栈区相对于堆区来说是一块连续的内存地址,在程序运行时自动分配和释放。栈区主要用于函数调用和参数传递。每调用一个函数时,都会在栈区中创建一个函数帧,存储函数的参…

    C 2023年5月23日
    00
  • js获取客户端操作系统类型的方法【测试可用】

    js获取客户端操作系统类型的方法【测试可用】 在Web开发中,有时需要根据客户端的操作系统类型来做一些不同的处理,比如适配不同的用户界面或者加载不同的资源文件。JavaScript提供了一些方法来获取客户端的操作系统类型,本文将详细阐述这些方法。 通过userAgent属性获取操作系统信息 在HTTP请求头中包含了一个User-Agent信息,它描述了请求的…

    C 2023年5月23日
    00
  • C++ Qt利用GPU加速计算的示例详解

    标题:C++ Qt利用GPU加速计算的示例详解 简介 本文将介绍使用C++和Qt框架实现使用GPU加速计算的方法。我们将介绍以下内容: 如何正确配置开发环境。 如何利用CUDA实现GPU加速。 如何使用Qt界面实现数据输入和结果展示。 开发环境配置 在开始之前,我们需要正确配置开发环境。首先,我们需要安装NVIDIA的GPU驱动和CUDA工具包。 驱动安装:…

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