使用STM32CubeMX创建新的工程,使用vscode进行编码和调试

一.软件准备

1.STM32CubeMX

生成我们所需要的工程文件

2.STM32CubeCLT

包含cmake等工具包

3.Vscode

对代码进行修改和编写

二.操作过程

首先我们打开STM32CubeMX

在搜索框里面输入STM32F103C8T6这个使我们第一块接触的芯片

双击进入到它的里面

这里我们设置Debug模式

设置成Serial Wire模式,也就是我们常说的SWD模式

具体有关这个模式可以看这个文章深入理解 ARM Serial Wire Debug (SWD) 协议_swd协议-CSDN博客

左键这个芯片图选择芯片的输出模式

这里为了简化我就初始化六个引脚

从上图上可以看出我们的PA6,PA7,PB0被初始化成输出引脚

而我们的PA8,PB15,PB14被初始化成输入引脚

我们可以从输入引脚获取输入信号,例如使用按键控制LED灯,按键就是输入信号

这个是比较简单的

点击这个创建工具生成我们的HAL库代码,在这个里面就完成标准库的初始化

比如我们可能在标准库里写

cpp 复制代码
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
	//使用各个外设前必须开启时钟,否则对外设的操作无效
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;					//定义结构体变量
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		//GPIO模式,赋值为推挽输出模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;				//GPIO引脚,赋值为第6和第7号引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//GPIO速度,赋值为50MHz
	
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//将赋值后的构体变量传递给GPIO_Init函数                                  
                                             //函数内部会自动根据结构体的参数配置相应寄存器
												//实现GPIOA的初始化

大概就这这一大堆东西他直接给你写好

然后进入

之后弹出这个直接关闭就行

然后我们进入VScode (如果第一次使用vscode安装Chinese中文包)

在vscode中新建一个配置环境

点击小齿轮

安装STM32Cube for vscode

和c/c++ Extension Pack 和c/c++ Themes

还有CMake工具

然后进入源码

main就是我们标准库中的主函数

找下面的路径

这个就是他给我们生成的代码文件

我们可以发现他给我们初始化好了GPIO

我们可以从这个函数中看出来 MX_GPIO_Init中

objectivec 复制代码
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* USER CODE BEGIN MX_GPIO_Init_1 */

  /* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);

  /*Configure GPIO pins : PA6 PA7 */
  GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PB0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PB14 PB15 */
  GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN MX_GPIO_Init_2 */

  /* USER CODE END MX_GPIO_Init_2 */
}

在main中的while(1)中写逻辑

点击下面那个生成就生成工程文件了,就可以烧录到我们的STM32F103C8T6上了

但是这个里面我发现下面的代码

objectivec 复制代码
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

这个在标准库里面是没有见过的

__disable_irq(); 禁止所有中断

while(1){

} 如果出现错误将会停在这里

但是这里有引入一个新的概念,什么是句柄Handle,什么时候调用句柄,是我们自己调用还是系统自动调用。

在源码中我看到这里调用了句柄

objectivec 复制代码
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

这段代码中调用了这个句柄

看出这个应该是我们自己调用的,而不是系统判断自己调用的

那这个句柄和函数有啥区别呢

在deepseek中我了解到

句柄相当于这个引用type & error 就是一旦出现这个问题就是这个错误

而且句柄在这个函数中有唯一性

相关推荐
许商4 小时前
【stm32】【Freertos】config详解(1)
stm32·单片机·嵌入式硬件
普中科技4 小时前
【普中DSP28335开发攻略】-- 第 7 章 F28335时钟及控制系统
单片机·嵌入式硬件·时钟·dsp28335·普中科技
IT_阿水8 小时前
RA-Eco-RA4M2之RTC电子钟
单片机·嵌入式硬件·实时音视频
清风66666612 小时前
基于单片机的水塔液位检测与智能调节报警系统设计
数据库·单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
某zhuan13 小时前
STM32中PB4引脚作普通GPIO使用的一个小问题
stm32·单片机·嵌入式硬件
Caesar Zou15 小时前
ssh远程连接服务器,vscode不显示claude
服务器·vscode·ssh
点灯小铭16 小时前
基于单片机的人体红外传感的步进电机调速自动门智能控制系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
一月千帆16 小时前
STM32 串口 Bootloader 固件升级方案实现
stm32·单片机·嵌入式硬件
朱嘉鼎17 小时前
GPIO引脚操作方法概述
单片机·嵌入式硬件
JoannaJuanCV19 小时前
vscode debug Transformer源码说明
ide·vscode·transformer·qwen3