ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Arduino Nano 引脚分配实战:复用关系、电源边界与 PWM 排查

Arduino Nano 引脚分配实战:复用关系、电源边界与 PWM 排查

Arduino Nano 引脚分配这件事,看起来是最基础不过的功课,但我在帮别人排查问题的这些年里,真正被它绊倒的人远比想象中多。有人把传感器接到 D0/D1,程序怎么都传不上去;有人拿 A6、A7 当数字口用,折腾一下午以为是板子坏了;还有人用 D5 驱动舵机、D3 驱动蜂鸣器,结果舵机抖得像抽风,最后发现是 PWM 频率不一致。这些问题的共同点是:原理图没看、引脚定义没记牢。这篇文章我把 Arduino Nano 的 30 个引脚从头到尾拆一遍,包括物理布局、复用关系、电源边界、频率参数,再给一套可以直接跑的自检程序和排查表。不管你是刚拆封第一块 Nano 的新手,还是已经堆了几十块板子、想把手头资料整理清楚的老手,应该都能从里面找到一点能用的东西。

1. 先把这块板子的物理布局看清楚

1.1 两排 15 脚,位置比编号更重要

手头这块 Nano 用的是 DIP-30 封装,两排各 15 个焊盘,标准 2.54mm 间距,两排之间的宽度是 15.24mm,也就是常说的 0.6 英寸。这个尺寸意味着它能直接插在标准面包板中缝两侧,但要注意面包板中间凹槽的宽度,插之前先把针脚对齐了再往下压,硬怼很容易把排针压歪,后面接触不良查半天都查不出来。把 USB 接口朝上、元件面朝向自己,就是官方引脚图的默认视角,两侧各 15 个脚,顺序固定。

左侧这一排从 USB 那头往下数,依次是 D13、3V3、AREF、A0 到 A7、5V、RST、GND、VIN;右侧这一排从 USB 那头往下数,依次是 D12、D11、D10、D9、D8、D7、D6、D5、D4、D3、D2、GND、RST、D0(RX)、D1(TX)。记住一个规律:数字口在两排都有分布但右侧连续排了一串,模拟口全在左侧下段,电源和复位挤在左下角。这个布局不是随意安排的,它沿着芯片 TQFP-32 封装的引脚顺序走线,尽量缩短 PCB 上的走线长度。

不同厂家的兼容板在丝印上会有细微差别,有的把 A6、A7 标在更靠外的位置,有的把两个 GND 标成一上一下,还有个别板把 RST 挪到 VIN 旁边。功能完全一致,但上手前一定对着丝印确认一遍,别凭记忆插。我见过有人照着某块兼容板的照片接线,结果插到自己板子上差了一位,5V 捅进 GND,芯片当场发烫。

1.2 一张表看懂全部 30 个引脚定义

下面这张表是我平时贴在工位上的速查版,按功能分组,把每个引脚的复用能力都标出来了。建议你也打印一份,接线的时候比翻资料快得多。

引脚位置主要功能复用能力备注
D0右侧最下数字 IORX(串口接收)上传程序时被占用
D1右侧最下数字 IOTX(串口发送)上传程序时被占用
D2右侧数字 IOINT0、PCINT18外部中断首选
D3右侧数字 IOINT1、PCINT19、PWM、OC2BPWM 频率约 490Hz
D4右侧数字 IOPCINT20
D5右侧数字 IOPWM、OC0B频率约 976Hz
D6右侧数字 IOPWM、OC0A频率约 976Hz
D7右侧数字 IOPCINT23
D8右侧数字 IOPCINT0
D9右侧数字 IOPWM、OC1A、PCINT1频率约 490Hz
D10右侧数字 IOPWM、OC1B、SS、PCINT2SPI 片选
D11右侧数字 IOPWM、OC2A、MOSI、PCINT3SPI 数据输出
D12右侧数字 IOMISO、PCINT4SPI 数据输入
D13左侧最上数字 IOSCK、PCINT5、板载 LED做输入时注意漏流
A0左侧模拟输入 0PCINT8可当数字口用
A1左侧模拟输入 1PCINT9可当数字口用
A2左侧模拟输入 2PCINT10可当数字口用
A3左侧模拟输入 3PCINT11可当数字口用
A4左侧模拟输入 4SDA、PCINT12I2C 数据线
A5左侧模拟输入 5SCL、PCINT13I2C 时钟线
A6左侧仅模拟输入 6无不能做数字输入输出
A7左侧仅模拟输入 7无不能做数字输入输出
VIN左侧最下外部电源输入无建议 7~12V
5V左侧5V 电源输出/输入无USB 供电时输出 5V
3V3左侧3.3V 输出无由板载串口芯片提供,电流很小
AREF左侧模拟参考电压无外接参考时慎用
RST两侧各一复位无低电平复位
GND两侧各一地无两个脚内部连通
GND左/右地无同上

