ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Keil5.23建STM32工程全流程:环境配置、编译报错与提速技巧

Keil5.23建STM32工程全流程:环境配置、编译报错与提速技巧 写这篇东西的起因很简单有朋友给我发消息问“怎么用Keil5.23建一个STM32工程并编译”我第一反应是这问题太基础了网上一搜一大把。但聊深了才发现真正卡住新手的往往不是建工程那几步而是安装环境时一堆乱七八糟的小选项、固件包版本对不上、编译出来一堆看不懂的英文报错任何一个环节出错都能让人卡一晚上。所以我把这十几年的经验整理成一篇完整流程从环境准备、芯片支持包到新建工程、编译出HEX文件再到高频报错排查从零开始带你走一遍保证你照着做就能把板子上的灯点亮。这篇文章适合刚接触STM32、没有任何开发环境经验的入门者也适合装了好几次Keil但始终没编译成功过的朋友。标题里说的“固件包自带版本”其实就是指Keil5.23配合官方芯片支持包来创建工程不用自己找库、配路径只要把环境选对剩下的都是肌肉记忆。1. 先搞清楚这个标题里的三个关键词1.1 Keil5.23不是越新越好稳定才是王道先说版本号。市面上能下载到的Keil MDK版本五花八门有5.14、5.17、5.23、5.27、5.36、5.38再新的还有6.x系列。很多新手一看到新版本就忍不住去装最新的其实对入门来说这反而是个坑。Keil 5.23是老一代的经典稳定版本它的界面、编译流程、插件兼容性都经过大量用户验证网上教程也基本都是基于这个版本写的你遇到问题搜解决方案时绝大多数都能直接对上号。我自己测试过5.23对标准外设库StdPeriph_Lib也就是老教程里最常见的STM32F10x固件库支持得很好编译速度快占用内存也不高调一个入门级的工程完全够用。对比起来5.27以上版本虽然界面更现代但如果你用的还是老库或者旧工程反而容易出现奇怪的兼容问题。5.23这个版本卡在一个“功能刚好够用、生态最成熟”的位置上对自学者来说这是最好的起点。使用5.23还要注意一个细节这个版本的默认编译器是ARMCCARM Compiler 5而新版本会默认切换到ARM Compiler 6。编译器一变很多老代码的编译行为就不一样了比如语法检查更严格、优化策略不同对新手来说这是额外变量。用5.23你默认用的就是最主流的ARMCC 5.06踩坑概率大幅下降。1.2 “固件包自带版本”到底指什么继续说回标题里的“固件包自带版本”。在STM32开发的世界里有两个“包”特别容易混淆一个是芯片支持包DFPDevice Family Pack一个是固件库Firmware Library。芯片支持包是给Keil用的“芯片身份证”装好之后你在新建工程时才能在选择界面看到“STM32F103C8”“STM32F407ZGTx”这样的具体型号。没有这个包Keil根本不认识任何STM32芯片。而固件库是编程时用到的“底层驱动代码集合”比如你想操作GPIO、配置串口、初始化定时器直接调用库函数就行不用自己去翻寄存器。固件库又分为标准外设库、HAL库、LL库三种。标题里说的“固件包自带版本”通常是指Keil安装包或教程配套资源里已经集成了某个版本的芯片支持包你装好Keil之后再手动把那个.pack文件双击安装一下就能直接建工程。这种方式对新手最友好省去了去官网找包、担心版本不匹配的麻烦。我见过太多人卡在这一步Keil装好了但在Device选择界面怎么都找不到STM32型号就是因为没装芯片支持包。1.3 认识你即将面对的三个“包”为了避免后续流程里晕头转向我们先把“包”这件事彻底理清。你接下来会接触到的有三个东西Keil MDK 5.23集成开发环境也就是我们“写代码和编译”的软件本体。STM32F1xx_DFP或F4、F0等芯片支持包作用是让Keil“认识”你的芯片型号。相当于你在手机上下了一个输入法手机才知道怎么打出这个语言的文字。标准外设库/固件库写程序时的底层驱动源码。相当于输入法里自带的词库你打出“GPIO”三个字母它能帮你联想出完整的那一串寄存器配置代码。这三者的关系可以打个比方Keil是厨房芯片支持包是菜谱告诉厨房有什么食材、怎么开火固件库是已经洗好切好的配菜拿来即用不用自己从头备料。理解了这层关系后面所有操作都会豁然开朗。2. 环境准备安装Keil5.23和芯片支持包2.1 安装前需要知道的几个原则先说安装这件事其实没什么高难度但有几个坑是新手必踩的。第一安装路径千万不要有中文和空格。我见过有同学把Keil装到“D:\软件\Keil_v5”下面结果编译的时候报了一堆莫名其妙找不到文件的错误后来把整个路径改成“D:\Keil_v5”就全好了。不是Keil矫情是老外写的工具链对非ASCII字符支持不太好包括后面建的工程路径也一样一律用英文。第二安装时最好关闭杀毒软件和防火墙或者至少把Keil的安装目录加入白名单。Keil安装包里有破解工具、License授权相关文件这些经常被误报成病毒。我并不是让你用盗版其实Keil有评估版可以免费试用只是很多教程资源里的安装包附带了License生成工具这类文件确实容易被拦截。如果你只是学习评估版32KB代码限制完全够用点个灯、跑个串口根本不会超。第三安装过程中会让你选择“Core”还是“Pack”新手不要改动默认配置直接选全部安装就行。有些教程为了省空间会让只装Core但这样后面装芯片支持包时反而容易缺东西。空间不够的话装完再把C盘一些缓存文件清一清就行。2.2 芯片支持包DFP安装实操Keil装好后默认是找不到STM32型号的别慌这只是因为还没安装芯片支持包。装包有两种方式第一种是通过Keil自带的Pack Installer在线安装打开Keil菜单栏点“Pack Installer”左边列表里搜索“STM32F1xx”找到对应芯片系列点Install即可。这种方式需要网络畅通下载速度有时候很慢如果等半天没反应就果断换第二种。第二种方式是离线安装。从官网或网盘下载“Keil.STM32F1xx_DFP.2.3.0.pack”这样的文件直接双击Keil会自动打开并执行安装流程等右下角出现“Pack Installed”的提示就完成了。我推荐你用这种方式因为安装包体积大一般几百MB用下载工具拖下来更稳定而且以后重装系统时还可以再拿来用。判断芯片支持包有没有装成功很简单在Keil菜单栏点“Project”→“New uVision Project”在弹出的窗口里左侧列表展开“STMicroelectronics”如果能看到“STM32F103系列”之类的型号列表说明已经装好了。这里顺便说一句不同系列对应不同DFPF103用STM32F1xx_DFPF407用STM32F4xx_DFP不要贪多下载好几个哪个系列就装哪个。2.3 顺便说下C51和STM32共存的事热搜词里有“keil5兼容c51和stm32安装”这确实是很多人的真实痛点。很多同学之前学过51单片机电脑里已经有了Keil C51注意C51和MDK是两个不同的产品现在学了STM32又装了Keil MDK 5.23结果发现两个软件的图标长得一模一样打开之后芯片列表却不一样搞得一头雾水。解决方案很简单先装C51再装MDK装到同一个目录下比如都装在“D:\Keil_v5”。这样两个工具链会合并到一个IDE里你在新建工程时如果看到的是“Atmel 89C51”说明当前默认是C51模式看到“STMicroelectronics STM32F103”说明正常显示的是MDK模式。两个模式共存互不干扰不会出现打开后只能看到其中一个的情况。如果先装了MDK再装C51或者装到了不同目录就容易出现只看到一个模式的情况。处理方法是重新运行一下C51的安装程序把路径指到MDK的安装目录覆盖安装一遍就好了。这个问题太典型了每次带新人基本都要解释一遍所以单独拿出来说一下。3. 手把手创建一个最小STM32工程3.1 新建工程的完整操作步骤环境准备好了接下来就是重头戏新建工程。现在我就以一个最常见的STM32F103C8T6蓝板那种为例把每一步操作和白话解释同步给你。第一步打开Keil5.23菜单栏找到“Project”点“New uVision Project”在弹出的对话框里先选好工程保存路径。注意这里一定不要放在桌面也不要放进有中文的文件夹我习惯在D盘根目录下建一个“stm32_project”文件夹然后工程名写“LED_test”点击保存。第二步弹出的“Select Device”窗口中左侧栏展开“STMicroelectronics”下的“STM32F1 Series”接着找到“STM32F103”选择你的具体型号。蓝板常用的是STM32F103C8T6在列表里选它右侧会显示这个芯片的内核信息、Flash大小、RAM大小。选好之后点OK。第三步这一步最容易被新手跳过接下来会弹出一个“Manage Run-Time Environment”窗口里面一大堆勾选项看着头大。对于标准库工程来说这里全部取消勾选直接点OK。因为我们后面要手动添加启动文件和库文件不需要Keil自动帮你管这些。第四步此时工程已经建好但左边Project栏里还是空的。我们需要手动添加启动文件和固件库。鼠标右键“Target 1”→“Add Existing Files to Group”能找到已存在的文件并添加进去。先添加启动文件这个文件的路径在固件库压缩包里标准库解压后的路径大致是“STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm”文件夹里有很多startup_stm32f10x_xxx.s文件分别是不同芯片型号的启动文件我们用的是C8T6中等容量选“startup_stm32f10x_md.s”添加进来。第五步添加固件库的“系统文件”和“内核文件”。还是在同一个库目录下“Libraries\CMSIS\CM3\CoreSupport”下的“core_cm3.c”和“Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x”下的“system_stm32f10x.c”都要加进来。这两个文件一个是ARM内核的抽象层一个是STM32系统时钟初始化代码缺一个都会编译报错。第六步在Source Group 1上右键“Add New Item to Group”选择C File文件名写main.c点击Add。这样工程文件就建好了。3.2 为什么推荐用“标准库寄存器混搭”的方式起步说到这顺便分享一个我的教学经验新手学STM32建议先别急着上HAL库。虽然现在ST官方主推的是HAL库和STM32CubeMX图形化配置工具画个引脚图就能生成代码很方便但我一直觉得入门阶段用标准外设库和寄存器混搭的学习方式能帮你把底层原理摸得更透。为什么因为标准库是一层“薄封装”每个函数背后对应的寄存器操作一眼就能看懂。比如你想让PA1引脚输出高电平标准库写的是“GPIO_SetBits(GPIOA, GPIO_Pin_1)”你去翻源码能看到它最终操作的是“GPIOA-BSRR (uint32_t)GPIO_Pin_1”这个寄存器。而你用HAL库看到的是“HAL_GPIO_WritePin(GPIOA, GPIO_Pin_1, GPIO_PIN_SET)”虽然写法更统一但背后多了一层抽象新手如果不去深挖源码根本不知道底层发生了什么。当然这只是我的个人观点。如果你以后打算长期做STM32开发HAL库确实是大势所趋生态更完善、代码移植性更强。但对入门第一个工程来说标准库能让你在几十行代码内就明白时钟、GPIO、引脚配置这些核心概念而不会被一堆中间件和回调函数淹没。我倾向于“先用标准库把门推开再决定要不要换HAL”。所以第三步里我们没有用RTE环境自动管理文件而是手动添加启动文件和系统文件这也是有意为之。手动添加让你亲眼看到“一个工程由哪些部分组成”以后编译器报错说“找不到某个文件”时你能直接判断是缺了哪个部分。3.3 魔术棒里这几个配置不改必后悔工程文件添加完毕不要急着写代码先把“Options for Target”配置好。在工具栏上找到那个长得像魔术棒的图标点击打开这里有三个选项卡必须看。第一个是“Output”选项卡“Select Folder for Objects”可以自定义编译输出文件存放位置默认在工程目录下新建一个Objects文件夹即可。关键是把“Create HEX File”勾上这样编译之后才会生成烧录用的HEX文件。很多新手编译成功了却找不到.hex文件去烧录就是因为没勾这个选项。第二个是“C/C”选项卡在“Define”栏里输入“STM32F10X_MD, USE_STDPERIPH_DEVICE”因为F103C8属于中等容量芯片需要用这个宏定义来告诉编译器启用哪些代码分支。标准库源码里有很多条件编译语句比如“#ifdef STM32F10X_MD”如果没有定义这个宏很多外设驱动代码根本不会被编译进去后面调用库函数必然报错“undefined symbol”。第三个是“Debug”选项卡这里选择你手头的调试器。用ST-Link就在右侧下拉框里选“ST-Link Debugger”用J-Link就选“J-LINK/J-TRACE”旁边“Settings”里有可能会在“SW Device”标签页显示一个芯片IDCODE串如果显示了说明仿真器连接正常。这一步配置错了后面点仿真调试时会提示“No target connected”。这三个配置是新手最容易漏做的。我不止一次在答疑群看到有人发出“编译零错误但烧录失败”的求助一问全是没勾HEX或者没选Debug模式。4. 编译一顿操作从报错到出HEX4.1 第一次编译会遇到什么现在到了检验成果的时刻。先给main.c里写下最简单的点灯代码然后直接按F7或者点工具栏的“Build”按钮开始编译。如果你和我当年一样是纯新手大概率会看到Output窗口里冒出一堆红色警告和错误别慌一件件来看。这里给出一个最简单的main.c内容你可以先照着抄#include stm32f10x.h int main(void) { GPIO_InitTypeDef GPIO_InitStructure; // 打开GPIOB端口时钟LED接在PB12具体以你板子为准 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 配置PB12为推挽输出最大翻转频率2MHz GPIO_InitStructure.GPIO_Pin GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_2MHz; GPIO_Init(GPIOB, GPIO_InitStructure); while (1) { GPIO_SetBits(GPIOB, GPIO_Pin_12); // 拉高电平LED灭 for (volatile int i 0; i 500000; i); // 简单延时 GPIO_ResetBits(GPIOB, GPIO_Pin_12); // 拉低电平LED亮 for (volatile int i 0; i 500000; i); } }如果你是第一次接触这段代码不需要完全理解每一行的意思只需要知道它的大致逻辑是把某个引脚配置成输出模式然后在死循环里交替拉高拉低让LED闪烁。这个点后续你学完GPIO章节就全懂了。编译后在Output窗口的Build Output子窗口里如果你看到“0 Error(s), 0 Warning(s)”并且下方多了一行“creating hex file...”恭喜你工程已经建好并成功编译了。哪怕有三五个Warning只要没有“Error”字样一般都能正常烧录。4.2 高频报错速查与解决我整理了新手问的最多的几类编译报错做成一个速查表你遇到问题时直接对着查报错内容原因解决方法cannot open source input file stm32f10x.h头文件路径没有添加到工程在C/C选项卡的Include Paths里把固件库所在路径添加进去如...Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10xError: L6218E: Undefined symbol GPIO_Init标准库源码没有编译进工程或宏定义缺失确认GPIO相关.c文件已添加确认Define里已写STM32F10X_MDcore_cm3.c not found内核文件漏添加回到第3.1节第五步把core_cm3.c和system_stm32f10x.c都加入工程.\Objects\LED_test.axf: Error: L6406E: No space in execution regionsFlash内存溢出一般是把代码写满了或者启动文件选错了芯片容量检查启动文件是否为md版本*** Target Target 1 uses ARM-Compiler Default Compiler Version 5 which is not available.Keil版本缺少AC5编译器安装MDK5.23时不要选“Without AC5”之类的精简安装重装时确保勾选ARM Compiler 5其中第一条出现频率最高原因是你在include头文件时编译器不知道头文件在哪。解决方法是在“C/C”选项卡的“Include Paths”右侧点“...”把固件库中所有包含.h文件的文件夹添加进去。我一般把这三个路径都加进去省得以后出问题工程源码目录你自己的.h文件...Libraries\CMSIS\CM3\CoreSupport...Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x还有个小技巧双击Output窗口里的红色报错行Keil会自动跳到出错的代码位置光标停在出错行上。用这个方法定位问题比一行行找快得多。4.3 编译速度优化Keil5.23其实可以很快热搜词里有“keil5编译很慢?”这个问题确实困扰了不少人。很多同学用的都是老旧笔记本电脑编译一次要等半分钟以上如果是用的固态硬盘还好机械硬盘的话本来就慢的Keil雪上加霜。我分享几个实测有效的提速方法。第一关闭“Browse Information”。在工程Options→Output选项卡里有一个“Browse Information”复选框改成不勾选。这个选项是用来生成代码跳转和变量查找索引的对入门学习和编译动态调试来说用处不大但开着会让编译产物体积增大不少编译时间也变长。实测下来关闭这个选项后编译时间大约能缩短30%。第二编译时只点“Build”而不是“Rebuild”。“Build”会让Keil只编译上次编译之后修改过的文件增量编译速度很快而“Rebuild”是重新编译所有文件花的时间多好几倍。这个问题上我见过很多新人以为点那个“Rebuild”图标才是编译其实“Rebuild”的意思是“全部重来”平时的常规操作点“Build”就行。第三把工程放到固态硬盘上。这个建议听起来像废话伤钱但确实效果立竿见影。我有一台老笔记本原来工程放在机械硬盘里编译要40秒换到固态盘后只要12秒。如果条件允许哪怕外接一个USB3.0的移动固态硬盘都比原来的机械盘强。第四关闭不必要的软件。Keil编译时CPU会跑满一个核浏览器、微信、网盘这些后台软件如果都在抢CPU编译时间自然就长了。编译那几秒把后台大软件临时关一关体验会好很多。5. 自学者踩过的坑我给你摊开讲5.1 芯片包版本与固件库版本别搞混关于版本匹配我吃了不少亏这里专门给大家提个醒。芯片支持包的版本比如2.3.0和固件库的版本比如V3.5.0是两个完全独立的东西很多人会拿它们的版本号去对谁新谁旧其实完全没必要。芯片支持包只管“让Keil认识这块芯片”固件库才是你写代码时调用的那个东西。实际开发中只要固件库代码能编译通过芯片支持包和固件库版本差异大一点也没关系。比如你装的是STM32F1xx_DFP的旧版本2.1.0用V3.5.0的标准库写代码完全没问题。反过来如果你用的是新版HAL库可能要求DFP版本高一些。唯一要担心的是不同芯片型号要用对应的DFP。比如你现在用F103装的是F1系列的DFP哪天换成F407就得再装一个F4系列的DFP。这不算坑算是常识但老有人在这儿卡住。5.2 中文注释乱码与编码格式GBK/UTF-8热搜词里有“mdk工程编码gbk改为utf-8”这个坑我先说结论再讲原因。Keil5.23这个版本默认是按ANSI中文系统下就是GBK编码解释源文件的如果你用VS Code或者别的现代编辑器把源码保存成了UTF-8格式那么在Keil里打开就能看到满屏的乱码注释甚至可能导致编译报错因为字符串常量里的中文被编译器按GBK读取时解析错了编译器会把后面的代码内容一起当成字符串内容一路报错到文件结尾。如果你想在Keil里用中文注释最简单的方法就是统一用Keil自带的编辑器写代码别用其他的编辑器代劳这样默认就是ANSI/GBK不会乱码。如果你确实要用VS Code等现代编辑器那可以在Keil的Edit→Configuration→Editor→Encoding里改成“UTF-8”然后再重新打开所有项目文件。改完之后同一个文件在Keil和VS Code里显示都正常。但注意Keil5.23对UTF-8的支持不算完美改了编码后之前用ANSI保存的文件如果不在工程里统一处理反而会乱得更厉害。我的建议是既然是自学干脆注释全部用英文写。别担心英文不好嵌入式领域常用的注释词就那么几十个练几次就能顺手上。用英文注释还有一个额外好处就是编译时永远不用为了注释乱码而分心代码的通用性也好很多以后你把代码发到GitHub上别人看着也舒服。5.3 工程路径、文件命名这些细节这一节讲的都是小事但小事不改大事早晚翻车。第一工程文件夹的路径总长度不要太长。系统对路径长度有上限太长了编译器会找不到文件。我自己习惯把工程路径控制在“D:\stm32_project\LED_test”这样的两到三级以内别放在“D:\Desktop\stm32学习资料\1.代码\练习\第3课_GPIO_LED\版本2\最终版”这种路径下且不说编译容易出问题光每次打开工程找路径就得找半天。第二源文件和工程名尽量保持简单少用“test1_最终版_改版”这是代码管理的大忌。我在实际工作中见过一个工程叫“final_final_v2_ok_真的能用”这种名字谁看到谁头大。给工程起名直接用英文小写下划线比如led_test、key_scan、uart_echo清爽利落。第三工程建好之后不要轻易移动位置或改文件名。Keil的工程文件.uvprojx里记录了各种绝对路径移动位置后路径对不上就会报“cannot open file”。如果你确实要搬家最好的办法不是移动文件而是直接重新新建一个工程把源代码重新添加进去几十秒的事情别折腾。5.4 下载调试环节的常见拦路虎编译通过只是万里长征走完一半。等你想把程序烧进板子可能又会碰到新问题。最常见的两个一个是“No target connected”一个是“Error: Flash Download failed - Cortex-M3”。“No target connected”通常是仿真器没识别到芯片解决办法首先是检查接线SWD模式只需要SWDIO、SWCLK、GND三根线另外最好把3.3V也接上给目标板供电避免电压不稳。检查完之后在Debug选项卡的Settings里点“Detect”重新搜索一次看能否识别到IDCODE。有时候是驱动问题插上ST-Link后设备管理器里显示黄色感叹号那就需要重装ST-Link驱动。“Flash Download failed”一般是烧录算法没选对。在Options→Debug→Settings→Flash Download里要勾选对应的烧录算法比如STM32F103C8只有64KB Flash应该选择“STM32F10x Medium-density 64K Flash”。如果算法选成了High-density或者256K的虽然大多数情况下也能烧但偶尔会报错。特别是C8T6这种小容量芯片经常有人从F103ZET6的工程改过来忘了换烧录算法一烧就报错。这个坑很隐蔽一旦遇到先去检查这里。6. 一些掏心窝的建议说了这么多最后聊点个人体会。我见过太多初学者在第一个星期就被环境问题劝退觉得嵌入式开发太难了其实很多时候不是因为难而是因为“没人告诉你这些坑在哪”。Keil5.23建STM32工程这件事说透了就三步装对软件、装对芯片包、配好编译选项。只要这三步走稳后面就是不断写代码、编译、看现象的正循环。我个人建议第一个工程不要抄太复杂的代码就从LED闪烁开始。点亮一颗灯看似简单但它验证了整个工具链——Keil能建工程、编译器能编译、烧录器能下载、单片机能运行。这四个环节全部打通之后你才真正拥有了继续学下去的底气。接下来无论是点灯、按键检测、串口打印还是中断、定时器、PWM每一关都建立在这个基础上。最后分享一个小技巧每次换个开发板或者换台电脑我都会从建一个LED工程重新开始验证环境。磨刀不误砍柴工十五分钟验证完环境后面几天开发遇到问题就知道不是环境锅能省很多怀疑人生的时间。希望这篇教程能帮你少走一些弯路早点点亮你的第一块STM32。
返回列表