为什么不使用稚晖君的Clion编辑器方案呢?因为VSCode不仅支持C/C++,还支持Python等其他语言,是微软旗下开源的编辑器;Clion是Jetbrains旗下的C/C++编辑器,且Clion需要版权收费(建议大家尽量支持正版,开发人员付出了很多,有兴趣的小伙伴可以“绿色使用”)。
前几天将VSCode+ Keil Assistant插件的环境搭建完成后,发现这种环境不能实现在VSCode调试和自由选择下载方式(J-link/ST-link/CMSIS-DAPlink),还得切回到Keil IDE。
因此最近又想搭建一套完整的基于VSCode的HAL库环境【大家可以参考这个视频链接搭建,手把手地教会你,VSCode编辑+GCC for ARM交叉编译工具链+Make构建工具+OpenOCD调试(基于STM32CubeMX的HAL库)】,我这边的环境已经搭建完成。
但是出现了一个问题:自己创建了1个文件夹,加入串口初始化的.c和.h文件,然后在main.c中调用 USART1_Init(); 函数
附上usart1.c、usart1.h源码文件:
usart1.c:
#include "usart1.h"
UART_HandleTypeDef huart1;
/*************************************************************************************************
* 函 数 名: HAL_UART_MspInit
* 入口参数: huart - UART_HandleTypeDef定义的变量,即表示定义的串口
* 返 回 值: 无
* 函数功能: 初始化串口引脚
* 说 明: 无
*************************************************************************************************/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (huart->Instance == USART1)
{
__HAL_RCC_USART1_CLK_ENABLE(); // 开启 USART1 时钟
GPIO_USART1_TX_CLK_ENABLE; // 开启 USART1 TX 引脚的 GPIO 时钟
GPIO_USART1_RX_CLK_ENABLE; // 开启 USART1 RX 引脚的 GPIO 时钟
GPIO_InitStruct.Pin = USART1_TX_PIN; // TX引脚
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出
GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 速度等级
HAL_GPIO_Init(USART1_TX_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USART1_RX_PIN; // RX引脚
HAL_GPIO_Init(USART1_RX_PORT, &GPIO_InitStruct);
}
}
/*************************************************************************************************
* 函 数 名: USART1_Init
* 入口参数: 无
* 返 回 值: 无
* 函数功能: 初始化串口配置
* 说 明: 无
*************************************************************************************************/
void USART1_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = USART1_BaudRate;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
while (HAL_UART_Init(&huart1) != HAL_OK)
{
}
}
usart1.h:
#ifndef __USART1_H
#define __USART1_H
#include <stdio.h>
#include "stm32f1xx_hal.h"
/*-------------------------------------------- USART配置宏 ---------------------------------------*/
#define USART1_BaudRate 115200
#define USART1_TX_PIN GPIO_PIN_9 // TX 引脚
#define USART1_TX_PORT GPIOA // TX 引脚端口
#define GPIO_USART1_TX_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE() // TX 引脚时钟
#define USART1_RX_PIN GPIO_PIN_10 // RX 引脚
#define USART1_RX_PORT GPIOA // RX 引脚端口
#define GPIO_USART1_RX_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE() // RX 引脚时钟
/*---------------------------------------------- 函数声明 ---------------------------------------*/
void USART1_Init(void); // USART1初始化函数
#endif
编译build的时候显示报错了,未定义`HAL_UART_Init’这个HAL库函数。
排查问题步骤
排查点一、stm32f1xx_hal_conf.h头文件中,相关串口模块的使能宏定义已经打开
排查点二、我又去STM32CubeMX自动生成的Makefile文件里面查看C_SOURCES,已经引入了自己创建的源文件(注意,源文件是引入到具体的.c文件,头文件是包含相对路径,和keil MDK的UI形式引入和包含一样)
排查点三、继续在Makefile文件中查看C_INCLUDES,也包含了自己创建的头文件的相对路径和自动包含了stm32f1xx_hal_uart.h的相对路径
排查点四、引入stm32f1xx_hal_uart.c源文件(排查到了,在这里成功了)
思来想去,没想到问题出在哪里……后面联想到 HAL_UART_Init 这个HAL库函数所在的源文件是否引入进去了呢?一查看,哦……原来Makefile文件里面的C_SOURCES还没有引入stm32f1xx_hal_uart.c源文件,没包含,那我们就手动引入吧,谁叫我一开始用STM32CubeMX生成HAL库工程的时候没有选择使用UART模块呢。
1)首先右键点击你想引入的源文件,然后选择复制相对路径
2)其次粘贴到Makefile文件里面的C_SOURCES的任意位置,在后面加上空格+反斜杠符号
3)最后build,查看终端,就没有报错了
好了,到这里就解决了报错未定义库函数的问题。
总结
上述报错的原因其实和Keil IDE引入源文件和包含头文件路径的思路一样,只是以前习惯了Keil的UI界面包含方式,换成Makefile方式包含,终究是有点不习惯,后面有时间还是好好学习一下Makefile的语法规则吧(立个flag!)
最后还是要重申一遍!!!!!注意,在Makefile中,源文件是引入到具体的.c文件,头文件是包含其相对路径。