表格里最容易被忽略的是最后几行。很多人以为 A6、A7 跟 A0 到 A5 一样是"模拟口兼数字口",实际不是。ATmega328P 只有 8 个 ADC 输入通道,但 TQFP-32 封装里只有 6 个通道的引脚同时具备数字 IO 功能,A6、A7 是纯模拟输入,只能读电压,不能输出电平、不能上拉、不能用 digitalWrite。想用它们驱动一个 LED?门都没有。

1.3 版本差异:V3、Every、33 系列千万别混着记

市面上还流通着好几种"叫 Nano"的板子,引脚外形相似,内部完全是另一套东西。最常见的经典款是 Nano V3.0,主控 ATmega328P,5V 逻辑,16MHz 晶振,30 个引脚。Nano Every 换成了 ATmega4809,主频 20MHz,逻辑电压还是 5V,但引脚排列和 ADC 位数都不一样,部分引脚能输出真正的模拟电压(DAC 类似功能)。Nano 33 IoT 和 Nano 33 BLE 是 3.3V 逻辑的 32 位板子,主控是带 ARM 内核的芯片,模拟口 12 位,D 口编号方式也不同。

这三类板子最危险的混用点在于电平。3.3V 板子的 IO 口绝对不能直接接 5V 信号,一接一个准。反过来,5V 板子接 3.3V 传感器,低压信号有时能识别(因为阈值大约在 0.6 倍 VCC,也就是 3V),但边沿不可靠,长线一跑就误触发。更别说供电,V3 的 3V3 脚最多只能给出几十毫安,接个屏幕就掉压。买板子时看清楚丝印上的型号,别只看"Nano"两个字。

2. 电源与地:最容易被忽视、也最容易烧板的一组

2.1 VIN、5V、3V3 三个电源脚,用途完全不同

VIN 是外部电源输入口,接的是板载线性稳压器的输入端。官方给的建议范围是 7V 到 12V,绝对极限大约 6V 到 20V,但真要按照 20V 去用,稳压器会烫得没法碰。稳压器是常见的 AMS1117 类芯片,压差大约 1.1V,也就是说输入电压至少要 6.2V,5V 输出才能稳住。我曾经用 6V 电池盒接过一次,空载还行,一旦带起继电器模块,输出电压立刻掉到 4.6V,板子反复重启,换成 9V 就正常了。

5V 这个脚是双向的。板子用 USB 供电时,它对外输出 5V,可以给传感器、小屏幕供电;当 VIN 有输入时,它同样是稳压后的 5V 输出。但如果从外部直接给这个脚灌 5V,就会绕过稳压器直接连到整个 5V 网络,这时候 USB 绝对不能同时插,否则两个电源互相倒灌,轻则保护二极管发热,重则烧掉 USB 口或者电脑的主板供电。我的做法是:只要外接 5V 直供,就贴个胶带在 USB 口上,逼自己记住不能插。

3V3 这个脚是很多人的认知盲区。它不是板载稳压器给的,而是板载 USB 转串口芯片自带的 3.3V 输出,最大电流通常只有 50mA 左右。接一个 3.3V 的温湿度传感器没问题,接 3.3V 的屏或者无线模块就很可能不够,表现为电压被拉低、板子复位。要带这类负载,老老实实外挂一个 3.3V 稳压模块,别指望这个脚。

2.2 GND、AREF、RST 这几个"辅助脚"的讲究

