使用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 就是一旦出现这个问题就是这个错误

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

相关推荐
范纹杉想快点毕业3 小时前
ZYNQ7045芯片中UART实现RS422通信详解,50000字解析,C语言,嵌入式开发,软件开发
c语言·笔记·stm32·单片机·嵌入式硬件·mcu·fpga开发
与你诗画3 小时前
电路中的 ”CT“
单片机·嵌入式硬件
沐欣工作室_lvyiyi5 小时前
基于单片机的盲人智能水杯(论文+源码)
单片机·嵌入式硬件·物联网·毕业设计·智能水杯
brave and determined5 小时前
硬件-电容学习DAY20——从零到精通的电容实战指南
单片机·嵌入式硬件·滤波·储能·硬件设计·电路设计·电容核心功能
是大强6 小时前
嵌入式开发中用于调试的技术Semihosting
单片机·嵌入式硬件
RaLi和夕7 小时前
嵌入式学习笔记4.STM32中断系统及外部中断EXTI
笔记·stm32·单片机·学习
瓢儿菜20187 小时前
【Proteus8.17仿真】 STM32仿真 0.96OLED 屏幕显示ds1302实时时间
stm32·单片机·嵌入式硬件
10001hours7 小时前
(基于江协科技)51单片机入门:8.DS1302
科技·嵌入式硬件·51单片机
充哥单片机设计7 小时前
【STM32项目开源】基于STM32的工地环境监测系统
stm32·单片机·嵌入式硬件