嵌入式入门第一周:为什么我选Arduino而不是STM32
发布时间:2026/10/4 14:52:07 锦皓数字建站

1. 从零上手嵌入式为什么第一周我选了Arduino而不是STM32很多人一提到嵌入式入门第一反应就是买块STM32开发板装Keil啃寄存器手册。我身边不少朋友就是这么干的结果第一周卡在环境配置上第二周卡在时钟树配置上第三周直接放弃。这不是能力问题是路径选择的问题。我这次给自己定的目标是第一周必须把“代码能跑起来”这件事跑通建立正反馈再谈深入。所以选了Arduino Uno作为起点。原因很直接——它把工具链、烧录、基础外设驱动全部封装好了你写digitalWrite(13, HIGH)就能点亮板载LED不需要查任何寄存器手册。对于刚接触嵌入式的人来说先建立“输入代码→看到现象”的闭环比什么都重要。这一周的时间跨度是2026年9月21日到9月27日实际投入大概每天两到三小时。最终完成的内容包括开发环境搭建、LED闪灯、按钮控制LED、串口通信与串口监视器调试、以及一个按钮串口LED的综合小项目。下面按实际学习顺序展开每一步都附上我踩过的坑和验证过的操作细节。注意Arduino不是终点它是跳板。它的抽象层帮你跳过大量底层细节但到了第二、第三周你迟早要面对寄存器、中断、DMA这些东西。第一周的任务是“跑通”不是“学完”。2. 开发环境搭建Arduino IDE安装与板子识别的那些坑2.1 IDE下载与安装别从第三方站点拿安装包Arduino IDE目前有两个大版本经典版1.8.x和新版2.x。我建议新手直接用2.x版本界面更现代串口监视器和绘图器集成得更好。下载渠道只有一个——官网。第三方站点经常夹带旧版本或者捆绑软件我有个朋友从某下载站拿了个“汉化版”结果串口驱动死活装不上折腾了一晚上。安装过程本身没什么好说的一路下一步就行。但有一个细节Windows系统在安装过程中会弹出驱动安装提示一定要点“允许”或“安装”。这个驱动是Arduino Uno板载USB转串口芯片的驱动不装的话后面电脑识别不到板子。2.2 板子连接后识别不到先排查这三件事插上USB线之后打开IDE在“工具→端口”菜单里应该能看到一个类似COM3或COM4的选项。如果看不到按以下顺序排查换一根USB线。这是最常见的问题。很多USB线是“只供电不传数据”的尤其是从充电宝、小风扇之类设备上随手拿的那种。我第一晚就栽在这上面换了三根线才找到一根能传数据的。检查驱动。在Windows设备管理器里看“端口”分类下有没有黄色感叹号。如果有右键更新驱动手动指向Arduino安装目录下的drivers文件夹。换USB口。有些台式机前面的USB口供电不足或者接触不良换到主板后面的口试试。2.3 板子型号和端口的选择逻辑在“工具→开发板”里选Arduino Uno。如果你用的是其他型号比如Nano、ESP32选对应的。这里有个容易忽略的点端口号不是固定的。你今天插上去是COM3明天换个USB口可能就变成COM5了。所以每次打开IDE准备烧录之前先确认一下端口选对了没有。烧录失败十次里有三次是端口选错。提示如果你同时插了多块板子或者多个串口设备端口菜单里会出现多个选项。不确定哪个是Arduino的话拔掉板子看哪个选项消失了再插上看哪个选项出现了那个就是。3. 第一个程序LED闪灯背后的电路逻辑与代码结构3.1 板载LED和外部LED的区别Arduino Uno板上有一颗贴片LED标注为“L”连接在数字引脚13上。所以你写digitalWrite(13, HIGH)这颗灯就会亮。但如果你要外接LED就需要额外的元件LED灯珠、限流电阻、杜邦线。限流电阻怎么选这是新手最容易忽略的地方。LED的正向电压一般在1.8V到2.2V之间红色工作电流5mA到20mA。Arduino的数字引脚输出5V。如果直接接LED不加电阻电流会远超20mA轻则烧LED重则烧引脚。计算方式很简单R (5V - 2V) / 10mA 300Ω所以选一个220Ω到330Ω之间的电阻都行。我手头只有220Ω的实测电流在13mA左右LED亮度足够也不会过热。3.2 面包板接线正极长脚负极短脚LED有两个引脚长脚是正极阳极短脚是负极阴极。接线顺序是Arduino数字引脚8 → 电阻一端 → 电阻另一端 → LED长脚 → LED短脚 → Arduino GND。面包板上的孔是横向连通的中间有一条凹槽隔断凹槽两边的孔不连通。这个结构决定了你的元件怎么跨接。我第一次接线的时候把LED两个脚插在了同一列结果短路了灯不亮。后来才明白面包板的连通规则。建议新手拿到面包板之后先用万用表的通断档测一下哪些孔是连通的花五分钟搞清楚结构后面接线会快很多。3.3 代码结构setup和loop的分工Arduino程序的核心结构就两个函数void setup() { pinMode(8, OUTPUT); } void loop() { digitalWrite(8, HIGH); delay(1000); digitalWrite(8, LOW); delay(1000); }setup()里的代码只执行一次用来做初始化。loop()里的代码会无限循环执行。pinMode(8, OUTPUT)是把引脚8配置为输出模式。digitalWrite是设置引脚电平HIGH是5VLOW是0V。delay(1000)是延时1000毫秒也就是1秒。这里有个细节delay()是阻塞式的。在延时期间程序什么都做不了。如果你后面要做按钮检测或者串口接收delay()会严重影响响应速度。第一周先用delay()建立概念后面要换成millis()的非阻塞方式。4. 按钮控制LED上拉电阻、抖动与状态读取4.1 按钮为什么需要上拉或下拉电阻按钮的本质是一个开关。按下时两端导通松开时两端断开。如果你把按钮一端接5V另一端接数字引脚按下时引脚读到5VHIGH松开时引脚悬空——悬空的引脚电平是不确定的可能读到HIGH也可能读到LOW这叫“浮空”。解决方案有两种外接下拉电阻按钮接5V和引脚引脚再通过10kΩ电阻接地或者使用Arduino内部上拉电阻pinMode(2, INPUT_PULLUP)。我推荐用内部上拉省一个电阻接线也简单。用了内部上拉之后逻辑是反的松开时读到HIGH按下时读到LOW。4.2 按钮抖动为什么按一次会触发多次机械按钮在按下和松开的瞬间金属触点会有几毫秒的弹跳导致电平快速变化多次。如果你在代码里直接判断if (digitalRead(2) LOW)一次按下可能会被识别成好几次。解决方法有两种硬件消抖在按钮两端并联一个0.1μF电容和软件消抖检测到电平变化后延时20毫秒再读一次。第一周我用的软件消抖代码简单效果也够用void loop() { if (digitalRead(2) LOW) { delay(20); if (digitalRead(2) LOW) { digitalWrite(8, !digitalRead(8)); while (digitalRead(2) LOW); } } }最后那句while (digitalRead(2) LOW);是等待按钮松开防止按住不放时LED疯狂翻转。4.3 状态翻转的写法与常见错误digitalWrite(8, !digitalRead(8))这行代码的意思是读取引脚8当前的电平取反再写回去。这样就实现了“按一次亮再按一次灭”的效果。常见错误是写成digitalWrite(8, !digitalRead(8))之前先digitalWrite(8, LOW)那就永远只亮不灭了。还有一个错误是忘记在setup里把按钮引脚设为INPUT_PULLUP导致读数不稳定。注意按钮接内部上拉时按钮的一端接引脚另一端接GND不要接5V。接错了会一直读到LOW或者烧引脚。5. 串口通信从Serial.print到串口监视器的完整链路5.1 串口是嵌入式中最重要的调试手段没有串口你只能靠LED判断程序状态信息量极其有限。有了串口你可以打印变量值、打印状态信息、接收上位机指令。Arduino Uno的串口通过USB线连接到电脑在IDE里打开“串口监视器”就能看到板子发来的数据。初始化串口用Serial.begin(9600)参数是波特率。板子和监视器的波特率必须一致否则看到的是乱码。9600是最常用的也够稳定。如果你想传大量数据可以调到115200。5.2 Serial.print和Serial.println的区别Serial.print打印完不换行Serial.println打印完自动换行。调试信息一般用println方便阅读。如果要打印多个变量拼成一行可以这样Serial.print(Button state: ); Serial.println(digitalRead(2));输出结果是Button state: 1然后换行。5.3 串口监视器的几个实用设置串口监视器右上角有个波特率下拉菜单必须和代码里的Serial.begin一致。下面有个输入框可以发送数据给板子。发送格式有“无结束符”“换行”“回车”“回车换行”等选项。如果你在代码里用Serial.readString()接收建议选“换行”或“回车换行”这样能明确知道一条指令什么时候结束。我第一周用串口做了一个小功能电脑发送“1”点亮LED发送“0”熄灭LED。代码逻辑是void loop() { if (Serial.available() 0) { char cmd Serial.read(); if (cmd 1) { digitalWrite(8, HIGH); Serial.println(LED ON); } else if (cmd 0) { digitalWrite(8, LOW); Serial.println(LED OFF); } } }这个功能虽然简单但它是后面做“上位机控制下位机”的基础模型。6. 综合练习按钮串口LED三合一项目6.1 项目需求拆解把前面学的东西串起来一个按钮控制LED亮灭同时每次状态变化都通过串口打印出来。另外电脑也可以通过串口发送指令直接控制LED。这样既有本地控制又有远程控制还有状态反馈。需求拆解成三条按钮按下时LED状态翻转串口打印当前状态。串口收到“1”时LED点亮打印“LED ON”。串口收到“0”时LED熄灭打印“LED OFF”。6.2 完整代码与逐段解释const int LED_PIN 8; const int BUTTON_PIN 2; bool ledState false; void setup() { pinMode(LED_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); Serial.begin(9600); Serial.println(System ready); } void loop() { // 按钮检测 if (digitalRead(BUTTON_PIN) LOW) { delay(20); if (digitalRead(BUTTON_PIN) LOW) { ledState !ledState; digitalWrite(LED_PIN, ledState); Serial.print(Button pressed. LED: ); Serial.println(ledState ? ON : OFF); while (digitalRead(BUTTON_PIN) LOW); } } // 串口指令检测 if (Serial.available() 0) { char cmd Serial.read(); if (cmd 1) { ledState true; digitalWrite(LED_PIN, HIGH); Serial.println(Command: LED ON); } else if (cmd 0) { ledState false; digitalWrite(LED_PIN, LOW); Serial.println(Command: LED OFF); } } }用了一个bool ledState变量来记录当前LED状态这样按钮和串口两条控制路径不会互相冲突。如果不用变量记录按钮翻转之后串口再发指令状态就乱了。6.3 实测中遇到的三个问题问题一按钮按下后串口打印了多次。原因是while (digitalRead(BUTTON_PIN) LOW);这行等待松开的代码在某些劣质按钮上会卡住因为抖动导致电平在LOW和HIGH之间跳变。解决办法是在while循环里加一个超时或者改用更完善的消抖逻辑。问题二串口发送“1”之后LED亮了但按钮再按一次变成灭串口打印的状态和实际不一致。这是因为按钮翻转用的是ledState !ledState而串口设置的是ledState true两者都更新了同一个变量逻辑是对的。问题出在我一开始用digitalRead(LED_PIN)来读取LED状态但输出引脚的digitalRead返回值不一定等于digitalWrite设置的值。改成用变量记录就解决了。问题三同时按按钮和发串口指令时偶尔会丢指令。因为delay(20)和while等待松开期间串口数据可能已经到达但没被读取。这是阻塞式代码的固有问题后面学了中断和millis()之后可以解决。7. 第一周踩过的坑与验证过的经验7.1 硬件方面的坑坑一LED不亮以为是代码问题结果是LED插反了。长脚正极短脚负极这个一定要记住。如果不确定用万用表的二极管档测一下能微亮的就是正向。坑二按钮接线接成了5V和引脚之间用了内部上拉之后一直读到HIGH。内部上拉是把引脚通过电阻拉到5V按钮应该接在引脚和GND之间按下时把引脚拉到GND读到LOW。坑三面包板电源轨没连通。有些面包板的电源轨是分段式的中间断开。如果你从一端供电另一端的元件可能没电。用万用表测一下通断或者直接用跳线把两端连起来。7.2 软件方面的坑坑一串口监视器波特率选错看到一堆乱码。代码里是9600监视器里选了115200必乱。每次打开监视器先确认波特率。坑二烧录时忘记选端口IDE报错“avrdude: ser_open(): cant open device”。这个错误九成是端口没选对或者板子没插好。坑三delay()用太多导致按钮响应迟钝。如果loop里有delay(1000)按钮按下去要等一秒才被检测到。第一周先用delay建立概念但要知道它的局限性。7.3 学习节奏方面的体会第一周不要贪多。我见过有人第一天就想着驱动OLED屏幕、第二天就想连WiFi模块结果每个都只跑了个Demo什么都没深入。把LED、按钮、串口这三个东西吃透比囫囵吞枣跑十个例程有价值得多。具体来说“吃透”的标准是你能不看教程自己从零接线、写代码、调试通过。遇到问题能自己排查而不是第一时间去群里问。这一周我大概烧录了三十多次每次失败都记下来原因后面翻看的时候发现大部分问题都是重复的。8. 下周计划从Arduino抽象层走向寄存器操作第一周用Arduino把基本概念跑通了但心里要清楚digitalWrite背后是一堆寄存器操作Serial.begin背后是USART配置。这些封装让你快速上手但也屏蔽了底层细节。下周我打算做两件事一是用Wokwi仿真平台把同样的电路在浏览器里复现一遍验证自己对电路的理解是否准确二是开始看ATmega328P的数据手册搞清楚pinMode和digitalWrite到底操作了哪些寄存器。从Arduino到寄存器的过渡是嵌入式学习的关键一步这一步走稳了后面上STM32或者ESP32都会顺很多。如果你也在第一周我的建议是别急着换板子别急着买一堆模块。把手头这块板子的每一个引脚、每一个基础函数都摸清楚比什么都强。我第一周最大的收获不是学会了多少函数而是建立了一套“遇到问题→查资料→动手验证→记录总结”的循环。这套循环后面会一直用下去。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。