板上有两个 GND 脚,位置一左一右,内部是连通的。这么设计是为了方便接线,尤其是同时接模拟传感器和数字外设的时候,两边就近取地,减少走线长度。但要注意,虽然内部连通,回流路径还是有区别的。大电流负载(比如电机、继电器)的地千万别从模拟口旁边的 GND 取,否则大电流在地线上产生的压降会直接叠加到 ADC 读数上,读数开始乱跳。

AREF 是模拟参考电压输入脚。默认情况下,ADC 用的是内部 5V 参考,不需要接任何东西。想提高小信号分辨率时,可以接一个更低的、稳定的参考电压(比如 2.5V 基准源),然后在代码里调用 analogReference(EXTERNAL)。这里有个坑:ATmega328P 从外部参考切回默认参考,光调函数不生效,必须断电重启才能恢复。我见过有人在程序里来回切参考模式,结果读数一直不对,找了两小时才发现是这个特性。

RST 有两个脚,功能一样,接低电平就复位。外接复位按钮或者看门狗电路时用得上。要注意复位脚内部有上拉,平时是高电平,接线的时候别把它接到 GND 附近容易短路的地方。想禁用复位功能(比如把它当普通 IO 用)需要改熔丝位,风险不小,一般不建议动。

2.3 供电方案怎么选,先算电流再动手

选供电方案这件事,我的习惯是先列一张电流预算表,把所有外设的峰值电流加起来,再留 30% 余量。下面这张表是我给一个典型小项目估的,你可以直接套用这个思路。

负载典型电流峰值电流取电位置
Nano 主板本身15mA25mA—
板载 LED(D13)5mA10mA主板内部
数字温湿度传感器1mA1.5mA5V
0.96 寸 OLED15mA25mA3V3 或 5V
蜂鸣器(无源)20mA30mA5V
微型舵机100mA700mA独立 5V 电源
单路继电器模块20mA70mA5V(光耦隔离)

加起来峰值接近 900mA,远超板载稳压器的能力。这时候正确做法是:主板自己用一路电源(USB 或者 VIN 接 7.5V),舵机、继电器用另一路 5V 大电流电源,两路的地必须共起来。共地这件事必须做,不共地信号就没有共同参考点,继电器控制信号飘忽不定,舵机也会乱转。

还有一点经验:ATmega328P 每一个 IO 脚的绝对最大电流是 40mA,推荐长期工作在 20mA 以内;每个端口组(B、C、D)的总电流上限大约 100mA;整颗芯片 VCC 和 GND 引脚的总电流上限 200mA。这几个数字是硬约束,超了不是"可能会坏",是"早晚会坏"。驱动 LED 时记得串限流电阻,5V 供电、普通红色 LED 压降 1.8V、想跑 10mA,电阻就是 (5-1.8)/0.01 = 320Ω,取 330Ω 就近的标准值。这步计算别省。

3. 数字口与 PWM、外部中断:编号背后的复用关系

3.1 D0 到 D13 的编号陷阱

Nano 的 14 个数字口在板子上标的是 D0 到 D13,代码里 directly 写 0 到 13 就行,跟丝印编号完全对应。这一点比某些开发板省心,不用查映射表。但有两个编号一定要单独拎出来说:D0 和 D1。

这两个脚默认连着板载 USB 转串口芯片的 RX 和 TX,也就是下载程序和串口打印都走它们。如果你把外设接到 D0/D1 上,上传程序时就会冲突,表现是编译通过了、上传卡在"avrdude: stk500_recv(): programmer is not responding",反复重试都不行。解决办法很简单:上传前把 D0/D1 上的线拔了,或者干脆一开始就别用这两个脚,留作调试专用。

串口通信的正确用法是:程序里用 Serial.begin(9600) 之类初始化,数据从 D1 发出去、从 D0 收进来,同时通过 USB 线在电脑的串口监视器里看。想接 GPS、蓝牙模块这类串口设备时,如果设备只发不收,可以直接接 D0(板子接收),但要记住上传程序时断开。更好的是用软件串口库,把通信挪到 D2、D3 这类空闲脚上,硬件串口留给调试。

3.2 六路 PWM 的真实频率,决定了你的电机响不响

