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 | 右侧最下 | 数字 IO | RX(串口接收) | 上传程序时被占用 |
| D1 | 右侧最下 | 数字 IO | TX(串口发送) | 上传程序时被占用 |
| D2 | 右侧 | 数字 IO | INT0、PCINT18 | 外部中断首选 |
| D3 | 右侧 | 数字 IO | INT1、PCINT19、PWM、OC2B | PWM 频率约 490Hz |
| D4 | 右侧 | 数字 IO | PCINT20 | |
| D5 | 右侧 | 数字 IO | PWM、OC0B | 频率约 976Hz |
| D6 | 右侧 | 数字 IO | PWM、OC0A | 频率约 976Hz |
| D7 | 右侧 | 数字 IO | PCINT23 | |
| D8 | 右侧 | 数字 IO | PCINT0 | |
| D9 | 右侧 | 数字 IO | PWM、OC1A、PCINT1 | 频率约 490Hz |
| D10 | 右侧 | 数字 IO | PWM、OC1B、SS、PCINT2 | SPI 片选 |
| D11 | 右侧 | 数字 IO | PWM、OC2A、MOSI、PCINT3 | SPI 数据输出 |
| D12 | 右侧 | 数字 IO | MISO、PCINT4 | SPI 数据输入 |
| D13 | 左侧最上 | 数字 IO | SCK、PCINT5、板载 LED | 做输入时注意漏流 |
| A0 | 左侧 | 模拟输入 0 | PCINT8 | 可当数字口用 |
| A1 | 左侧 | 模拟输入 1 | PCINT9 | 可当数字口用 |
| A2 | 左侧 | 模拟输入 2 | PCINT10 | 可当数字口用 |
| A3 | 左侧 | 模拟输入 3 | PCINT11 | 可当数字口用 |
| A4 | 左侧 | 模拟输入 4 | SDA、PCINT12 | I2C 数据线 |
| A5 | 左侧 | 模拟输入 5 | SCL、PCINT13 | I2C 时钟线 |
| 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 主板本身 | 15mA | 25mA | — |
| 板载 LED(D13) | 5mA | 10mA | 主板内部 |
| 数字温湿度传感器 | 1mA | 1.5mA | 5V |
| 0.96 寸 OLED | 15mA | 25mA | 3V3 或 5V |
| 蜂鸣器(无源) | 20mA | 30mA | 5V |
| 微型舵机 | 100mA | 700mA | 独立 5V 电源 |
| 单路继电器模块 | 20mA | 70mA | 5V(光耦隔离) |
加起来峰值接近 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 频率 | 说明 |
|---|---|---|---|---|
| D5 | Timer0 | OC0B | 约 976Hz | 与 millis() 共用 |
| D6 | Timer0 | OC0A | 约 976Hz | 与 millis() 共用 |
| D9 | Timer1 | OC1A | 约 490Hz | 16 位定时器,相位修正 |
| D10 | Timer1 | OC1B | 约 490Hz | 同上 |
| D3 | Timer2 | OC2B | 约 490Hz | 8 位定时器 |
| D11 | Timer2 | OC2A | 约 490Hz | 8 位定时器 |
频率是怎么算出来的?以 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/D1 | Serial | 9600~115200 | 占用后无法上传程序 |
| I2C | A4/A5 | Wire | 100k/400kHz | 上拉不足、地址冲突 |
| SPI | D10~D13 | SPI | 最高 8MHz | SS 未设输出导致失效 |
三套总线之间互相独立,可以同时使用,但引脚不能重复分配。比如你用了 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 的瓷片电容,效果立竿见影。
第五条:手上常备一张打印出来的引脚图。屏幕上看图是一回事,接线时手忙脚乱地切窗口是另一回事。我工位上贴的那张已经被杜邦线划得乱七八糟,但用得最顺手。引脚这件事,看一百遍不如亲手量一遍。