1. 项目概述
如果你手头有一块基于Microchip ATSAMD21微控制器的开发板,比如Arduino MKR Zero或者一些SparkFun的SAMD21开发板,并且厌倦了传统的C/C++开发流程,想体验一下Python在嵌入式设备上“即写即运行”的便捷,那么这篇文章就是为你准备的。我将带你一步步完成从一块“裸板”或仅支持Arduino的板子,到成功运行CircuitPython的完整过程。核心在于利用一个名为UF2的引导加载器,它能让你的开发板变身成一个U盘,之后安装CircuitPython就像拷贝文件一样简单。整个过程涉及Arduino环境配置、UF2引导加载器的烧录以及CircuitPython固件的部署,我会把每个环节的原理、操作细节和我踩过的坑都讲清楚,确保你一次成功。
2. 核心思路与准备工作
2.1 为什么选择CircuitPython + UF2这个组合?
在嵌入式开发中,传统的固件更新通常需要专用的编程器(如JTAG)或通过串口配合特定的烧录工具,步骤繁琐。UF2(USB Flashing Format)协议彻底改变了这一点。它本质上是一个运行在微控制器上的小程序(引导加载器),其核心功能是让芯片通过USB接口将自己模拟成一个USB大容量存储设备(Mass Storage Device)。对你来说,电脑上会直接出现一个可移动磁盘。要更新固件?只需把符合UF2格式的.uf2文件拖进去,引导加载器会自动识别并将其写入芯片的闪存。这个过程无需任何额外驱动或软件(在主流操作系统上),真正实现了“傻瓜式”刷机。
CircuitPython是Adafruit主导开发的一个Python 3的精简实现,专为微控制器设计。它与UF2是天作之合。一旦通过UF2安装了CircuitPython固件,你的开发板在电脑上会显示为一个名为CIRCUITPY的磁盘。你的Python代码文件(如code.py)直接放在这个磁盘里,板子就会自动执行。修改代码?直接编辑文件并保存,板子会自动重启运行新代码。这种开发体验极其友好,特别适合快速原型验证、教育和物联网设备开发。
那么,为什么我们的SAMD21板子一开始没有这些功能呢?很多通用SAMD21开发板出厂时搭载的是Arduino的默认引导程序(Bootloader),它只响应通过串口传来的特定编程协议(比如Arduino IDE使用的bossac)。我们的任务就是“替换”这个引导程序:先用Arduino环境把UF2引导加载器写进去,然后再用UF2的方式把CircuitPython固件写进去。听起来像是“用魔法打败魔法”,但逻辑是通的:利用板子现有的、可用的编程接口(Arduino Bootloader)来安装一个更强大的新接口(UF2 Bootloader)。
2.2 所需工具与材料清单
在开始动手前,请确保你手边有以下东西。别小看这个清单,缺了任何一样都可能让你卡在半路。
硬件:
- SAMD21开发板:本文以Arduino MKR Zero为主要示例,其他如SparkFun SAMD21 Dev Breakout等原理相通。请确认你的板子核心是ATSAMD21G18或类似型号。
- USB数据线:一根可靠的Micro-USB或USB-C数据线(取决于你的板子接口)。务必使用能传输数据和供电的线,有些充电线只有电源线,会导致电脑无法识别设备。
- 一台电脑:Windows、macOS或Linux均可。本文会涵盖各系统的差异点。
软件:
- Arduino IDE:这是我们的“跳板”。用于给板子上传最初的UF2引导加载器。建议从 arduino.cc 下载安装最新版。如果遇到上传问题,可以尝试版本1.8.x的稳定版。
- 文本编辑器:用于编写和修改Python代码。任何纯文本编辑器都可以,例如VS Code、Sublime Text、甚至系统自带的记事本或文本编辑。
网络:需要稳定连接以下载必要的板支持包和固件文件。
注意:在整个过程中,请确保你的开发板通过USB线稳定连接到电脑,并且电脑能识别到它(在设备管理器或系统信息中能看到对应的串口)。如果板子需要外部供电,也请确保供电充足。
3. 配置Arduino开发环境
既然我们要利用Arduino的烧录能力,第一步就是让Arduino IDE认识我们的SAMD21板子。很多非Arduino官方的SAMD21板子,其板定义并不在Arduino的默认仓库里。
3.1 安装Arduino IDE并添加板支持包URL
首先,下载并安装Arduino IDE。安装过程很简单,一路下一步即可。安装完成后打开它。
关键的步骤是添加额外的“板支持包”仓库地址。这就像给软件管家添加一个新的软件源。
- 打开文件(File) > 首选项(Preferences)。
- 在首选项窗口的底部,找到“附加开发板管理器网址”(Additional Boards Manager URLs)。
- 点击旁边的图标(可能是一个文件夹或多个小窗口),会弹出一个文本框。
- 在这里,你需要添加你的开发板对应的仓库URL。这个URL因板子厂商而异。例如:
- Adafruit的板子(如Feather M0):
https://adafruit.github.io/arduino-board-index/package_adafruit_index.json - SparkFun的板子(如SAMD21 Dev Breakout):
https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json - Arduino官方板子(如MKR Zero):通常已内置,无需额外添加。但如果你找不到,可以添加:
https://downloads.arduino.cc/packages/package_index.json
- Adafruit的板子(如Feather M0):
- 将正确的URL粘贴到新的一行,然后点击“确定”(OK)保存并关闭首选项。
实操心得:如果你有多个不同厂商的板子,可以在这个文本框里添加多个URL,每行一个。Arduino IDE会从所有这些源中搜索板定义。添加后如果没立即生效,可以重启一下Arduino IDE。
3.2 通过开发板管理器安装板定义
添加了“软件源”之后,我们就可以安装具体的“软件包”了。
- 点击工具(Tools) > 开发板(Board) > 开发板管理器(Boards Manager...)。
- 这会打开开发板管理器窗口。在顶部的搜索框中,输入你的板子关键词,比如“SAMD21”、“MKR Zero”或“Adafruit SAMD”。
- 在搜索结果中,找到对应的板支持包。例如:
- 对于Arduino MKR Zero,你应该安装由Arduino官方提供的“Arduino SAMD Boards (32-bits ARM Cortex-M0+)”。
- 对于Adafruit的Feather M0,你应该安装“Adafruit SAMD Boards”。
- 对于SparkFun的板子,你应该安装“SparkFun SAMD Boards”。
- 点击你需要的包,右侧会出现“安装”(Install)按钮,点击它。IDE会开始下载并安装这个包及其所有依赖,这可能需要几分钟,取决于你的网速。
- 安装完成后,关闭开发板管理器。
验证安装:再次点击工具(Tools) > 开发板(Board),你应该能在列表的靠上部分(可能在“Arduino SAMD Boards”或“Adafruit SAMD”等分类下)找到你的具体板子型号(例如“Arduino MKR Zero”)。选中它。
3.3 选择端口与驱动注意事项
选中板子后,还需要告诉Arduino IDE你的板子连接在哪个端口上。
- 点击工具(Tools) > 端口(Port)。
- 你会看到一个或多个串行端口。通常,新插入的开发板会对应一个新出现的端口。在Windows上,它可能叫
COM3、COM4等;在macOS上,类似/dev/cu.usbmodemXXXX;在Linux上,类似/dev/ttyACM0。 - 选择这个新出现的端口。
Windows 7用户特别注意:Windows 7系统可能无法自动为SAMD21板子安装正确的USB驱动。如果你在端口列表中看不到你的板子,或者上传时失败,你需要手动安装Adafruit提供的Windows 7驱动。你可以从Adafruit的教程页面找到驱动下载链接。Windows 8/10/11和macOS/Linux用户通常无需此步骤。
至此,你的Arduino IDE已经配置好,可以和你手上的SAMD21开发板“对话”了。接下来,我们将用它来上传改变一切的UF2引导加载器。
4. 烧录UF2引导加载器
这是整个流程中最关键的一步,目的是用一个新的、更友好的引导程序替换掉板子原有的引导程序。
4.1 获取正确的UF2安装程序
UF2引导加载器本身也是一个需要被烧录到芯片里的程序。Adafruit社区为我们准备好了针对不同板子的、可以直接用Arduino IDE上传的安装程序。
- 访问Adafruit的
uf2-samdx1GitHub仓库的发布页面:https://github.com/adafruit/uf2-samdx1/releases。 - 在发布列表的顶部,找到最新的版本(版本号最高的)。
- 在发布的资源文件(Assets)列表中,寻找一个文件名格式为
update-bootloader-[你的板子名称]-vx.x.x-adafruit.x.ino的文件。- 例如,对于Arduino MKR Zero,文件名为
update-bootloader-mkrzero-vx.x.x-adafruit.x.ino。 - 对于SparkFun SAMD21 Dev Breakout,可能是
update-bootloader-sparkfun_samd21_dev-vx.x.x-adafruit.x.ino。
- 例如,对于Arduino MKR Zero,文件名为
- 点击这个
.ino文件进行下载。这是一个Arduino项目文件。
重要警告:请务必使用v3.9.0 或更高版本的UF2安装程序。早期版本存在缺陷,可能导致你的板子“变砖”(无法再通过USB编程)。Adafruit已从仓库移除了有问题的版本,但如果你从其他渠道获取文件,请务必检查版本号。
4.2 使用Arduino IDE上传UF2
现在,我们将这个.ino文件“上传”到你的板子,这个过程会覆盖原有的引导程序。
- 在Arduino IDE中,点击文件(File) > 打开(Open...),找到并打开你刚刚下载的
.ino文件。 - 如果弹出提示说“文件需要放在同名文件夹中”,点击“确定”(OK),IDE会自动处理。
- 再次确认工具(Tools)菜单下的两项:
- 开发板(Board):已选择你的具体板型(如“Arduino MKR Zero”)。
- 端口(Port):已选择你的板子对应的串口。
- 点击工具栏上的“上传”(Upload)按钮(向右的箭头图标)。
Arduino IDE会开始编译这个.ino文件(虽然它看起来大部分是十六进制数据),然后通过板子原有的Arduino引导程序,将新的UF2引导加载器写入芯片的引导程序存储区域。
上传成功标志:
- IDE底部状态栏显示“上传完成”(Done uploading)。
- 观察你的开发板,如果板载有可编程的LED(通常是连接到13号引脚的LED),你会看到这个LED开始缓慢地呼吸(渐亮渐暗),这是UF2引导加载器运行时的标志性信号。
- 最关键的是,打开你的电脑文件管理器(Windows资源管理器、macOS访达或Linux文件浏览器),你会看到出现了一个新的可移动磁盘,名称通常是
[你的板子名称]BOOT,例如MKRZEROBOOT。点开这个磁盘,里面应该有几个文件,如CURRENT.UF2、INDEX.HTM和INFO_UF2.TXT。
如果你看到了这个BOOT磁盘,那么恭喜你,UF2引导加载器已经成功安装!你的板子现在拥有了“U盘模式”的超能力。
踩坑记录:我第一次操作时,上传完成后没有立刻出现
BOOT磁盘。解决方法是将板子的USB线拔掉再重新插上。如果还不行,尝试快速按两次板子上的复位(RESET/RST)按钮。进入UF2模式的核心手势就是“双击复位”。这个操作在后续安装CircuitPython或需要重新进入引导模式时也会用到。
5. 安装CircuitPython固件
有了UF2这个“传送门”,安装CircuitPython就变得异常简单了,真的就是“拖拽”。
5.1 下载对应板型的CircuitPython UF2文件
CircuitPython为每种支持的板子都编译了专用的.uf2固件文件。
- 访问CircuitPython官方网站的下载页面:
https://circuitpython.org/downloads。这个网站按板子型号分类,比在GitHub上找更方便。 - 在网页上找到你的板子型号(例如“Arduino MKR Zero”)。
- 找到最新稳定版(通常标为“Latest”),点击下载对应的
.uf2文件。文件名格式通常是adafruit-circuitpython-[板子名称]-x.x.x.uf2。
5.2 通过拖拽安装固件
确保你的板子正处于UF2引导加载器模式(即电脑上能看到[板子名]BOOT磁盘)。
- 将你下载的CircuitPython的
.uf2文件(例如adafruit-circuitpython-arduino_mkrzero-x.x.x.uf2)直接复制或拖拽到BOOT磁盘里。 - 当你开始复制时,
BOOT磁盘可能会自动弹出(在macOS上)或状态灯会快速闪烁。等待几秒钟。 - 操作完成后,
BOOT磁盘会从电脑上消失。稍等片刻,一个新的磁盘会出现,名字叫CIRCUITPY。
看到CIRCUITPY磁盘,就大功告成了!CircuitPython已经安装到你的SAMD21开发板上了。这个磁盘就是你的板子的“文件系统”,你之后所有的Python代码和库文件都将放在这里。
5.3 非Express板子的特别说明
如果你使用的不是Adafruit的“Express”系列板子(如Feather M0 Express),而是像Arduino MKR Zero这样没有外置SPI闪存芯片的板子,需要了解一个限制:CircuitPython的文件系统(CIRCUITPY磁盘)将使用芯片内部闪存的一部分来模拟。这会导致两个结果:
- 可用存储空间较小:大约只有48KB左右,用于存放你的
code.py和其他库文件。对于大型项目可能捉襟见肘。 - 某些高级功能被禁用:为了节省空间,一些非核心功能(如长整数、音频播放等)可能在此类板子的CircuitPython构建中被移除。但你仍然拥有GPIO、I2C、SPI、UART、ADC、DAC输出和电容触摸等基本外设功能。
对于有外置闪存的“Express”板子,文件系统在外置芯片上,空间更大(通常2MB以上),且功能完整。
6. 测试与验证安装结果
理论成功,还得实践检验。我们来写一个最简单的程序,让板载LED闪烁,这是嵌入式界的“Hello World”。
- 打开
CIRCUITPY磁盘。 - 在磁盘根目录下,创建一个新的文本文件,并将其重命名为
code.py。注意,文件名必须是这个,这是CircuitPython启动后自动执行的主程序文件。 - 用文本编辑器打开
code.py,输入以下代码:
import board import digitalio import time # 根据你的板子,指定控制板载LED的引脚 # 对于 Arduino MKR Zero,是 board.L # 对于 SparkFun SAMD21 Dev Breakout,是 board.LED led_pin = board.L # 请根据下方表格修改! led = digitalio.DigitalInOut(led_pin) led.direction = digitalio.Direction.OUTPUT while True: led.value = True # LED亮 time.sleep(0.5) # 等待0.5秒 led.value = False # LED灭 time.sleep(0.5) # 等待0.5秒- 修改
led_pin:你需要根据你的板子型号,将board.L替换成正确的引脚标识。参考下表:
| 开发板型号 | 应使用的引脚对象 | 说明 |
|---|---|---|
| Arduino MKR Zero | board.L | 板载LED连接在PA20引脚 |
| Adafruit Feather M0 Basic Proto | board.D13 | 与Arduino引脚13对应 |
| SparkFun SAMD21 Dev Breakout | board.LED | 板载LED引脚 |
| SparkFun SAMD21 Mini Breakout | board.LED | 板载LED引脚 |
- 保存
code.py文件。神奇的事情发生了:当你保存文件时,CIRCUITPY磁盘可能会短暂断开又重连(这是CircuitPython在自动重启),然后你板子上的LED应该开始以1秒的周期(亮0.5秒,灭0.5秒)闪烁。
如果LED成功闪烁,那么一切完美!你的SAMD21板子现在已经是一个功能完整的CircuitPython开发平台了。你可以开始探索CIRCUITPY磁盘里的lib文件夹(用于放置第三方库),并尝试更多的传感器和模块。
7. 常见问题与深度排查指南
即使步骤清晰,实际操作中也可能遇到各种问题。这里我汇总了一些常见坑点和解决方法。
7.1 问题:Arduino IDE上传UF2安装程序时失败
- 现象:编译或上传过程中报错,例如“avrdude: ser_open(): can‘t open device”、“Timed out waiting for upload port”等。
- 排查思路:
- 检查端口:确认在工具 > 端口中选择了正确的串口。可以尝试拔插USB线,观察哪个端口出现或消失。
- 检查板型:再次确认工具 > 开发板选择的是完全匹配的型号。
- 驱动问题(Windows 7):如前述,Windows 7可能需要手动安装驱动。
- 权限问题(Linux/macOS):在Linux或某些macOS配置下,当前用户可能没有串口设备的读写权限。需要将用户添加到
dialout(Linux)或tty(macOS)组,或使用sudo运行Arduino IDE(不推荐)。 - 其他程序占用端口:关闭可能占用串口的其他软件,如串口监视器、PlatformIO、Mu编辑器等。
- 双击复位进入编程模式:有些板子的Arduino引导程序需要你在上传开始前的短时间内(如上传前1-2秒)快速按两次复位按钮,才能进入可接收代码的状态。在上传时留意IDE底部状态栏,出现“上传中”提示时立即双击复位键试试。
7.2 问题:无法进入UF2模式(看不到BOOT磁盘)
- 现象:上传UF2安装程序成功后,LED在呼吸,但电脑上没有出现
BOOT磁盘。 - 排查思路:
- USB线/接口:换一根确认好的数据线,或换一个电脑USB接口试试。USB 3.0(蓝色接口)有时兼容性不如USB 2.0。
- 手动进入UF2模式:断开USB线,按住板子上的“用户按钮”(如果有的话,不是复位键)不放,同时插入USB线,等待几秒再松开。或者,直接尝试快速双击复位按钮。这是进入UF2模式的标准手势。
- 系统磁盘管理:在Windows的“磁盘管理”、macOS的“磁盘工具”或Linux的
lsblk命令中,查看是否有新的未挂载的磁盘设备出现。有时系统不会自动弹出盘符。 - UF2版本:确认你下载的UF2安装程序版本是v3.9.0或更高。
7.3 问题:拖入UF2文件后,CIRCUITPY磁盘不出现
- 现象:将CircuitPython的
.uf2文件拖入BOOT磁盘后,BOOT磁盘消失,但CIRCUITPY磁盘迟迟不出现。 - 排查思路:
- 等待与复位:多等一会儿(最多一分钟),然后尝试按一次复位按钮。有时系统刷新需要时间。
- 文件系统损坏:极少数情况下,文件系统可能损坏。需要重新安装UF2引导加载器(重复第4步),然后再安装CircuitPython。
- 不兼容的UF2文件:确保你下载的CircuitPython UF2文件是完全对应你的板子型号的。给Feather M0用的固件不能用在MKR Zero上。
- Windows延迟写入:在Windows上,从
BOOT磁盘弹出到CIRCUITPY出现期间,切勿强行拔线或按复位。Windows的延迟写入功能可能导致文件传输未真正完成。确保文件复制进度条完成,并且可以安全弹出硬件后再操作。
7.4 问题:code.py文件不执行或报错
- 现象:LED不闪,或者
CIRCUITPY磁盘里多出了一个code.txt或code.py文件报错。 - 排查思路:
- 文件名与编码:确保文件名叫
code.py,而不是code.py.txt(Windows隐藏扩展名导致)。用文本编辑器保存时,选择编码为UTF-8 without BOM。 - 语法错误:CircuitPython会在启动时执行
code.py,如果有语法错误,它会停止并在磁盘根目录生成一个error.txt或output.txt文件,里面会有错误信息。打开这个文件查看具体错误。 - 引脚定义错误:这是最常见的问题。再次核对上文表格,确保
led_pin变量指向了正确的引脚常量。错误的引脚号可能导致程序无反应或报错。 - 硬件差异:有些板子的LED是低电平点亮(sink),而代码默认是高电平点亮(source)。如果确认引脚正确但灯不亮,可以尝试将
led.value = True和led.value = False对调试试。
- 文件名与编码:确保文件名叫
7.5 高级维护:安全弹出与固件升级
- 安全弹出(尤其Windows):在拔下USB线或按复位键之前,务必在系统中“安全弹出”或“弹出”
CIRCUITPY磁盘。因为操作系统可能会缓存文件写入操作,强行断开可能导致CIRCUITPY磁盘的文件系统损坏。如果损坏,你可能需要重新拖入CircuitPython的UF2文件来修复。 - 升级CircuitPython:未来想升级到新版本的CircuitPython?过程非常简单:让板子进入UF2模式(双击复位),将新的
.uf2文件拖入BOOT磁盘即可。你的code.py和lib文件夹里的内容通常会被保留。 - 回退到Arduino:如果你想重新使用Arduino环境,同样需要进入UF2模式,然后拖入一个特殊的“恢复”UF2文件(通常可以在板子厂商的页面找到),或者使用专业的编程器(如Atmel-ICE)重新烧录Arduino的引导程序。
通过以上步骤和问题排查,你应该能够顺利地在你的SAMD21开发板上搭建起CircuitPython开发环境。这套组合带来的开发效率提升是巨大的,让你可以更专注于项目逻辑本身,而不是纠缠于底层编译和烧录工具链。