板子上标着波浪号或者 PWM 的脚一共 6 个:D3、D5、D6、D9、D10、D11。它们分属三个定时器,频率并不一致,这一点绝大多数入门教程都不提,但实际用起来差别很大。

引脚定时器比较通道默认 PWM 频率说明
D5Timer0OC0B约 976Hz与 millis() 共用
D6Timer0OC0A约 976Hz与 millis() 共用
D9Timer1OC1A约 490Hz16 位定时器,相位修正
D10Timer1OC1B约 490Hz同上
D3Timer2OC2B约 490Hz8 位定时器
D11Timer2OC2A约 490Hz8 位定时器

频率是怎么算出来的?以 Timer0 为例,16MHz 主频,预分频 64,8 位快速 PWM 每 256 个计数一个周期,频率就是 16,000,000 ÷ (64 × 256) ≈ 976Hz。Timer1 和 Timer2 用的是相位修正模式,每个周期要数两遍(上升一遍下降一遍),所以是 16,000,000 ÷ (2 × 64 × 256) ≈ 488Hz,取整叫 490Hz。

这个差别带来的直接后果是:490Hz 落在人耳可听范围内,驱动无源蜂鸣器或者小电机时会有明显的啸叫和抖动。想让电机安静,要么换到 D5/D6,要么手动改定时器预分频。改 Timer1 的预分频能把 D9、D10 的频率拉到 31kHz 以上,超出人耳范围,但代码里要直接操作寄存器 TCCR1B,改完 analogWrite 的行为也会跟着变,得一起考虑。还有一点必须记住:Timer0 承担着 millis()、micros() 和 delay() 的计时任务,动它的预分频会把这些函数全部搞乱,除非你非常清楚后果,否则别碰 Timer0。

舵机是另一个大坑。常用的舵机库在 AVR 平台上默认占用 Timer1,也就是 D9 和 D10。一旦调用了舵机库,这两个脚的 analogWrite 就失效了,写进去没反应。更严重的是,如果舵机信号线正好接在 D9 或 D10,而你又想用另一路 PWM 调光,冲突排查起来非常费劲。我的习惯是:舵机固定接 D3 或者 D5,PWM 调光接 D6,把 D9、D10 留空。

3.3 外部中断只有两个,其余靠引脚变化中断

Nano 上能触发真正外部中断的只有 D2 和 D3,分别对应 INT0 和 INT1。用法是 attachInterrupt(digitalPinToInterrupt(2), 处理函数, 触发方式),触发方式可选 RISING、FALLING、CHANGE、LOW。这两个脚适合接旋转编码器、红外对管、按键这类需要即时响应的信号。

其他引脚并非完全不能中断,它们支持引脚变化中断(PCINT),也就是一组引脚共用同一个中断向量,触发后要在处理函数里自己判断是哪一个脚变了。这种方式在库层面封装得不太好,普通项目用不上,但如果你的项目需要同时监听七八个传感器,又不想轮询,可以用 PinChangeInterrupt 这类第三方库。代价是中断响应会稍微慢一点,因为要额外判断来源。

用外部中断有三条经验值得记:第一,中断处理函数里只做标记,别做耗时操作,更不能调用 delay() 和 Serial.print(),否则主程序会卡死;第二,机械按键一定要做消抖,硬件上并一个 0.1μF 电容,软件上在中断里记录时间戳、间隔小于 20ms 就忽略;第三,如果用内部上拉,接法是按键一端接引脚、另一端接 GND,按下时读到低电平,这样最省外围元件。

3.4 D13 的板载 LED 是个甜蜜的陷阱

D13 上挂着一个板载 LED 加限流电阻,方便你跑 Blink 测试。这块板子的 LED 支路是直接并在引脚上的,没有加缓冲器。这意味着什么?当 D13 配置成输入时,这个 LED 支路依然存在,会带来额外的漏电流,引脚上的电平可能被拉低,读值不准。我试过把 D13 当按键输入用,外部上拉 10kΩ,结果读到的始终是低电平,换成 D12 立刻正常。

