做嵌入式开发,一定对Keil、IAR不陌生,可它俩那与现代IDE格格不入的远古画风让人脑壳着实发疼。好一点的解决方案就是IAR或Keil联调VS Code,即代码在VS Code编写(调试),在IAR或Keil编译烧录。以VS Code强大而丰富的插件功能和简约优美的画面,已经使开发体验有了大幅的提升,而这里则提供另一种更为一体化的开发思路(缘于稚晖君大佬的博客)
同时由于CLion不像IAR、Keil那样有完善的嵌入式的工具链,所以手动配置工具链,流程又长又容易出错。如果某个环节没有如教程那样复现,那将会是顶级的折磨,所以要做好心理准备和取舍,这里就先祝愿大家一步到位。
需要说明的是:
1,本篇面向的是了解过HAL开发的同志,可能相当啰嗦,篇幅也较长(主要是避免以后自己看不懂),建议按需查目录。同时由于水平十分有限,难免会有一些冗余的步骤和谬误,还望指正。
2,第一次配置工程会很麻烦,不过以后配置工程时就会轻松许多,直接复制原工程再改(需要学会编写CMakelist,只是稍许麻烦哦,三行语句而已)。
3,后面会给出几个配置CLion过程中遇到的问题,解决或避免的方法都内嵌在教程里。如果你已熟稔配置流程,却仍出一些问题,可以跳到最后看看有没有可以参考的例子,
4,以下内容是基于Windows操作系统的搭建过程,若是其他操作系统,希望本篇能提供一点参考和帮助。(网页端的目录在左侧←)
5,如果你想使用C++,同时对CLion新建工程已经了然如胸,那么可以不必看这些冗余的内容,直接根据目录,跳转到目录五下的使用C++开发。
一、工具准备 ૮₍ ˃ ⤙ ˂ ₎ა
本着版本越新越好的原则(虽然实际上往往会出现各种令人不快的兼容性问题),这里的版本都尽可能地为当下最新版
CLion:2023.3.3
-> 哦吼吼~~
STM32CubeMX:6.9.0
-> 到官网下载最新版即可,不必在意有没有SW4STM32选项(6.4.0版前是有的)
MinGW:13.2
-> 这有大佬的博客可以参考,MinGW-W64 下载、安装与配置
arm-none-eabi-gcc:13.2
-> 这个必须得说明一下,之前我下载的交叉编译工具链也是2019版的,但那个实在太老还停产了,构建时提示只支持11.0及以上的,当时没注意花了一夜才搞明白。。。快点我快点我
OpenOCD:0.12.0
-> 选择下图这个压缩包Releases · xpack-dev-tools/openocd-xpack (github.com)
二、安装 ଘ(੭ˊ꒳ˋ)੭
1,安放
CLion、STM32CubeMX安装就不赘述了,其余三个解压在同一个目录下即可(忽略起错名字的父目录MinGW-64,mingw64那个好像是安装得到的,其余两个是直接解压)。
注意哈,最好改一下名字,整个路径都不要有空格、中文什么的,不然构建时可能会出现十分离谱的事情
2,配置系统Path
先依次按Ctrl+C把三个文件夹下的bin的路径复制一下
然后,正式开始配置系统Path,打开【高级系统设置】-【环境变量】-【编辑】
一定要注意的是,打开的是系统变量下的Path,而不是上面那个用户变量!!!
然后,双击空白处,按Win+V,剪贴板上就会有刚刚复制的三个路径,填入即可
填完后要按三次确定,配置完后要重启,避免识别不到系统路径
3,检验
重启后运行cmd,分别执行下面代码检验是否系统路径配置成功。如果不成功需要再检查一下前面系统变量的配置,并尝试重启,因为有时候即便过程全对也会出现识别不到的现象
arm-none-eabi-gcc -v
gcc -v
三、配置CLion (꒪⌓꒪)
1,搭好工具链
打开所有设置(如果英文不习惯,在下面的插件/Plugins里可安装中文插件Chinese什么的)
找到工具链,为了避免混乱就直接在默认的环境上配置(很容易改回去的)
a.把工具集换成自己下载的那个mingw64的目录(不需要到它的下级目录bin),其实用它绑定的也行,据说还更快一些,不过mingw-32-make生成的提示自带百分比显得更美观
b.把构建工具、C编译器、C++编译器改为自己的相应程序路径(照葫芦画瓢即可)
c.其余都不必改,以防出现不可知的错误
2,确认CMake
反正是用默认配的,工具链只有一个所以选哪个都一样。但还是换一下比较好,权当心理安慰
3,配置程序的位置
找到你自己程序的安装位置即可,按一下测试,冒绿字即可
做好这一切之后,记得按确定!!
四、创建工程 ಠ_ರೃ
1,创建项目
完成配置CLion后选择新建项目,路径和名字不要有中文!这里以创建“jk触发器”为例
2,检验初始化工程
(第一次配置工程时,最好做这一步。正常新建工程,由于工具链已配好,这一步的检验过程是可以省略的)
初始工程默认配置的是STM32F030F4PX芯片,且正常情况下一定是可以通过编译的, 这里之所以要进行这一步,就是为了确认工具链之类的是否搭好,避免后面STM32CubeMX都配好了,结果却不能编译调试的悲催情况。
配置文件先随便选一个或跳过都行,这里先随便选一个。
点击左下角那个长得像方舟的符号,再点击它旁边那个长得就像重新编译的东西,没有红字即为正常
然后点击最上面的那个小锤子,构建成功后会冒绿光且生成两个蓝色的文件,这一步很关键
(下面的窗口拉长了一点,为了方便观察)
【这一步的检验过程很长,需要很大的耐心。而且这一次只是体验一下过程,后面可能又要重新配置】
这时如果你可以配置烧录配置文件了,没有连接板子或者连接了但没安装相应仿真器驱动就直接烧录(长得像运行的那个按钮),会出现含failed的红字。
这里可以新建一个后缀名为cfg的文件,我用的是STLink(-V2),所以起名为stlink.cfg,板子是stm32f407VET6,配置如下(稚晖君那有更详尽的配置)
source [find interface/stlink.cfg]
transport select hla_swd
# 内存大小 这里我的是512kb,就是80000
set WORKAREASIZE 0x80000
# chip name 改为相应型号
set CHIPNAME STM32F407VET6
source [find target/stm32f4x.cfg]
(或有不一样,但最值得关注的是下面这三句)
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/stm32f4x.cfg]
然后改掉之前那个我们随便选的cfg文件
把这个cfg替换成我们新建的那个stlink.cfg,同时把下载改为始终(这个看个人需要),点击确定
虽然工程的芯片型号我还没改,但是依旧可以“烧进去”的。烧成功后依然是令人心颤的红字,但是很明显跟之前不一样,有了诸如flash地址、Program Finshed等更为详尽的信息,且右下角会有已下载固件的提示
3,配置工程
点击上面那个.ioc文件,可以看到这个界面,再点击通过STM32CubeMX打开
等一下STM32CubeMX就会打开,默认是这个STM32F030F4PX芯片。这里肯定要改,点击红圈位置
选择你钟意的芯片,双击即可(我这里收藏过,你可以直接在左上方第一个搜索框内搜索)
为避免后续改名字的麻烦和文件残余的问题,更换芯片后就直接配置工程,在Toolchain/IDE一栏选择STM32CubeIDE(官方文档里说过),不用考虑什么SW4STM32
然后直接按Ctrl+S,它会给个框,按保存,再点击Yes,之后就会变成下面这个了
此时回到CLion,你会发现工程配置为正确的芯片了,但左边的包还没被清掉,还冒出个红字提示(emm,这个看情况吧,更严重一点的提示是找不到资源工程什么的,反正除了第一次要一下重启CLion也没有什么实际影响,后续再配置STM32CubeMX生成代码时,会自动加载)
不过打开资源管理器,就可以看到已经清理过了
现在可以放心地重启CLion了
重启后,确定即可,反正只有一个。不放心的话,再编译构建一下看看有没有正确的消息提示
如果你前面配置过cfg,这时cfg很可能被扬了,我是说最上面那个长得像爬虫的芯片,那个绿色标志没了
那么现在就可以体验一下配置cfg的整个流程了,点进编辑或是直接点击编辑配置,到里面点击左上角添加,然后找到那个OpenOCD下载并运行
然后,更改名称,添加可执行的二进制文件,添加面板配置文件( 点击选择路径下的第三个,可以直接到项目目录里),下载选择始终
4,配置芯片
接下来就可以通过点击目录里的ioc文件,回到STM32CubeMX,是一成不变的SYS、RCC和时钟树的配置,就不赘述了
这个外部晶振一定要对照一下自己手上这块板子的原理图,尽管芯片一样,但板子上的外部晶振就不一定了,有些是25MHz、8MHz,我这里是12MHz
设置好外部晶振频率并选择好通路后,直接在右侧输入想要达到的最终频率,它会自动配好
5,导出工程代码
Toolchain /IDE 要选STM32CubeIDE
到左侧的Code Generator里,勾选那个生成“.c/h”文件的,避免生成的代码乱七八糟的
生成后就可以点击close了,然后回到CLion,接下来可能弹出一个框让你选择配置文件,如果已经配置了,那么就直接跳过。没有的话,可以参考前面(2,检验初始化工程)的配置
6,接下来,开测!
接上仿真器,点击烧录,再点击旁边那只爬虫就可以得到一堆令人畏惧的红字,最上方会变成重新调试和停止,同时仿真器也会闪闪发光。
然后就可以设置断点什么的了,至于查看寄存器svd什么的其他博客里也有
嗯~,出乎意料,这不知道怎么回事就进去Error里了 囧 ,不过能调试能连接上单片机也算是莫大的幸福了,剩下的走一步看一步了
注释掉了之后就能正常运行了???原因未知,先记录一下,方便以后按Ctrl+F可以直接定位
详情请见目录【七、某些BUG】-【卡死在SystemClock_Config里的Error_Handler】
【锚点】:系统时钟配置的隐患
【半解决】:按一下板子上的重置键,或者使用OpenCD自带的重置MCU
【半解决+1】:在Open CD的配置文件中重置选项勾选运行
7,移植库或文件
这个是比较简单的,要么在CLion项目打开的情况下,直接该替换替换,该删删,之后修改CMakeLists。要么直接把原有的工程文件夹拖到关闭项目后的CLion里,点击一下信任,再把之前用STM32CubeMX新建工程时产生的CMakeLists和启动文件复制粘贴过来。总之,多试多查,不怕犯错,但前提是要把重要工程都备份好。下面内容建议先了解一下CMake构建的过程
现以第一种方式为例,原目录如下
现在开始移植
如果此时你以无需使用STM32CubeMX,那么与其有关的文件可以删掉,注意.idea不建议删掉(但也无所谓,顶多弹个框按一下确定),两个ld文件不要删除,其余自便。Startup文件没有删,放到CORE里了
也就是说现在保留的部分是:两个ld文件和一个启动文件,以及idea文件夹
CLion里面如下,main文件其实放在USER/src或者USER/下比较好,放在外面等会又需要在CMakeLists多写一句
CMakeLists里面其余的可以先不了解,值得关注的是下面这三句
#这一句是包含头文件目录,只需把头文件目录包含进来即可
#目录之间需要用空格(换行也行)隔开,写文件名时CLion会自动补全
include_directories(Core/Inc Drivers/STM32F4xx_HAL_Driver/Inc Drivers/STM32F4xx_HAL_Driver/Inc/Legacy Drivers/CMSIS/Device/ST/STM32F4xx/Include Drivers/CMSIS/Include)
#这是添加预定义,-D后面紧跟着预定义的内容即可
#这一句就加了DEBUG、USE_HAL_DRIVER、STM32F407xx这三个预定义
#一般不需要改,看个人需求,与.h里的#define并无二致
add_definitions(-DDEBUG -DUSE_HAL_DRIVER -DSTM32F407xx)
#下面这一句是包含所有要编译的文件,包括启动文件
#其中GLOB_RECURSE表示使用通配符“*”,SOURSES是个变量名,可以理解为file变量
#使用了通配符需要用双引号括起来,“Core/*.*”表示包含Core目录下的所有文件
#注意!如果你是从Keil或IAR移植过来的,切忌不要把它的启动文件之类的带过来,只要带c相关的文件即可
file(GLOB_RECURSE SOURCES "Core/*.*" "Drivers/*.*")
根据刚才的目录,可以改为下面这样
include_directories(CORE/inc CORE/system DATA USER/inc DRIVER/inc)
add_definitions(-DDEBUG -DUSE_HAL_DRIVER -DSTM32F407xx)
file(GLOB_RECURSE SOURCES "CORE/*.*" "DRIVER/*.*" "DATA/*.*" "USER/*.*" main.cpp )
改了CMakeLists之后Cmake需要重新加载
如果你是使用C++开发就要格外小心了,我在使用IAR时,在c文件对应的.h文件里直接调用C++的头文件是不会报错的(当然这样做并不好,IAR和CLion对头文件与源文件的映射似乎有些不同,IAR相较更为完善些),换到CLion就需要尽量避免C文件直接调用C++的头文件(虽然网上有解决方法)
测试过程中,使用含C++的小项目时,可以正常运行,而移植以前的稍大的项目时出现了下面错误,目前还在排查,发现是C函数以C++的方式编译,但无论是.h文件还是在cpp调用这个.h文件都加了extern "C",可还是出现这个报错。
查了很久很久,才找到这两篇博客undefined reference to ,undefined reference to `_sbrk‘,只是没有想到,我堂堂Windows系统下的嵌入式开发,使用的居然是Linux系统的消息提示,看来arm-none-eabi真是深藏不露
总而言之,就是arm-none-eabi默认是使用startfiles,且编译器为了节省空间,删减了一部分代码, 导致有些方法只有声明没有实现,需要自己实现。
这一部分的解决方法放在了下面目录的使用C++开发
且依这两篇博客所言,这个缺失的部分还是要补回来的,因为malloc、free、printf等难免会用到,具体解决方法在下面的目录【开发拓展-使用C++开发-找回编译器缺失的部分】
五,开发体验提升 (⑅˃◡˂⑅)
由于是长期更新的,所以工程项目会经常替换,名字不一样很正常
1,查看寄存器
①下载
a.到STM32CubeMX里下载
点击【Help - Docs&Resources - System View Description】,就可以等待下载了
不过运气比较糟,下载了三次它还是未回应我
b.到官网去下载(推荐)
进入ST下载官网,在输入框内填上相应型号,然后经历漫长的等待,下载那个SVD
②添加SVD
下载完后,为了方便添加以及后续可能出现的更换等等问题,于是在CLion的目录下新建了一个user_resources,里面专门用来添加各种包的。考虑到以后CLion可能会用于别的用途,那就再新建一个子目录MCU,在这里添加刚刚下载的SVD包,并解压
现在回到CLion,到相应调试窗口下,点击外设一栏,然后点击加载.svd文件,找到相应型号
选择第一个全都要或者挑选几个按需选
这里选择全都要,当然会冒出一堆外设,然后点击最外面的那个STM32F407.svd的,让它收起来,这样再展开时,所有外设都会默认收缩起来
2,背景
无意中看到有个博客(现在找不到了)把背景图片的配置写进去了,这里也提一下。
打开所有设置或设置,然后【外观-背景图像】,选择想要的图片,确定即可
3,推荐一些插件与调试方法
1,调试方法-博客
4,示例工程
语音存储与回放(串行)_页写入_stm32f407VET6_非正点或野火实验平台_裸机
5,ITM与SWO(未完)
简单来说就是打印输出,没有打印输出的调试是不完整的
使用usart还需要一个USB转串口模块,很遗憾我手上这块只有一个仿真接口,连USB都没有,所以就想试试仿真器自带的打印功能。之前打印使用的是IAR的Terminal I/O,转到CLion后就完全不知道怎么做了,先在这放着,同时也希望有大佬可以解答一下
但为了不影响开发,姑且先用平(?次)替ST-LINK Utility 试一试,如果你使用的是其他仿真器可以先查查有没有SWO模式之类的,一般来说是有的
SWO:
【优点】:配置极为简单
【缺点】:速度还行,但与CLion无法联合调试
在合适的位置加入下面HAL自带的ITM_SendChar(char );函数就行了,输出内容为字符,自定义即可
然后编译,烧录到板子上
完成后,可以到官网下载
下载完成后,就可以打开了
点击上方工具栏的【ST-LINK】-【Printf via SWO viewer】
或者点击一下这个示波器样的按钮
然后设置好System clock,这个要根据你自己的时钟树来设置,我的是168MHz,在前面STM32CubeMX关于时钟树配置中有(我已经运行过,所以下面会有输出,正常是空白),端口默认
按下start就可以直接运行已经烧录在MCU的程序了,但此时CLion是无法调试、下载的,被 ST-LINK Utility占用了,除非把 ST-LINK Utility关上。二选一的调试方法让人 (//̀Д/́/)
需要说明的是,只发送char是远远不能满足我们的需求的,还需要对printf进行重定向
①先打开syscalls.c文件(如果你没有,参考一下目录【使用C++开发-找回编译器缺失的部分】)
②找到 _write
③改为下面这样
ITM_SendChar((uint32_t)(*ptr++));
六、开发拓展 ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚
1,使用C++开发
a.编程规范
①无论是c文件还是其对应的头文件都不要直接调用Cpp对应的头文件,不然会编译错误。网上是有如何在C中调用C++的,但还是不建议这么做。因为C++作为C的超集是兼容C的且功能更强大,适合当主体(main.cpp)使用。即便不使用模板、智能指针等泛型编程的东西(当然不一定带得动),重载、引用类型、bool类型、类的继承等就已经可以大大提升开发体验和效率了。
②在cpp文件或其头文件里调用C头文件时,直接用extern “C”包含需要的头文件即可,其实绝大多数都不必包含,因为HAL里已经做过了。
③定义中断服务例程和中断回调函数一定要用extern "C"括起来,不然可能会识别不到
b.找回编译器缺失的部分
和前面的移植一样,STM32CUbeMX生成的ld文件和启动文件都要复制过来,
除此之外!!还要把下面这个syscalls.c文件复制过来
并且要在里面加上这些函数的实现方法(如果不适合,可到网上查这些函数的实现)
先是全局变量
extern int errno;
extern int _end;
然后是实现方法(函数)
caddr_t _sbrk(int incr)
{
static unsigned char *heap = NULL;
unsigned char *prev_heap;
if (heap == NULL)
{
heap = (unsigned char *) &_end;
}
prev_heap = heap;
heap += incr;
return (caddr_t) prev_heap;
}
下面是完整代码供参考
/**
******************************************************************************
* @file syscalls.c
* @author Auto-generated by STM32CubeIDE
* @brief STM32CubeIDE Minimal System calls file
*
* For more information about which c-functions
* need which of these lowlevel functions
* please consult the Newlib libc-manual
******************************************************************************
* @attention
*
* Copyright (c) 2020-2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes */
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
/* Variables */
extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));
extern int errno;
extern int _end;
char *__env[1] = { 0 };
char **environ = __env;
/* Functions */
void initialise_monitor_handles()
{
}
int _getpid(void)
{
return 1;
}
int _kill(int pid, int sig)
{
(void)pid;
(void)sig;
errno = EINVAL;
return -1;
}
void _exit (int status)
{
_kill(status, -1);
while (1) {} /* Make sure we hang here */
}
__attribute__((weak)) int _read(int file, char *ptr, int len)
{
(void)file;
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
*ptr++ = __io_getchar();
}
return len;
}
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
(void)file;
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
__io_putchar(*ptr++);
}
return len;
}
int _close(int file)
{
(void)file;
return -1;
}
caddr_t _sbrk(int incr)
{
static unsigned char *heap = NULL;
unsigned char *prev_heap;
if (heap == NULL)
{
heap = (unsigned char *) &_end;
}
prev_heap = heap;
heap += incr;
return (caddr_t) prev_heap;
}
int _fstat(int file, struct stat *st)
{
(void)file;
st->st_mode = S_IFCHR;
return 0;
}
int _isatty(int file)
{
(void)file;
return 1;
}
int _lseek(int file, int ptr, int dir)
{
(void)file;
(void)ptr;
(void)dir;
return 0;
}
int _open(char *path, int flags, ...)
{
(void)path;
(void)flags;
/* Pretend like we always fail */
return -1;
}
int _wait(int *status)
{
(void)status;
errno = ECHILD;
return -1;
}
int _unlink(char *name)
{
(void)name;
errno = ENOENT;
return -1;
}
int _times(struct tms *buf)
{
(void)buf;
return -1;
}
int _stat(char *file, struct stat *st)
{
(void)file;
st->st_mode = S_IFCHR;
return 0;
}
int _link(char *old, char *new)
{
(void)old;
(void)new;
errno = EMLINK;
return -1;
}
int _fork(void)
{
errno = EAGAIN;
return -1;
}
int _execve(char *name, char **argv, char **env)
{
(void)name;
(void)argv;
(void)env;
errno = ENOMEM;
return -1;
}
至此,也算得上优雅地使用CLion了
2,使用RTOS(简)
如何在STM32CubeMX中配置FreeRTOS的教程网上有很多,不多言了。值得关注的是配置完后,要修改一下CMakeLists,把下面图中22到24行的注释取消掉(大家的行数可能不一样),因为生成的CMakeLists是默认关闭硬件浮点(FPU)的
七、一天写不了几行BUG ( ´◔︎ ‸◔︎`)
有些由于忘了截屏,只能简单描述一下
1,文件在却显示No such file or directory
-> 这是因为文件冲突了,比如原先STM32F013F4PX的包没删,有两个main函数等;由STM32CubeMX生成代码时没有选STM32CubeIDE,使用默认的选择,生成包含所有库文件的代码,这就会有大量的重复
-》删除多余的库,再删除.idea文件夹和cmake-build-debug-mingw这样的编译文件。然后重新进入CLion,配置cmake什么一堆的,都是熟悉的内容
2,刚新建项目,CMake直接报出红字
或是出现no path什么的,那么就要好好看看设置里的工具链和CMake有没有配好,或是有没有下错版本。出现path很容易理解,可能配到了用户变量的Path,而非系统变量,也可能是没有重启
3,显示“不是有效的win32应用程序”
编译能过,但调试时显示运行 “'.elf' 时出错createprocess error=193, %1 不是有效的 win32 应用程序”之类的
-》这个之前没有使用C++时,重新调一下工具链和CMake就好了
-》(使用C++后?)没有配置OpenOCD也会出现,配置后就不会出现了,可以正常下载烧录
4,只有一个报错,并指向了蓝色的flash.id文件
进去一看有个提示,说什么【“ready”这个关键字只支持11.0以上的gcc,如果你有10.0的,请把它删除】。
-》按照本教程里的安装,下个13.2版本的arm-none-eabi-gcc,然后配置系统变量,加到工具链什么的
5,出现了完全摸不到头绪的提示
唯一能找到价值的还是标出的那一句
“ "F:\JetBrains\CLion 2023.1.1\OpenOCD-20231002-0.12.0\bin\openocd.exe" -c "tcl_port disabled" -c "gdb_port 3333" -c "telnet_port 4444" -s F:\JetBrains\CLion 2023.1.1\OpenOCD-20231002-0.12.0\share\openocd\scripts -f D:\EDA\MCU\untitled1\stlink.cfg -c "program D:/EDA/MCU/untitled1/cmake-build-debug/untitled1.elf" -c "init;reset init;" -c "echo (((READY)))" Open On-Chip Debugger 0.12.0 (2023-10-02) [https://github.com/sysprogs/openocd] Licensed under GNU GPL v2 libusb1 09e75e98b4d9ea7909e8837b7a3f00dda4589dc3 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Unexpected command line argument: 2023.1.1\OpenOCD-20231002-0.12.0\share\openocd \scripts GDB Server stopped, exit code 1 进程已结束,退出代码0”
这个问了一下智谱AI 4.0(没打钱),还真给回答出来了,于是我就照着做也确实解决了。这也许是一个不错的思路
6,卡死在SystemClock_Config里的Error_Handler
这个比较莫名奇妙,即便外部时钟源是按原理图配置的,使用IAR时能正常起振,这里却会死循环。
把SystemClock_Config里的Error_Handler直接去掉是可以运行的,但治标不治本的办法只是遮盖了失败的初始化,时钟频率只有正常的一小半。这都是用STM32CubeMX配置的,不应该有问题才对,同样的代码用IAR就没有问题,原因未知
无意中按了一下板子上的重启键就正常了,这一点让我想起了IAR中Debugger下关于ST-Link的配置,是有什么硬件复位、系统复位的。试了一下CLion自带的重置MCU,发现也可以使HSE正常初始化
由此推测cfg配置、GDB什么的存在某些问题没配好,希望有大佬可以讲解一下。
实在没有解决办法的话,只好把这个重置MCU当成程序运行键,毕竟IAR烧录完了之后还需要按一下运行键,这样似乎也不错?
把重置改为运行即可,其它教程好像不需要这样做,难道是我的配置和板子特殊?望大佬解答
7,出现一堆关于启动文件报错的红字
注意哈,移植时不要把IAR或Keil的启动文件也带进来了,启动文件要用STM32CubeIDE(MX)的,也不要把原项目工程的工程配置如.icf带过来,只要.c .h .cpp之类的文件即可
曾闻:硬件开发嘛,就是要反复折腾,折腾得多了,水平自然就提高了
标签:文件,int,void,配置,C++,STM32CubeMX,file,CLion From: https://blog.csdn.net/m0_74349248/article/details/137279554