ARTICLE DETAIL

资讯详情

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

STM32入门到进阶:内核选型、开发环境搭建与外设驱动实战

STM32入门到进阶:内核选型、开发环境搭建与外设驱动实战 1. 从一颗芯片说起STM32到底是个什么东西第一次接触STM32的人脑子里冒出来的问题往往不是“怎么用”而是“它到底是什么”。我见过太多新手抱着一块开发板看着密密麻麻的引脚和一堆英文手册完全不知道从哪里下手。所以这篇内容我不打算一上来就甩代码而是先把这颗芯片的来龙去脉讲清楚让你知道自己在跟什么东西打交道。STM32是意法半导体ST推出的一系列基于ARM Cortex-M内核的32位微控制器MCU。拆开来看“ST”是厂商前缀“M”代表Microcontroller“32”代表32位架构。就这么简单一个命名逻辑但背后承载的东西可不少。它不是一个单一型号的芯片而是一个庞大的产品家族从低端的F0系列到高端的H7系列覆盖了从几块钱到上百块钱的广阔区间。那MCU又是什么你可以把它理解成一台“微型电脑”塞进了一颗芯片里。它内部集成了CPU核心、Flash存储器存程序、SRAM存运行时数据、各种外设接口串口、SPI、I2C、ADC、定时器等等。你写好程序烧进去它就能独立运行不需要操作系统也能干活。这和你在电脑上写Python脚本完全不同——STM32上的程序是直接跑在裸机上的每一行代码都直接操控硬件寄存器。为什么STM32能成为嵌入式领域最火的MCU之一我个人的观察是三个原因叠加第一ARM Cortex-M内核本身设计优秀指令集精简高效功耗控制好第二ST的外设库和生态做得极其完善从标准外设库到HAL库再到LL库不同层次的需求都能满足第三社区庞大你遇到的几乎任何问题网上都有人踩过坑并留下了解决方案。这三点加在一起就形成了一个正向循环——用的人越多资料越丰富新入坑的人就越容易上手。注意STM32不是唯一的选择。同级别的还有NXP的LPC系列、TI的MSP430、Microchip的PIC32等。但就目前国内的学习资源和项目实践来说STM32的生态优势是压倒性的新手从它入门是最省力的路径。适合阅读这篇内容的人如果你刚买了开发板不知道从哪开始如果你在选型阶段想搞清楚STM32各系列的区别如果你是从51单片机转过来想了解32位MCU的开发方式那接下来的内容应该能帮你少走不少弯路。2. Cortex-M内核家族M0到M7到底差在哪里很多人选STM32的时候只看型号数字比如F103、F407、H743但忽略了后缀里那个关键信息——内核类型。Cortex-M0、M0、M3、M4、M7这些内核之间的差异直接决定了芯片的性能天花板和适用场景。搞不清楚这个选型就是瞎蒙。2.1 各内核的核心差异与典型型号对应先给一个直观的对比表把几个主流内核的关键指标拉出来内核架构版本典型主频浮点单元DSP指令典型STM32系列适用场景Cortex-M0ARMv6-M48MHz无无F0低成本控制、简单传感器Cortex-M0ARMv6-M64MHz无无G0、L0低功耗、电池供电设备Cortex-M3ARMv7-M72-120MHz无无F1、F2、L1通用控制、工业应用Cortex-M4ARMv7E-M80-180MHz单精度有F3、F4、L4、G4电机控制、信号处理Cortex-M7ARMv7E-M200-480MHz双精度有F7、H7高性能计算、图形处理这张表里最值得关注的是M3和M4的区别。很多人以为M4就是M3的升级版其实不完全是。M4在M3的基础上增加了DSP指令集和可选的浮点运算单元FPU这意味着做FFT、滤波、电机矢量控制这类运算时M4的效率比M3高出数倍。但如果你只是做简单的逻辑控制和串口通信M3和M4的实际体验差别不大。M7则是另一个层级的东西。它有了指令和数据缓存I-Cache/D-Cache有了双精度浮点主频也拉到了400MHz以上。但代价是功耗和价格都上去了而且芯片的引脚更多、封装更大PCB设计的复杂度也跟着提升。我见过一些项目用H7来做本来F4就能搞定的事情结果成本翻倍、开发周期拉长这就是典型的过度选型。2.2 选型时最容易忽略的两个参数除了内核类型还有两个参数经常被新手忽略但在实际项目中会直接影响你的开发体验。第一个是Flash和SRAM的配比。很多人选型时只看Flash够不够大觉得程序能装下就行。但SRAM同样关键——你的全局变量、堆栈、DMA缓冲区都要占SRAM。我做过一个项目程序编译出来Flash只用了60%但SRAM用了85%结果稍微加一个缓冲区就溢出了。一般建议SRAM至少留30%的余量Flash留20%的余量。第二个是外设资源的数量。比如你需要3个SPI接口但选的型号只有2个那就只能软件模拟或者换型号。定时器的数量、ADC的通道数、串口的个数这些都要在选型阶段就数清楚。我习惯的做法是列一张需求表把项目需要的外设全部列出来然后对照数据手册逐个核对宁可多留一个也不要刚好卡死。提示ST的选型工具STM32CubeMX里的MCU选择器可以按外设需求筛选型号比翻数据手册快得多。但注意筛选结果里有些型号可能已经停产或供货紧张最终确认前最好查一下市场库存情况。2.3 从51单片机转过来需要转变的思维如果你之前用的是51单片机转到STM32最大的思维转变在于51上你直接操作寄存器就能控制一切因为寄存器就那么几十个。但STM32的寄存器数量是51的几十倍直接操作寄存器会让你痛不欲生。所以STM32开发必须依赖库——不管是ST官方的HAL库、LL库还是早期的标准外设库。另一个转变是时钟系统。51的时钟通常就是一个晶振直接供给最多分频一下。STM32的时钟树复杂得多外部晶振经过PLL倍频再分配到AHB总线、APB1总线、APB2总线不同外设挂在不同总线上频率各不相同。你配置一个串口的波特率实际上涉及了时钟源选择、分频系数计算、寄存器写入等一系列操作。好在CubeMX可以帮你自动生成这些配置代码但理解背后的逻辑仍然很重要否则出了问题你连从哪里查都不知道。3. 开发环境搭建从零到点亮第一颗LED搞清楚了芯片本身接下来就是动手。我见过太多人卡在环境搭建这一步就放弃了所以这部分我尽量把每个环节都讲透包括那些教程里通常不会提的坑。3.1 工具链的选择Keil、IAR还是CubeIDE目前STM32开发最主流的三个IDE是Keil MDK、IAR EWARM和STM32CubeIDE。各自的特点很鲜明Keil MDK国内用户最多资料最全编译器优化做得好。但它是商业软件正版价格不便宜。网上流传的注册机虽然能用但存在法律风险而且某些版本会有奇怪的编译问题。IAR EWARM编译效率高代码优化强在工业界用得比较多。同样是商业软件价格比Keil还贵。STM32CubeIDEST官方免费推出基于Eclipse集成了CubeMX配置工具和GCC编译器。免费是最大优势但Eclipse的界面响应速度和调试体验确实不如Keil流畅。我的建议是如果是学习用途CubeIDE完全够用而且不用担心版权问题。如果是公司项目根据团队已有的工具链来选不要为了个人喜好强行切换协作成本很高。注意网上搜索“Keil MDK下载”时务必从官方渠道获取。第三方下载站捆绑的安装包经常夹带其他软件而且版本可能被篡改。安装路径中不要包含中文和空格否则编译时可能出现莫名其妙的错误。3.2 芯片包的安装与常见报错处理装好IDE之后第一件事是安装对应芯片系列的Device Family PackDFP。比如你用F103就要装STM32F1xx_DFP。这个包里面包含了启动文件、链接脚本、外设寄存器定义等关键文件没有它编译都过不了。安装芯片包最常见的报错是“Cannot find device”或者“Device not found in database”。原因通常是包没有装全或者IDE的Pack路径设置不对。Keil的默认Pack路径在C:\Users\你的用户名\AppData\Local\Arm\Packs如果这个路径下有中文或者权限问题就会导致包加载失败。另一个高频报错是*** error: e:\keil5\arm\bin\sarmcm3.dll not found。这个错误通常出现在你从别人那里拷贝了整个Keil安装目录但没有正确安装运行时环境的情况下。sarmcm3.dll是ARM编译器的一部分缺失说明编译器组件不完整。解决办法是重新运行Keil的安装程序选择修复安装或者单独安装ARM Compiler组件。还有一种情况是编译时提示找不到core_cm3.h或stm32f10x.h。这通常是头文件搜索路径没有配置正确。在Keil的Options for Target → C/C → Include Paths里需要把芯片包的头文件目录、CMSIS目录、外设库目录都加进去。CubeMX生成的工程会自动配好这些路径但手动创建的工程就需要自己一个个添加。3.3 用CubeMX生成第一个工程以点亮LED为例CubeMX是ST官方推出的图形化配置工具你可以把它理解成一个“代码生成器”——你在界面上点选引脚功能、配置时钟树、设置外设参数它自动生成初始化代码。对于新手来说这极大地降低了入门门槛。具体操作流程打开CubeMX选择“New Project”在搜索框输入你的芯片型号比如STM32F103C8T6。在引脚图上找到连接LED的引脚假设是PC13左键点击选择“GPIO_Output”。在左侧的System Core → GPIO里选中PC13把模式设为Output Push Pull上下拉设为No Pull速度设为Low。转到Clock Configuration标签页配置时钟源。以F103为例外部晶振8MHz经过PLL 9倍频得到72MHz的系统时钟。CubeMX会自动计算分频系数你只需要在图上点选即可。转到Project Manager标签页设置工程名称、存储路径、工具链选MDK-ARM或STM32CubeIDE然后点击“Generate Code”。生成的工程里main.c的while(1)循环中默认是空的。你需要手动添加LED闪烁的代码while (1) { HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); HAL_Delay(500); }编译下载后LED应该以1秒的周期闪烁。如果没亮先检查硬件连接——LED的正负极有没有接反限流电阻是否合适。再检查软件配置——引脚号是否对应时钟是否使能了GPIOC。我遇到过有人把PC13配置成了输入模式然后纳闷为什么LED不亮这种低级错误在新手里其实很常见。3.4 下载器与调试接口的坑STM32常用的下载调试方式有ST-Link、J-Link和串口ISP。ST-Link是性价比最高的选择原厂的Nucleo开发板自带ST-Link也可以单独买一个几十块钱的ST-Link V2。连接方式是SWD接口SWCLK、SWDIO、GND、3.3V四根线。注意SWCLK和SWDIO不要接反虽然接反了通常不会烧芯片但会连不上。另外有些开发板上的SWD接口顺序和ST-Link的排线顺序不一致需要自己对照原理图确认。常见问题“No Cortex-M SW Device Found”几乎每个新手都会遇到。原因通常有几种一是SWD线没接好或者接反了二是芯片的调试引脚被程序禁用了比如你在代码里把PA13、PA14配置成了普通GPIO三是芯片进入了低功耗模式调试器唤不醒它。如果是第二种情况解决办法是按住复位键点击下载按钮在松开复位键的瞬间芯片会进入调试模式此时可以擦除Flash。或者把BOOT0拉高让芯片从系统存储器启动这样就不会运行你写的禁用调试引脚的程序。4. 外设驱动实战从GPIO到通信接口环境搭好、LED点亮之后接下来就是逐个攻克外设。STM32的外设很多但常用的就那么几个GPIO、定时器、串口、SPI、I2C、ADC。我把每个外设的核心要点和常见坑梳理一遍。4.1 GPIO的八种模式与实战选择GPIO是最好入门但也最容易被轻视的外设。STM32的GPIO有八种模式输入浮空、输入上拉、输入下拉、模拟输入、开漏输出、推挽输出、开漏复用、推挽复用。新手最困惑的是什么时候用推挽、什么时候用开漏。简单记推挽输出可以输出高电平和低电平驱动能力强适合直接驱动LED、继电器等。开漏输出只能输出低电平高电平需要外部上拉电阻适合I2C总线、多个设备共享信号线的场景。复用模式则是当引脚被分配给外设如SPI、串口时使用此时GPIO的控制权交给了外设。一个实际踩过的坑我用开漏模式驱动一个需要高电平触发的继电器结果继电器死活不动作。后来发现开漏输出在没有外部上拉的情况下高电平实际上是高阻态电压根本拉不上去。换成推挽输出后立刻正常。所以选模式之前先想清楚你的负载需要什么电平。4.2 定时器不只是延时那么简单很多人对定时器的理解停留在“做延时”上其实STM32的定时器功能极其丰富PWM输出、输入捕获、编码器接口、定时中断、DMA触发等等。以PWM输出为例配置步骤大致是选择定时器比如TIM2设置预分频器PSC和自动重装载值ARR来决定PWM频率设置捕获比较寄存器CCR来决定占空比。频率计算公式是PWM频率 定时器时钟 / ((PSC1) * (ARR1))假设定时器时钟72MHzPSC设为71ARR设为999那么PWM频率 72,000,000 / (72 * 1000) 1000Hz。占空比 CCR / (ARR1)如果CCR设为500占空比就是50%。我做过一个用PWM调光的项目发现低占空比时LED有闪烁。原因是PWM频率设得太低只有100Hz人眼能感知到闪烁。把频率提高到1kHz以上就看不出来了。但频率也不能太高否则MOS管的开关损耗会增加。一般LED调光用1-5kHz比较合适。4.3 串口通信从轮询到中断到DMA串口是调试和通信最常用的接口。STM32的串口支持三种收发方式轮询、中断、DMA。轮询方式最简单但CPU会一直等着数据效率极低。中断方式在收到数据时触发中断CPU不用一直等但每个字节都要进一次中断波特率高了之后中断开销很大。DMA方式则是数据直接由DMA控制器搬运到内存CPU完全不参与效率最高。我的经验是波特率低于115200时中断方式足够用。高于115200或者数据量大的场景必须上DMA。曾经有个项目用中断方式接收GPS模块的数据波特率设了460800结果CPU有30%的时间都在处理串口中断其他任务明显卡顿。换成DMA之后CPU占用降到了几乎为零。另一个常见问题是串口通信突然连不上。排查思路先确认波特率、数据位、停止位、校验位是否匹配再检查硬件连线TX和RX是否交叉连接然后看是否有其他程序占用了串口最后检查电源是否稳定电压不足会导致通信异常。4.4 I2C与SPI两种总线的选择逻辑I2C和SPI都是板级通信总线但适用场景不同。I2C只需要两根线SCL、SDA可以挂多个从设备适合连接传感器、EEPROM等低速设备。SPI需要四根线SCK、MOSI、MISO、CS速度比I2C快得多适合连接显示屏、Flash存储器等高速设备。I2C最容易踩的坑是上拉电阻。I2C总线必须接上拉电阻通常4.7kΩ或10kΩ。如果上拉电阻太大信号上升沿变缓高速通信时会出错。如果太小功耗增加而且某些从设备可能拉不动。我遇到过用10kΩ上拉在400kHz速率下通信不稳定的情况换成4.7kΩ后问题消失。SPI的坑主要在片选信号CS的管理上。如果总线上挂了多个从设备每个设备需要独立的CS引脚。通信时先把对应的CS拉低通信完成后拉高。如果忘记拉高从设备会一直以为在通信中导致后续操作异常。另外SPI的时钟极性和相位CPOL/CPHA必须和从设备匹配否则数据会错位。这个参数在从设备的数据手册里都有配置前务必确认。5. 那些年我踩过的编译与链接坑代码写完了编译不过或者编译过了跑不起来这是最让人抓狂的阶段。我把自己遇到过的典型问题整理出来希望能帮你节省一些排查时间。5.1 链接脚本.ld文件与内存布局STM32的链接脚本定义了Flash和SRAM的起始地址、大小以及各个段.text、.data、.bss、.stack、.heap的存放位置。CubeIDE使用GCC编译器链接脚本是.ld文件Keil使用ARM编译器对应的是.sct分散加载文件。最常见的链接错误是“region FLASH overflowed by X bytes”意思是代码量超过了Flash容量。这时候要么优化代码减小体积要么换Flash更大的型号。优化代码的手段包括开启编译器的优化选项-Os、移除未使用的函数和变量、把常量数据放到Flash而不是SRAM中。另一个错误是“no room for stack/heap”说明SRAM不够用了。STM32的启动文件里会定义堆栈大小默认通常是1KB堆、512B栈。如果你的程序用了递归或者大的局部数组就需要增大栈的大小。在启动文件startup_stm32f10x.s里找到Stack_Size和Heap_Size按需调整。提示调整堆栈大小后记得重新编译并检查map文件确认SRAM的使用量没有超过物理容量。map文件在Keil的Listing目录下CubeIDE则在Debug目录下搜索“Total RW Size”就能看到SRAM占用情况。5.2 中文编码问题GBK转UTF-8的实操Keil MDK默认使用GBK编码而CubeIDE和VSCode默认使用UTF-8。如果你在Keil里写了中文注释然后用CubeIDE打开中文就会变成乱码。反过来也一样。解决办法有两种一是统一编码格式建议全部用UTF-8。在Keil里可以通过Edit → Configuration → Editor → Encoding改为UTF-8。二是用工具转换比如Notepad的“编码”菜单里可以批量转换文件编码。我个人的习惯是所有源文件统一用UTF-8编码并且在文件头部加一行注释说明编码格式。这样不管用什么IDE打开只要IDE的编码设置正确就不会出现乱码。另外尽量避免在代码中使用中文变量名和函数名虽然编译器支持但跨平台协作时容易出问题。5.3 HardFault异常的定位方法HardFault是STM32开发中最让人头疼的异常之一。程序跑着跑着就卡死了调试器显示停在HardFault_Handler里但完全不知道哪里出了问题。定位HardFault的核心思路是在进入HardFault时把当时的寄存器状态保存下来然后分析是哪种错误导致的。Cortex-M内核有几种 fault 类型总线错误、存储器管理错误、用法错误。通过读取SCB-CFSR寄存器可以判断具体类型。更实用的方法是在HardFault_Handler里加入打印堆栈信息的代码把出错时的PC指针、LR寄存器值打印出来然后对照反汇编文件找到对应的代码行。具体实现网上有很多现成的代码片段搜索“STM32 HardFault定位”就能找到。我遇到过的HardFault原因包括数组越界访问、空指针解引用、栈溢出、访问了未使能时钟的外设寄存器。其中栈溢出最隐蔽因为编译时不会报错运行时才出问题。后来我养成了一个习惯在调试阶段把栈大小设大一些等程序稳定后再逐步调小。6. 进阶方向从裸机到RTOS再到嵌入式Linux当你把STM32的基本外设都玩过一遍之后接下来往哪个方向走这个问题没有标准答案取决于你的职业规划和项目需求。我把自己了解的几条路径分享一下。6.1 裸机开发的瓶颈与RTOS的引入时机裸机开发就是用一个大循环while(1)加上中断来处理所有任务。简单项目这么做完全没问题但当任务数量增多、实时性要求提高时裸机就会力不从心。比如你同时要处理串口数据、刷新显示屏、读取传感器、控制电机这些任务的优先级和时序要求各不相同用一个大循环很难保证每个任务都能及时响应。这时候就需要引入RTOS实时操作系统比如FreeRTOS、RT-Thread、ThreadX。RTOS的核心是任务调度器它可以把不同的功能拆分成独立的任务每个任务有自己的优先级和栈空间调度器根据优先级决定什么时候运行哪个任务。什么时候该上RTOS我的判断标准是当你的裸机程序里出现了多个需要“同时”处理的任务而且任务之间的时序关系变得难以用中断和状态机管理时就该考虑RTOS了。但也不要为了用而用——一个简单的LED闪烁加串口打印的项目上RTOS就是杀鸡用牛刀。6.2 嵌入式Linux与STM32的定位差异经常有人问学完STM32之后要不要转嵌入式Linux我的回答是这取决于你想做什么方向。STM32代表的是MCU开发特点是实时性强、功耗低、成本低、无需操作系统或轻量级RTOS。适合工业控制、传感器节点、消费电子等场景。嵌入式Linux代表的是MPU开发微处理器特点是处理能力强、支持复杂操作系统、可以跑图形界面和网络协议栈。适合智能家居中控、工业网关、视频处理等场景。两者的知识体系有重叠比如C语言、硬件基础、通信协议但也有很多不同。Linux开发需要掌握操作系统原理、设备驱动模型、文件系统、Shell脚本等。从STM32转Linux不是简单的“升级”更像是换了一个赛道。我的建议是先把STM32做深做透有了扎实的嵌入式基础之后再根据职业需要决定是否拓展Linux方向。6.3 几个值得动手的练手项目如果你已经掌握了基本外设想找项目练手这几个方向比较有代表性超声波测距用HC-SR04模块配合定时器的输入捕获功能测量回波时间计算距离。涉及GPIO输出触发、定时器捕获、中断处理是一个很好的综合练习。ILI9341显示屏驱动通过SPI接口驱动TFT彩屏涉及SPI通信、DMA传输、图形库移植。调试时可以读取ILI9341的ID寄存器通常是0xA1A1确认通信是否正常。CAN总线通信CAN在汽车电子和工业控制中应用广泛。用两块STM32板子通过CAN收发器互联实现数据互传。CAN的坑主要在波特率配置和终端电阻匹配上。步进电机控制用STM32的定时器输出PWM驱动步进电机驱动器实现加减速和位置控制。五线四相步进电机的接线方式和驱动逻辑需要仔细看手册。这些项目网上都有大量参考资料但不要直接抄代码。我的做法是先看懂原理然后自己从零写一遍遇到问题再查资料。这样学到的东西才是自己的。7. 一些零散但重要的经验最后这部分没有固定的主题就是我在实际项目中积累的一些零散经验可能不成体系但每一条都是踩过坑之后总结出来的。关于芯片的第一脚确认拿到芯片或开发板时确认第一脚的位置非常重要。芯片表面通常有一个小圆点或者缺口标记对应第一脚。如果芯片已经焊在板子上看不清标记可以找板子上的丝印通常会有“1”或者一个方形的焊盘标记。接反电源或者把信号接到错误的引脚上轻则功能异常重则烧毁芯片。关于ADC通道切换STM32的ADC在多通道采集时切换通道后需要一定的稳定时间。如果切换后立刻启动转换采到的值可能是上一个通道的残留。解决办法是在切换通道后加一小段延时或者使用ADC的扫描模式配合DMA自动轮询多个通道。关于电源设计STM32对电源质量有一定要求。VDDA模拟电源和VDD数字电源之间建议用磁珠或电感隔离并且各自加去耦电容。如果ADC采集的值跳动很大首先检查电源是否干净。我遇到过一个案例ADC读数一直在跳最后发现是开关电源的纹波太大换成LDO供电后立刻稳定了。关于看门狗在产品级项目中看门狗是必须的。STM32有独立看门狗IWDG和窗口看门狗WWDG。独立看门狗用内部低速时钟即使主时钟挂了也能工作。窗口看门狗则要求喂狗时间在特定窗口内太早或太晚都会复位。调试阶段可以先禁用看门狗但量产固件里一定要开启。关于固件升级很多项目需要支持固件升级OTA。STM32的IAP在应用编程功能可以实现这个需求把Flash分成Bootloader区和App区Bootloader负责接收新固件并写入App区然后跳转执行。实现IAP的关键是理解中断向量表的偏移和跳转逻辑这部分内容展开讲可以单独写一篇这里就不细说了。关于低功耗如果项目是电池供电的低功耗设计就至关重要。STM32支持睡眠、停止、待机三种低功耗模式功耗依次降低但唤醒时间依次增加。选择哪种模式取决于你的唤醒频率和响应时间要求。另外外设的时钟一定要记得关闭——一个没关的串口时钟可能让待机功耗翻倍。关于代码规范嵌入式代码的可维护性往往被忽视。我的建议是变量命名要有意义函数职责要单一中断服务函数里不要做耗时操作全局变量尽量少用。这些规范在项目小的时候看不出好处但当项目变大、需要多人协作时就是救命稻草。关于工具的使用VSCode配合PlatformIO或者STM32CubeCLT可以搭建一套轻量级的开发环境代码补全和跳转体验比Keil好很多。但调试功能还是Keil或IAR更成熟。我的做法是用VSCode写代码用Keil做编译和调试各取所长。关于学习路线嵌入式学习没有捷径但有路径。我的建议是先搞定GPIO和定时器再学串口和中断然后攻克SPI、I2C、ADC最后上RTOS和复杂项目。每学一个外设不要只看教程要自己动手写一遍遇到问题自己查手册解决。这个过程很慢但基础会打得非常扎实。嵌入式这个领域入门容易精通难。STM32只是一个起点后面还有很长的路要走。但只要你保持动手、保持好奇、保持记录每踩一个坑都是一次成长。我在这个领域摸爬滚打这么多年最大的体会就是不要怕犯错怕的是犯了错不知道为什么错。把每一次调试都当成一次学习的机会时间长了你自然就成了别人眼中的“大佬”。
返回列表