所以用 D13 有几条准则:做输出没问题,驱动 LED 或者当状态指示都行;做输入尽量避开,尤其是高阻抗信号;做 SPI 的 SCK 时也还好,因为 SPI 是推挽输出。另外,如果你的项目对功耗敏感,D13 上的 LED 会带来几毫安的额外消耗,深睡眠场景下要把它设成输入并关闭上拉。

4. 模拟口、串口、I2C、SPI:通信类引脚的复用与冲突

4.1 A0 到 A7,前六个和后两个是两种东西

A0 到 A7 一共 8 个模拟输入,ADC 是 10 位精度,读到 0 到 1023 的整数。换算电压的常用公式是 读数 × 参考电压 ÷ 1023。严格来说 10 位 ADC 有 1024 个量化台阶,除以 1024 更准确,但 Arduino 生态里统一用 1023,两种算法的误差在小数点后几位,日常测量无所谓,做精密测量就要自己校准。

关键区别在这里:A0 到 A5 除了模拟输入,还能当普通数字口用,代码里写 digitalRead(A0) 或者直接用编号 14 到 19 都能工作;A6 和 A7 是纯模拟输入,只能 analogRead,不能 digitalWrite,不能开内部上拉,也不能配置成输出。为什么?因为 TQFP-32 封装引脚数量有限,A6、A7 复用的是芯片上只保留 ADC 功能的引脚。

这个限制在实际项目里经常咬人。比如你想接 8 路模拟传感器,同时又想用两个数字口驱动机器人的方向控制,结果发现 A6、A7 占了位置却干不了数字活,只能从别处挤。还有一个更隐蔽的坑:A6、A7 没有内部上拉,如果接的是悬空的模拟信号源,读数会满量程乱跳,看着像传感器坏了,其实是浮空输入。

模拟读数的稳定性还跟参考电压直接相关。默认用 5V 供电做参考,而 USB 供电的 5V 实际上可能在 4.75V 到 5.25V 之间波动,读数就会跟着漂。要测毫伏级的小信号,有两个办法:一是用内部 1.1V 参考(analogReference(INTERNAL)),把量程压到 0 到 1.1V,分辨率立刻提高四倍多;二是外接一个 2.5V 或 4.096V 的基准源到 AREF。我一般用第一种,改一行代码就完事,代价是量程变小,超过 1.1V 的信号会读满。

4.2 串口、I2C、SPI 三套总线的引脚归属

串口用 D0(RX)和 D1(TX),前面已经说过 ocupied 的问题。这里补充一个细节:串口是硬件外设,收发都是独立进行的,发送时不会因为接收等待而卡住,所以主程序里用 Serial.print 打印调试信息几乎不影响实时性。但波特率太高(比如 115200)时,长数据的打印会占掉不少时间,做高速采样的时候要注意把打印放在采样完成之后。

I2C 固定在 A4(SDA)和 A5(SCL)上,这是硬件 I2C,速度标准模式 100kHz、快速模式 400kHz。用法是包含 Wire 库,Wire.begin() 初始化,然后按地址读写。Nano 板上通常没有专门的 I2C 上拉电阻,很多传感器模块自己带了 4.7kΩ 到 10kΩ 的上拉,直接接上就能用。但如果你的总线上挂了多个裸芯片模块、或者线拉得比较长(超过 30cm),上拉不够会导致通信失败,表现为程序卡在 Wire.endTransmission() 返回非零错误码。这时在 SDA 和 SCL 上各补一个 4.7kΩ 到 5V 的上拉电阻,问题基本就解决了。

SPI 用的是 D10(SS)、D11(MOSI)、D12(MISO)、D13(SCK),另外还有一个 ICSP 排针,六个针脚里包含 MISO、MOSI、SCK、RESET、VCC、GND,方便插排线。SPI 是全双工、速度最快的片上总线,接 SD 卡、TFT 屏、无线模块都用它。用的时候注意 SS 脚即使不接从设备,也要设成输出,否则芯片可能被误触发进入从机模式,SPI 通信直接失效。这是 AVR 芯片的一个已知特性,很多库内部会自动处理,但自己写底层代码时必须设。

总线引脚库典型速率常见坑
串口D0/D1Serial9600~115200占用后无法上传程序
I2CA4/A5Wire100k/400kHz上拉不足、地址冲突
SPID10~D13SPI最高 8MHzSS 未设输出导致失效

