尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

STM32F103C8点灯工程烧录报错error #550解决指南

STM32F103C8点灯工程烧录报错error #550解决指南 简介基于STM32F103C8的LED点阵屏演示工程面向嵌入式初学者与显示驱动开发者解决HUB08接口下32x64双色点阵屏静态显示的实现问题。压缩包共74个文件包含31个h头文件、30个c源文件、8个汇编启动文件以及uvprojx工程、ini配置和bat批处理脚本整体仅273KB其中汇编启动文件完成内核初始化c/h文件分别承载外设驱动与应用逻辑目录划分便于快速定位。目前已有1999人学习下载内容覆盖系统时钟配置、GPIO初始化、定时器PWM亮度控制、显示缓冲区设计和HUB08协议数据传输等关键代码并附使用说明与工程清理脚本。阅读源码可完整掌握双色点阵屏静态驱动逻辑理解GPIO、定时器、中断在显示控制中的配合方式也能迁移到其他STM32F1系列项目对嵌入式LED显示开发具有直接参考价值。 接手一个老工程先别急着双击打开我见过太多人卡在第一步就放弃了。这个名为STM32F103C8_Demo_2020-10-10-LEDA.rar的压缩包表面上是个再普通不过的点灯示例但里面藏着的门道比你想的多。C8是STM32F103系列里最经典的型号Cortex-M3内核、64KB Flash、20KB RAM48脚封装国内做小项目、学嵌入式、毕业设计十个人里至少有八个是从这颗料起步的。而LEDA这个后缀按行业惯例指的是LED实验的第一个变体A通常代表基础版本后续可能还有B、C跑马灯或者按键控制版本。这篇文章我就拿这个Demo当标本从解压到烧录把整个流程掰开揉碎讲一遍。重点会放在一个几乎所有新手都会撞上的报错error #550: requested device stm32f103c8(stmicroelectronics) not found for target Target 1。很多人第一次遇到这个红字就以为板子烧了、仿真器坏了其实九成情况只是Keil的烧录配置漏了一环。看完这篇你应该能自己把这个问题彻底解决顺带把工程结构、点灯原理、常见坑位都理清楚。1. 拿到工程包以后先搞明白它到底是什么1.1 一个RAR文件名里藏了多少信息先说文件名。STM32F103C8_Demo_2020-10-10-LEDA.rar这一段字符串拆开看其实信息量巨大STM32F103C8主控芯片型号。C8代表64KB Flash这决定了你的代码体积上限同时RAM是20KB。对比一下C6是32KB Flash、CB是128KB Flash选型时别搞混。Demo表明这是一个示例工程不是完整产品代码。示例工程的代码风格通常偏向教学和验证模块划分不会太细但胜在路径清晰适合当骨架用。2020-10-10工程创建或打包的日期。这个细节其实很关键它提示你这套代码用的是当时流行的那一版标准外设库或者HAL库和现在的CubeMX生成的代码风格会有差异。LEDALED实验的A版本。嵌入式工程师的习惯是同一类实验用A/B/C标记迭代LEDA就是最原始的点灯版本通常是单颗LED闪烁或常亮控制。所以这个包的本质是2020年10月10日某个人用STM32F103C8的最小系统板写了一个最基础的LED控制Demo然后打包上传共享。放到今天来看它依然是一个绝佳的入门样本因为点灯涉及芯片上电、时钟配置、GPIO初始化、编译下载这一整条链路跑通它等于跑通了后续所有外设开发的基础流程。1.2 解压之后工程里最值得注意的几样东西用解压工具解开RAR正常情况下你会看到以下几类文件我逐个说明它们是什么以及哪些可以忽略文件/目录作用备注USER或Project文件夹存放Keil工程文件.uvprojx和主函数双击.uvprojx即可打开工程这是入口HARDWARE或BSP文件夹板级外设驱动LED控制代码通常在这里会看到led.c和led.hCORE文件夹启动文件、内核相关文件如startup_stm32f10x_hd.sC8属于中等容量但老工程有时不分容量通用放置STM32F10x_FWLib或Libraries文件夹标准外设库源码库函数版本的灵魂包含stm32f10x_gpio.c等OBJ或Listings文件夹编译中间文件和生成的hex文件如果压缩包里有现成的.hex你可以跳过编译直接烧录验证.uvopt文件Keil的界面配置如断点、窗口布局可有可无删了不影响编译判断这个工程是寄存器版还是标准库版就看是否包含Libraries目录。寄存器版的工程里通常只有USER、CORE、SYSTEM三个文件夹代码全是直接操作GPIOA-CRL这样的寄存器标准库版则会有一大堆stm32f10x_*.c源文件。2020年这个时间点大概率是标准库的天下但也有人抱着旧习惯写寄存器。无论是哪种不影响点灯逻辑只影响你读代码的姿势。1.3 别急着点编译先把版本账算清楚很多人解压完直接双击.uvprojx然后点击Build结果冒出一堆core_cm3.h not found或者几十个error。不要慌这通常不是代码的问题是Keil的版本和芯片支持包对不上。我在实际项目里遇到过一个情况用Keil MDK 5.36打开一个用MDK 4.74写的工程结果编译器路径全乱编译报错满天飞。处理办法就是先认清楚这个工程是不是有历史包袱按下述顺序排查看.uvprojx文件里的ToolsetName字段确认是ARM还是C51STM32肯定选ARM。确认Keil MDK版本是5.x还是4.x4.x的工程在5.x打开后会自动迁移但部分旧编译器选项会失效。最关键的一步点开魔术棒Options for Target在Device选项卡看能不能选中STM32F103C8如果不能说明缺芯片包去Keil官网装Keil.STM32F1xx_DFP.1.1.0或更高版本。把这个账算清楚了再谈后面的编译和烧录才是靠谱的节奏。2. 环境准备其实大部分报错都死在这一步2.1 Keil MDK的版本陷阱STM32F103C8的开发环境主流是Keil MDK但MDK这玩意儿的版本差异能坑死人不偿命。5.x版本把芯片支持从安装包里拆出去了必须单独装DFPDevice Family Pack。如果你用MDK 5.20以上的版本没装Keil.STM32F1xx_DFP打开工程后Device列表里连STM32F103C8的影子都看不到那之后的编译、烧录全是空中楼阁。具体操作路径是打开Keil点击菜单栏的Pack Installer图标。左侧找到STMicroelectronics→STM32F1 Series→ 选择最新的DFP版本点击Install。等待下载完成然后在魔术棒Device选项卡重新选一次STM32F103C8。如果你是老手用的是IAR或者GCC那这条就当作背景知识看但如果你用的是Keil这一步绕不开。我见过不少初学者下载完工程就点编译刷屏的device not found和core_cm3.h报错硬是搞了三天最后发现是芯片包没装。2.2 STM32F1固件包为什么不装就报错STM32F10x_FWLib这个文件夹里的标准外设库是整个工程的支撑。它提供了GPIO、RCC、USART这些外设的初始化函数没有它你只能面对寄存器手册逐位操作效率极低。在Keil里源码路径是通过魔术棒的C/C选项卡里的Include Paths指定的。老工程在换电脑、换目录之后最容易出现的问题是绝对路径失效。比如原来代码在D:\work\STM32F103C8_Demo\HARDWARE你把工程拷到了E:\test\下如果工程里用的是绝对路径Keil会找不到led.h直接报fatal error: led.h: No such file or directory。解决方法是打开Include Paths把所有路径重新指定一遍或者干脆全改成相对路径。我的习惯是在工程根目录建一个Doc文件夹放说明然后所有源码引用从上往下按相对路径写比如.\HARDWARE\LED、.\USER这种格式这样整个工程拷到任何地方都能直接编译。2.3 第一次编译成功不代表后面就顺利等你把这些前置条件都撸顺了编译通过是大概率事件。但编译通过和能跑起来是两码事链接阶段的Warning: L6305W或者老库函数被deprecated的警告在标准库工程里几乎是家常便饭。这些警告出现的原因通常是你用了GPIO_InitTypeDef但没把GPIO_Speed设置对或者调用了老版本的RCC_APB2PeriphClockCmd编译器提醒你注意兼容性。我的建议是只要没有errorWarning先放着不影响烧录和运行。点灯这个级别的Demo连assert_param都能通过说明逻辑上没大问题。真正要花精力的是后面烧录那一步那才是最磨练心性的地方。3. 点灯代码的底细从寄存器到库函数的思维切换3.1 开时钟最容易忘的一步打开led.c你会看到类似这样的初始化函数标准库版void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); }很多人不理解为什么第一行要开时钟没有它LED就是不亮。原因在于STM32的所有外设默认是断电状态你要用GPIO必须先通过RCC_APB2PeriphClockCmd把挂在APB2总线上的GPIOA外设时钟打开。这就好比你要用水龙头得先打开总水阀没有总阀后面调一万遍都没用。在寄存器版本里这一步对应的是RCC-APB2ENR | 1 2;把APB2ENR的第2位置1使能GPIOA时钟。两种写法的底层原理一样库函数只是把位操作封装成了人话。对于初学者我建议先用标准库理解流程等理解透了再回头看寄存器会有一通百通的感觉。3.2 GPIO模式选择推挽输出为什么是默认答案GPIO_Mode_Out_PP是推挽输出模式这是点LED的默认选择。所谓推挽就是引脚内部有一个高边MOS管和一个低边MOS管输出高电平的时候高边管导通把引脚拉到3.3V输出低电平的时候低边管导通把引脚拉到GND。这样的结构驱动能力强可以直接带一个串联了电阻的LED。你要是把模式改成GPIO_Mode_Out_OD开漏输出那就只能输出低电平和浮空要靠外部上拉电阻才能拉高不接上拉电阻的话LED是灭的这一点经常有人搞混。让我多提一嘴如果你的板子上LED是接在3.3V和PA0之间那初始化成推挽输出然后引脚写低电平LED才亮写高电平反而灭。很多教学板喜欢用这种低电平点亮的接法代码里可能是GPIO_ResetBits(GPIOA, GPIO_Pin_0)来点亮写代码前看原理图最稳妥。3.3 主循环写法延时、翻转与肉眼可见的闪烁节奏主函数通常长这样int main(void) { LED_Init(); while (1) { GPIO_SetBits(GPIOA, GPIO_Pin_0); Delay(1000); GPIO_ResetBits(GPIOA, GPIO_Pin_0); Delay(1000); } }这个Delay在标准库工程里一般是用SysTick实现的软延时有的工程直接用一个简单的循环for(i0;i0xFFFF;i);。后者的延时时间受主频影响很大如果你是72MHz主频循环次数合适的话大概是几百毫秒到一秒不等没法精确控制但用来点灯完全够用。如果你是2020年这个时间点的标准库工程大概率能看到Delay函数配合SysTick的相关实现。SysTick是内核自带的24位向下计数器用它做时基的好处是不占用定时器外设而且时间可控Delay(1000)就是延时1000毫秒。实际跑起来的效果就是LED以大约1Hz的频率闪烁这是嵌入式世界里最经典的第一支舞。看起来简单但CPU怎么上电、时钟怎么起振、外设怎么初始化、主循环怎么跑这一整套流程都在里面了。4. error #550不是硬件坏了是烧录配置缺了一环4.1 这个报错长什么样什么时候出现你编译成功后点击Download按钮结果Keil的Build Output窗口刷出一行红字error #550: requested device stm32f103c8(stmicroelectronics) not found for target Target 1第一次见到这行字的人通常的念头是我的板子联系不上了或者ST-Link坏了。其实这个报错翻译成人话是Keil想往目标芯片写程序但在当前烧录配置里根本没找到对应的Flash编程算法。换句话说它压根不知道怎么把程序写进STM32F103C8的内部Flash。什么时候会出现除了上面说的漏配Flash Download功能还有几种情况新建工程时选了Device但从未配置过Utilities和Debug选项卡。更换了仿真器比如从J-Link换成了ST-LinkDebug选项卡里的驱动没有同步更换。使用ST-Link但固件版本过旧Keil识别不到设备报错表现也是device not found。4.2 根因分析Flash Download算法才是主角要理解这个报错先搞明白烧录的本质。STM32的内部Flash是一个存储介质你不能像访问数组一样直接往里面塞数据必须通过特定的Flash控制器时序来写入。Keil本身不内置每种芯片的Flash控制时序它调用的是一个独立的小组件叫做Flash Programming AlgorithmFlash下载算法。算法文件通常以.FLM格式存在Keil安装目录的ARM\Flash文件夹下ST官方提供的STM32F10x Med-density Flash就是适用于F103C8的那个算法。当你勾选了Debug选项卡里的Use Debug Driver并把Flash Download里的Programming Algorithm配置好Keil才能在烧录时正确识别芯片型号调用对应算法完成擦除、编程、校验这三步。缺了这一步它连烧录流程的第一脚都迈不出去只能报device not found。我把配置前后的状态做个对比你一看就明白配置项错误状态正确状态Debug下拉框未选择仿真器或选了但实际设备为ST-Link根据你手里的仿真器选择ST-Link Debugger或CMSIS-DAP DebuggerFlash Download列表空白没有添加任何Flash算法已添加STM32F10x Med-density Flash起始地址0x08000000大小8KReset and Run选项未勾选勾选后烧录完自动复位运行省去手动按复位键4.3 一步步把烧录配好接下来是操作步骤按照这个顺序做十分钟内解决确认仿真器物理连接。ST-Link插入电脑USB口SWD的四根线SWDIO、SWCLK、GND、3.3V分别接到板子对应的排针。这里有个新手最容易犯的错接线时只接了SWDIO和SWCLK忘接GND导致信号没有参考地仿真器完全识别不到板子。打开Keil的魔术棒Options for Target。切到Debug选项卡右上角选择ST-Link Debugger然后点旁边的Settings。在弹出的窗口里如果能看到IDCODE那一栏出现了0x1BA01477之类的一串值说明仿真器和芯片通讯成功了。如果SW Device窗口空白回去查接线。切到Utilities选项卡勾选Use Debug Driver这样烧录会复用刚才Debug的设置。点击Settings在Flash Download页面点击Add在列表里选择STM32F10x Med-density Flash点击Add。确认起始地址是0x08000000编程大小是8K同时勾上Reset and Run。返回主界面重新点击下载按钮。这一步跑完你会在Build Output窗口看到Programming Done. Verify OK.或者类似字样然后板子上的LED开始闪烁。我第一次把这一整套配通的时候那种畅快感不亚于解出一道高数大题。4.4 顺手补充复位模式与常见坑配置好Download之后还有一个隐藏选项值得注意在Settings的Debug页面里有Connect under Reset这个复选框。如果你的代码把SWD引脚PA13、PA14复用成了GPIO那么芯片正常运行时会把这几个引脚的电平状态拉死造成识别不到芯片、无法烧录的死循环。这时候勾上Connect under Reset让仿真器在复位瞬间抢占总线就能把程序烧进去。这也是很多人在实际项目里遇到过、但文档里不会明写的坑。另外一个更隐蔽的问题是电源不稳。如果你的板子不是从ST-Link取电而是用USB转TTL供电ST-Link又单独接了USB两边地线没连也会出现识别不稳定的情况报错五花八门。在Responsive Debugger这类工具普及之前地线干扰导致的诡异问题排第一养成先共地再谈通讯的习惯能省很多时间。5. 从LedA往外走这个工程还能怎么变5.1 流水灯点灯Demo跑通之后最常见的第一个变体是流水灯。在C8这个芯片上你有GPIOA的16个引脚外接8个LED做成跑马灯是大学实验室的经典项目。代码改造思路很简单在main函数的while(1)循环里用一个数组存放引脚号循环移位点亮。比如u16 pin[8] {GPIO_Pin_0, GPIO_Pin_1, GPIO_Pin_2, GPIO_Pin_3, GPIO_Pin_4, GPIO_Pin_5, GPIO_Pin_6, GPIO_Pin_7}; for (int i 0; i 8; i) { GPIO_Write(GPIOA, pin[i]); Delay(500); }这里要用到GPIO_Write这个库函数它可以直接给整个端口写入16位数据比一个一个SetBits快得多。注意GPIO_Write会把整个PA口都覆盖掉如果PA口还接了其他外设就不能这么粗暴要改用GPIO_SetBits和GPIO_ResetBits组合操作。5.2 按键控制第二个值得一试的变体是按键控制。在LEDA这个Demo的基础上加一路按键输入按下时翻转LED状态这比单纯闪烁有意思得多也更接近真实产品的交互逻辑。按键检测的初始化代码比LED稍麻烦一点要把GPIO配置为输入模式一般选择上拉输入GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU; GPIO_Init(GPIOC, GPIO_InitStructure);然后主循环判断GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1)的值。这里有个实战经验机械按键按下瞬间会有抖动必须做消抖处理简单的方法是延时20ms后再读一次确认电平没变化再认为按下有效。这个技巧看起来基础但很多产品的按键稳定性问题都出在这。5.3 64KB Flash的边界感最后想聊一个关于C8容量边界的话题。STM32F103C8的64KB Flash听起来不大但如果你只是点LED、跑跑传感器、控制几个继电器它完全够用。我实际做过一个温湿度采集加OLED显示加串口上报的小项目整个固件体积大概25KB在C8上跑得游刃有余。但如果你的工程用了全套HAL库、RTOS、完整版TCP/IP协议栈64KB很快就见底了。这时候你会看到链接器报L6220E: Region RAM overflowed或FLASH overflowed后者直接告诉你代码放不下了。解决办法无非是开编译优化-Os、裁剪未使用的外设驱动、或者直接换CB128KB Flash型号。我对C8的态度一直是它是练手和做小型项目的神器但别在它身上塞太多不切实际的幻想。把LEDA这个Demo玩透你就掌握了STM32开发的整套方法论后面不管是换H7还是换GD32思路都是通的。6. 我在实际调试LedA工程时的几个习惯聊到最后分享几个我在调这类老Demo工程时积累的习惯。第一个是拿到工程先看主时钟配置。很多Demo板用的是内部HSI 8MHz时钟但标准库工程默认是外部HSE 8MHz晶振倍频到72MHz。如果板子上没焊晶振程序就会卡在时钟启动的超时循环里表现就是LED不亮、调试器停在SystemInit。这种情况不是代码逻辑错是硬件和软件的时钟配置不匹配把SystemInit里的HSE启动改成HSI或者用SystemClock_Config重新配置一下就好。第二个习惯是每次烧录前先编译一次用最新的.axf文件去下载不要拿着过期的.hex硬刷。我见过不少人改完代码没编译就去下载结果板子跑的还是上上个版本白白排查半天。第三个习惯是动手改代码之前把原始工程完整复制一份作为备份。这个LedA工程虽然简单但改崩了再回去找原版很麻烦尤其是当你把GPIO模式、时钟树、宏定义都改得面目全非时一份干净的原始备份会救你于水火。我自己的做法是在解压目录下留一个src_backup文件夹任何大改动前先把当前可用的版本复制进去标注日期一年下来能少掉无数头发。最后一个建议可能和代码无关但确实帮我避了很多坑学会看原理图。哪怕是一张几十块钱的最小系统板它的LED接在哪个引脚、是高电平点亮还是低电平点亮、有没有串联限流电阻这些都决定了代码怎么写。拿到LedA工程先把板子的原理图打开找到LED那一路确认丝印上标的是PA0还是PC13再回来看代码你会发现很多原来想不通的设计都豁然开朗。本文还有配套的精品资源点击获取
返回列表