三套总线之间互相独立,可以同时使用,但引脚不能重复分配。比如你用了 SPI 的 SD 卡,D10 到 D13 就被占了,再想接个需要外部中断的传感器,就只能用 D2 或 D3。做项目规划的时候,先在纸上把引脚画一遍,标清楚哪个脚给哪个外设,比写代码时才发现冲突要省事得多。

5. 实操:从零做一次完整的引脚自检

5.1 硬件准备与接线检查

拿到一块新板子或者一块来源不明的二手板,我第一件事是做引脚自检,而不是直接上项目。需要准备的东西很简单:一块面包板、若干杜邦线、一个万用表、一个 220Ω 电阻加一个 LED 用于验证输出。接线之前先用万用表蜂鸣档测两件事:一是两个 GND 是否导通,二是 5V 与 GND 之间是否短路。二手板最容易出的问题就是电源脚短路,插上 USB 之前先测一遍能救回一条命。

把板子插上面包板时,注意 USB 接口那一端朝外,方便插线。杜邦线选公对公的,插拔几次之后如果发现松动,直接换,接触不良引起的间歇性故障最难查。测试 LED 串 220Ω 电阻后接到 D5 和 GND 之间,用来做视觉确认。

5.2 一段可以直接跑的引脚巡检程序

下面这段程序把 D2 到 D12 全部配置成内部上拉输入,然后循环读取每个脚的状态并通过串口打印。脚悬空时读 1,把某个脚接 GND 时读 0,用它来验证每个数字口是否正常工作。

const uint8_t pins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; void setup() { Serial.begin(115200); delay(300); Serial.println(F("Nano pin scan ready")); for (uint8_t i = 0; i < sizeof(pins); i++) { pinMode(pins[i], INPUT_PULLUP); } } void loop() { for (uint8_t i = 0; i < sizeof(pins); i++) { uint8_t p = pins[i]; uint8_t v = digitalRead(p); Serial.print(F("D")); Serial.print(p); Serial.print(F("=")); Serial.print(v); Serial.print(F(" ")); } Serial.println(); delay(500); }

跑起来之后,串口监视器里会不停地滚动输出,每个脚一个字符。用一根公对公杜邦线,一头接 GND,另一头依次点触 D2 到 D12,点在哪个脚上,那个脚的值就从 1 变成 0。全部正常响应,说明这 11 个数字口都能正常读取。如果某个脚始终是 0,可能是内部上拉坏了或者引脚虚焊;如果始终是 1,可能有外部短路,检查一下板子背面。

接下来验证输出和 PWM。把 LED 的正极接 D5,负极串 220Ω 电阻到 GND,跑下面这段呼吸灯代码,观察亮度是否平滑变化。

void setup() { pinMode(5, OUTPUT); } void loop() { for (int d = 0; d <= 255; d += 5) { analogWrite(5, d); delay(20); } for (int d = 255; d >= 0; d -= 5) { analogWrite(5, d); delay(20); } }

如果亮度变化有台阶感、或者中途闪一下,检查是不是把 LED 接到了 D9、D10 而程序里正好用了舵机库。正常情况下,这段代码在 D5 上跑出来的呼吸效果是很顺滑的。

5.3 用万用表验证输出电压与上拉能力

代码跑通只是第一层,物理层还得再验一遍。把万用表调到直流电压档,黑表笔接 GND,红表笔去量各个引脚。数字口设置为 HIGH 时,读数应该在 4.8V 到 5.0V 之间;设置为 LOW 时应该接近 0V,通常小于 0.1V。如果 HIGH 状态只有 3V 左右,说明这一路可能被外部负载拉低了,或者引脚内部驱动能力受损,回头检查是不是曾经直接驱动过电机或者大电流 LED。

还要量一下内部上拉的实际效果。把引脚设为 INPUT_PULLUP,不接任何外部电路,用万用表量该脚对地的电压,正常应该在 4.8V 以上。然后接一个 10kΩ 电阻到地,电压应该掉到 2.5V 附近,说明上拉电阻(内部大约 20kΩ 到 50kΩ)与外部电阻形成了分压。这个测试能帮你判断内部上拉是否真的生效,有些国产兼容板的上拉电阻偏差很大,做按键检测时会误判。

最后量一下 5V 和 3V3 的实际输出。USB 供电时,5V 应该在 4.9V 左右;3V3 应该在 3.3V 附近。如果 3V3 只有 3.0V,说明这颗串口芯片的 3.3V 稳压性能一般,接传感器时要留意。

6. 常见问题与排查速查

6.1 六类典型故障的现象与处理

引脚相关的问题看着花样多,其实归归类就那几大种。第一个高频问题是上传失败,串口监视器报 programmer is not responding。九成以上是 D0、D1 被外设占用,拔掉外设再传一次就行。如果还不行,检查板子在工具菜单里选的型号对不对,processor 一定要选 ATmega328P,老款板子有时候要选 Old Bootloader。

第二个高频问题是模拟读数乱跳。先看是不是 A6、A7 接了浮空信号,这两个脚没有内部上拉,浮空必然乱跳。再检查模拟地和数字地有没有分开走线,大电流负载有没有从模拟区取电。如果跳动幅度在正负两三个数以内,那是 ADC 的正常噪声,取 10 次平均就能压下去。

第三个问题是 PWM 驱动电机有啸叫。这就是前面算过的频率问题,490Hz 落在可听范围内。把负载换到 D5 或 D6,或者改 Timer1 预分频。

第四个问题是 I2C 设备时有时无。先跑一个 I2C 扫描程序,看设备地址能不能稳定扫到,然后检查上拉电阻和线长。杜邦线超过 30cm 就很容易出问题,换成排线或者加屏蔽会好很多。

第五个问题是舵机抖动。九成是供电不足,舵机启动瞬间拉走几百毫安,板载 5V 直接被拉垮。给舵机单独供电、共地,问题立刻消失。

第六个问题是引脚烧毁。表现是这个脚无论怎么设置都读不到正确值,或者一直输出高电平。通常是因为直接驱动了超过 40mA 的负载,或者把 5V 接到了配置成输出的引脚上。芯片不一定会全坏,但烧坏的引脚没法修,只能避开不用。

现象最可能原因快速验证方法处理方式
上传卡住不响应D0/D1 被占用拔掉所有外设再传改用 D2/D3 做通信
模拟读数跳动大浮空输入、地线干扰接一个已知电压测试加下拉、分地走线、取平均
PWM 负载啸叫频率落在音频段换到 D5/D6 试改定时器预分频
I2C 扫描不到设备上拉不足量 SDA/SCL 静态电压补 4.7kΩ 上拉
舵机来回抖动供电电流不足量舵机动作时的 5V独立供电、共地
某脚无响应引脚损坏万用表量输出电平换脚、标记报废

6.2 几条踩出来的经验

第一条:接线之前先在纸上画一遍引脚分配。我吃过不止一次亏,代码写到一半发现 I2C 和某个数字口抢了同一个定时器,或者传感器需要的脚正好是 SPI 的片选,只能推倒重来。画图花五分钟,返工省两小时。

第二条:D13 上的板载 LED 虽然方便,但别把它当成可靠的输出指示灯。它的亮度跟引脚驱动电流有关,某些兼容板的限流电阻偏大,看起来只有一点点微光。要状态指示,外接一个 LED 更靠谱。

第三条:给每个项目留一个"调试口"。我习惯把 D2、D3 空出来,接一个按键或者一个串口模块,出问题时能立刻挂上去看数据。全部引脚塞满的项目,后期调试会非常痛苦。

第四条:模拟传感器和数字外设的供电尽量分开。数字外设开关瞬间会产生很大的电流跳变,如果跟模拟传感器共用一条 5V 线,ADC 读数上会叠加毛刺。可以在模拟传感器的供电脚旁边并一个 100μF 的电解电容加 0.1μF 的瓷片电容,效果立竿见影。

第五条:手上常备一张打印出来的引脚图。屏幕上看图是一回事,接线时手忙脚乱地切窗口是另一回事。我工位上贴的那张已经被杜邦线划得乱七八糟,但用得最顺手。引脚这件事,看一百遍不如亲手量一遍。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进