
1. 项目概述从零上手一块高性价比的Wi-Fi蓝牙双模模块最近在捣鼓智能家居的小玩意儿手头正好有几块安信可的BW16模块也就是基于RTL8720DN芯片的核心板。这玩意儿性价比是真高集成了Wi-Fi和蓝牙价格还亲民非常适合用来做各种物联网的“大脑”。但说实话刚拿到手的时候有点懵官方资料虽然全但东一块西一块的对于想快速点个灯、验证下基础功能的新手来说门槛不低。所以我决定把这次从环境搭建到成功“点亮神灯”其实就是控制板载LED的完整过程以及中间踩过的所有坑都详细记录下来。如果你也刚拿到BW16或者对RTL8720DN在Arduino平台上的开发感到无从下手那这篇笔记应该能帮你省下不少折腾的时间。所谓“点亮神灯”听起来玄乎其实就是最经典的“Hello World”硬件版——控制开发板上的一个LED灯闪烁。别小看这个操作它涵盖了给BW16刷写Arduino固件、配置开发环境、编写并上传第一个程序的全流程。成功点亮意味着你的开发链已经彻底打通后续无论是连接Wi-Fi、操作传感器还是驱动舵机都有了坚实的基础。整个过程我会重点讲清楚几个关键点为什么选择Arduino框架而非原厂SDK、如何为这块“陌生”的板子添加支持、编译和烧录中的各种参数设置以及最后那段让灯闪烁的代码到底是怎么工作的。2. 核心思路与方案选型为什么是Arduino面对一块新的硬件模块第一步永远是选择开发框架。对于RTL8720DNBW16你至少有三种选择原厂Realtek的Ameba SDK、安信可基于原厂SDK二次封装的开发环境或者就是我们今天要用的Arduino。我最终选择Arduino主要是基于以下几点考量这也是很多从Arduino生态转过来的开发者会优先考虑的路径。2.1 规避原厂SDK的复杂度Realtek官方的Ameba SDK功能无疑是最强大、最底层的能发挥芯片的全部性能。但它的开发环境搭建相对复杂通常基于Eclipse或VS Code需要手动配置工具链、下载庞大的SDK包编译过程对新手不太友好。更重要的是其API风格和编程思路与常见的Arduino/ESP32有较大差异学习成本较高。如果你的项目不需要榨干芯片的每一分性能而是追求快速原型开发那么原厂SDK可能显得“杀鸡用牛刀”了。2.2 利用Arduino生态的巨量资源这是选择Arduino最核心的理由。Arduino拥有海量的开源库从传感器驱动DHT11, BMP280、通信协议MQTT, HTTP, WebSocket到显示设备OLED, TFT应有尽有。当你用Arduino框架开发BW16时理论上这些库经过少量适配甚至直接就能使用。这意味着你项目中的绝大多数功能模块可能都已经有人写好了现成的代码你只需要像搭积木一样调用即可开发效率呈指数级提升。2.3 统一的开发体验如果你之前玩过ESP8266或ESP32的Arduino开发那么上手BW16的Arduino开发将会异常顺畅。代码结构setup(),loop()、引脚操作digitalWrite(),analogRead()、串口打印Serial.print()等完全一致。这种一致性极大地降低了切换不同硬件平台时的心理负担和学习成本。你可以把更多精力放在项目逻辑本身而不是反复熟悉新的API。2.4 安信可官方与社区的支持安信可官方意识到了Arduino生态的重要性积极维护了针对BW16等RTL8720DN模块的Arduino核心包。这意味着有官方的质量背书和持续更新。同时在GitHub、论坛等社区基于Arduino的讨论和问题解答也越来越多遇到困难时更容易找到解决方案。注意选择Arduino并非没有代价。最主要的牺牲是对芯片底层硬件的直接控制能力和极致的性能优化。例如对RTL8720DN特有的低功耗模式、某些外设的高级功能Arduino核心包可能尚未封装或封装不全。但对于大多数物联网应用数据采集、无线控制、状态上报来说Arduino提供的性能已经绰绰有余。3. 环境搭建全流程详解从空白IDE到识别板子思路定下来接下来就是实战。环境搭建是第一步也是最容易卡住新手的环节。这里我会把每一步的操作意图和可能遇到的坑都讲明白。3.1 安装Arduino IDE首先确保你电脑上安装的是较新版本的Arduino IDE建议1.8.x以上或最新的2.0。直接从Arduino官网下载安装即可这一步没什么特别的。3.2 添加BW16的板卡支持网址这是关键一步。Arduino IDE默认只认识官方的Arduino板子如Uno, Mega。要让它能识别我们的BW16需要告诉IDE去哪里找BW16的定义文件。打开Arduino IDE点击文件-首选项。在“附加开发板管理器网址”一栏你会看到一个或多个网址。我们需要添加安信可官方维护的板卡索引地址。在已有的网址后面如果没有就直接填写添加以下网址。如果已有其他网址请用逗号英文逗号隔开。https://github.com/ambiot/ambd_arduino/raw/master/package_realtek_ameba_index.json提示这个URL是安信可维护的索引文件地址里面包含了RTL8720DNBW16以及其他Realtek Ameba系列芯片的Arduino包信息。确保网络通畅能访问GitHub。3.3 安装“Realtek Ameba Boards”核心添加好网址后就可以安装具体的板卡支持包了。点击工具-开发板-开发板管理器...。在弹出的开发板管理器顶部搜索框中输入“ameba”。你应该会看到“Realtek Ameba Boards (32-bit Arm Cortex-M33200MHz)”这个条目。选择它并点击右侧的“安装”。安装过程可能会持续几分钟因为它需要下载编译器工具链、核心库文件等。请耐心等待确保网络稳定。3.4 选择正确的开发板和参数安装成功后你的BW16模块就出现在可选列表里了。点击工具-开发板现在你应该能在列表里找到“Realtek Ameba Boards (32-bit Arm Cortex-M33200MHz)”这个分组展开它。根据你手头的具体模块选择。对于最常见的安信可BW16模块选择“Ai-Thinker BW16”。注意还有BW16 Module等选项务必核对板子丝印。选择开发板后端口Port通常还不会出现需要等板子进入下载模式并连接电脑。其他参数通常保持默认即可Upload Speed: 921600 (烧录速度高速烧录节省时间)Builtin Lib: 选择你需要的库初期可以默认。Flash Size: 根据模块型号选择BW16通常是2MB。Crystal Frequency: 40MHz (外部晶振频率BW16是40MHz)3.5 连接硬件与进入下载模式BW16RTL8720DN的烧录需要特定的引脚配合才能进入下载模式这是和经典Arduino板通过USB直接烧录不同的地方。接线你需要一个USB转TTL串口模块如CH340、CP2102等。BW16的TX接USB-TTL的RX。BW16的RX接USB-TTL的TX。BW16的GND接USB-TTL的GND。BW16的3.3V接USB-TTL的3.3V严禁接5V。关键步骤进入下载模式BW16没有物理复位键和BOOT键。需要通过在上电瞬间将特定引脚拉低来触发下载模式。找到BW16模块上的PB5引脚具体位置请查阅安信可BW16规格书或引脚图通常会有标注。在通过USB-TTL给模块供电接上3.3V和GND之前先用一根杜邦线将PB5引脚与GND短接。保持短接状态然后给USB-TTL模块插上电脑USB口此时BW16上电。上电后再断开PB5和GND的短接。如果操作成功Arduino IDE的端口列表里应该会出现一个新的串口如COM3, COM4, /dev/ttyUSB0等。实操心得进入下载模式是第一个“坑”。PB5拉低的时机非常关键必须在供电瞬间完成。我个人的经验是可以先接好所有线包括PB5到GND的短接线最后再插USB线这样成功率最高。如果一次没成功多试几次或者检查短接是否牢靠。4. “点亮神灯”代码解析与烧录环境准备好板子连上了接下来就是写代码和烧录了。我们从一个最简单的Blink程序开始但这里面的门道也不少。4.1 编写Blink程序在Arduino IDE中新建一个空白项目你会看到经典的setup()和loop()函数。我们的任务就是找到BW16板载LED对应的引脚号然后控制它闪烁。// BW16 Blink Example // 板载LED通常连接在PA12引脚上但需要确认你的具体版本 void setup() { // 初始化数字引脚PA12为输出模式 pinMode(PA12, OUTPUT); // 初始化串口用于调试打印波特率115200 Serial.begin(115200); Serial.println(BW16 Blink Demo Started!); } void loop() { // 点亮LED (HIGH代表高电平根据电路设计可能是高电平点亮或低电平点亮) digitalWrite(PA12, HIGH); Serial.println(LED ON); delay(1000); // 等待1000毫秒即1秒 // 熄灭LED digitalWrite(PA12, LOW); Serial.println(LED OFF); delay(1000); // 再等待1秒 }代码关键点解析引脚定义PA12在Realtek Ameba的Arduino核心中引脚名称不是简单的数字而是直接使用芯片的GPIO名称如PA12,PB5等。你需要查阅你的BW16模块的原理图或文档来确定板载LED连接到了哪个GPIO。对于最常见的安信可BW16模块板载蓝色LED通常连接在PA12。如果不确定可以尝试PA0、PA1等常见引脚或者用万用表测量。HIGH/LOW与点亮逻辑digitalWrite(PA12, HIGH)意味着向PA12引脚输出3.3V电压。如果你的LED阳极接PA12阴极通过电阻接地那么高电平时LED点亮。有些板子的设计是低电平点亮LED阳极接3.3V阴极接GPIO那么你就需要将HIGH和LOW对调。最保险的方法是先上传代码看LED状态如果常亮或常灭但不闪烁就反过来试试。串口调试强烈建议在setup()中初始化串口 (Serial.begin(115200))。这样你可以在loop()中通过Serial.println()打印信息在IDE的串口监视器工具 - 串口监视器里查看这对于验证程序是否在运行、排查问题至关重要。4.2 编译与上传点击Arduino IDE左上角的“验证”对勾图标来编译代码。第一次编译可能会比较慢因为要索引所有库文件。如果编译成功下方控制台会显示“编译完成”。确保在工具-端口中选择了之前识别到的那个串口就是BW16在下载模式下出现的那个。点击“上传”向右箭头图标。此时IDE会先编译代码然后尝试通过串口将程序烧录到BW16中。观察下方控制台输出。如果看到“Hard resetting via RTS pin...”或类似的提示并且进度条走完通常意味着上传成功。4.3 验证结果上传成功后BW16会自动复位并运行新程序。你应该能看到板载的LED开始以1秒的间隔规律地闪烁。同时打开串口监视器波特率设置为115200你会看到交替打印的“LED ON”和“LED OFF”信息。至此“点亮神灯”的核心任务就完成了这个简单的闪烁标志着你已经成功地在BW16上搭建起了Arduino开发环境并且掌握了最基本的GPIO输出控制。5. 深入实操GPIO使用详解与扩展成功点亮LED后我们可以更深入地探索BW16的GPIO功能这是连接各种传感器和执行器的基础。5.1 GPIO模式设置除了最简单的输出模式GPIO还有输入、上拉输入、下拉输入、开漏输出等模式。在Arduino核心中通过pinMode()函数设置。输入模式用于读取按键、开关等数字信号。pinMode(PA0, INPUT); // 将PA0设置为高阻态输入 int buttonState digitalRead(PA0); // 读取引脚电平上拉输入芯片内部连接一个上拉电阻到3.3V当外部引脚悬空时读取到的值为HIGH。常用于按键按键另一端接地。pinMode(PA0, INPUT_PULLUP); // 启用内部上拉电阻 // 当按键按下PA0接地digitalRead(PA0)为LOW // 当按键释放内部上拉起作用digitalRead(PA0)为HIGH注意RTL8720DN的Arduino核心也支持INPUT_PULLDOWN内部下拉但并非所有GPIO都同时具备上拉和下拉功能需查阅数据手册。5.2 模拟输入ADCBW16的某些引脚支持模拟输入可以读取0-3.3V之间的电压值并将其转换为数字量通常为0-409512位分辨率。void setup() { Serial.begin(115200); // 不需要为模拟输入专门设置pinMode但有些核心要求设为INPUT设为INPUT更保险 pinMode(PA0, INPUT); } void loop() { int sensorValue analogRead(PA0); // 读取PA0的模拟值 float voltage sensorValue * (3.3 / 4095.0); // 转换为电压值 Serial.print(ADC Value: ); Serial.print(sensorValue); Serial.print( | Voltage: ); Serial.println(voltage); delay(500); }关键参数解析analogRead()返回的值取决于ADC的分辨率。对于BW16RTL8720DNArduino核心默认将其配置为12位分辨率即最大值是40952^12 - 1。公式电压 读数 * (参考电压 / 最大读数)是通用的ADC值转电压公式。BW16的ADC参考电压通常是3.3V。5.3 模拟输出PWMBW16支持通过PWM脉冲宽度调制来模拟模拟输出常用于控制LED亮度、电机速度、舵机角度等。void setup() { pinMode(PA12, OUTPUT); // 设置引脚为输出 } void loop() { // 实现呼吸灯效果 for (int brightness 0; brightness 255; brightness) { analogWrite(PA12, brightness); // 设置PWM占空比范围0-255 delay(10); } for (int brightness 255; brightness 0; brightness--) { analogWrite(PA12, brightness); delay(10); } }PWM频率与分辨率analogWrite()的第二个参数范围是0-255对应8位分辨率。PWM的频率是固定的通常为1kHz由底层库决定。如果需要调整频率或使用更高分辨率可能需要调用更底层的RTL8720DN SDK函数这在Arduino核心中可能没有直接封装是Arduino框架在高级应用上的一个限制。6. 无线功能初探Wi-Fi扫描与连接作为一款Wi-Fi蓝牙双模芯片无线功能才是RTL8720DN的“主菜”。在Arduino环境下使用Wi-Fi得益于ESP32等芯片的普及其API已经非常标准化和易用。6.1 扫描附近的Wi-Fi网络这是一个验证Wi-Fi硬件是否工作正常的好方法。#include WiFi.h // 包含Wi-Fi库 void setup() { Serial.begin(115200); delay(1000); // 设置为Station模式客户端模式 WiFi.mode(WIFI_STA); // 断开之前的连接 WiFi.disconnect(); delay(100); Serial.println(Start scanning...); // 开始扫描 int n WiFi.scanNetworks(); Serial.println(Scan done.); if (n 0) { Serial.println(No networks found.); } else { Serial.print(n); Serial.println( networks found:); for (int i 0; i n; i) { // 打印SSID、信号强度(RSSI)和加密类型 Serial.print(i 1); Serial.print(: ); Serial.print(WiFi.SSID(i)); Serial.print( (); Serial.print(WiFi.RSSI(i)); Serial.print( dBm) ); Serial.println((WiFi.encryptionType(i) WIFI_AUTH_OPEN) ? Open : Encrypted); delay(10); } } } void loop() { // 主循环为空只扫描一次 delay(10000); }这段代码会将模块设置为Wi-Fi客户端扫描周围网络并将结果通过串口打印出来。如果能看到你家的Wi-Fi名称和信号强度说明Wi-Fi驱动和功能完全正常。6.2 连接指定Wi-Fi网络连接网络是物联网设备上网的第一步。#include WiFi.h const char* ssid Your_SSID; // 你的Wi-Fi名称 const char* password Your_PASS; // 你的Wi-Fi密码 void setup() { Serial.begin(115200); delay(1000); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.print(Connecting to ); Serial.println(ssid); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); // 可以在这里添加超时判断避免无限等待 } Serial.println(); Serial.println(WiFi connected!); Serial.print(IP address: ); Serial.println(WiFi.localIP()); // 打印获取到的本地IP地址 } void loop() { // 保持连接可以在这里添加需要网络的功能 if (WiFi.status() ! WL_CONNECTED) { Serial.println(WiFi disconnected, reconnecting...); WiFi.reconnect(); } delay(10000); // 每10秒检查一次连接状态 }连接过程解析WiFi.begin()启动连接过程但它是一个非阻塞函数会立即返回。因此我们需要用一个while循环不断检查WiFi.status()的状态直到它变为WL_CONNECTED。连接成功后可以通过WiFi.localIP()获取路由器分配给设备的本地IP地址这是设备在网络中的标识。避坑技巧连接失败时除了检查SSID和密码还要注意Wi-Fi的加密方式。一些非常旧的加密方式如WEP或企业级认证Arduino的WiFi库可能不支持。确保你的路由器使用WPA2-PersonalAES这种最通用的加密方式。7. 蓝牙功能浅尝BLE广播与连接RTL8720DN也支持蓝牙低功耗BLE。在Arduino上使用BLE通常需要安装额外的库例如ESP32 BLE Arduino库但经过适配后其API对于RTL8720DN也是可用的。这里展示一个最简单的BLE广播示例发送设备名称。7.1 安装BLE库由于安信可的Arduino核心可能没有预置BLE库我们需要手动安装一个兼容的库。在Arduino IDE中点击项目-加载库-管理库...。在库管理器中搜索“BLE”。你可以尝试安装由“Neil Kolban”提供的“ESP32 BLE Arduino”库。虽然名为ESP32但其底层接口经过适配后可以在Realtek Ameba平台上运行。安装完成后在代码中#include BLEDevice.h等头文件。7.2 一个简单的BLE广播示例#include BLEDevice.h #include BLEUtils.h #include BLEAdvertising.h void setup() { Serial.begin(115200); Serial.println(Starting BLE Beacon...); // 初始化BLE设备设置设备名称 BLEDevice::init(My_BW16_Beacon); // 获取BLE广播对象 BLEAdvertising *pAdvertising BLEDevice::getAdvertising(); // 配置广播参数可选 pAdvertising-setScanResponse(true); pAdvertising-setMinPreferred(0x06); // 有助于提高iPhone连接概率 pAdvertising-setMinPreferred(0x12); // 开始广播 pAdvertising-start(); Serial.println(BLE Beacon is now advertising!); Serial.println(You can scan for My_BW16_Beacon with your phone.); } void loop() { // 保持广播这里不需要做其他事 delay(1000); }这段代码将BW16配置为一个简单的BLE信标Beacon持续广播自己的名称“My_BW16_Beacon”。你可以用手机上的BLE扫描App如nRF Connect、LightBlue搜索到这个设备。7.3 BLE的复杂性需要注意的是BLE编程比简单的Wi-Fi连接要复杂得多它涉及服务Service、特征Characteristic、描述符Descriptor等概念。上面的例子只是冰山一角。要实现数据收发你需要定义自己的服务UUID和特征并为其设置读写回调函数。这部分的代码量会大很多建议在掌握基础GPIO和Wi-Fi后再专门找BLE的教程深入学习。8. 常见问题与排查实录在实际操作中你几乎一定会遇到一些问题。下面是我在开发过程中遇到的一些典型问题及解决方法希望能帮你快速排雷。8.1 开发板管理器里找不到“Realtek Ameba Boards”可能原因1附加开发板管理器网址填写错误或没有保存。解决检查文件-首选项中的网址是否正确确保是https://github.com/ambiot/ambd_arduino/raw/master/package_realtek_ameba_index.json并且点击了“好”保存。可能原因2网络问题无法访问GitHub。解决检查网络连接有时需要配置网络环境。可以尝试在浏览器中直接打开该网址看是否能下载到一个JSON文件。可能原因3Arduino IDE版本太旧。解决升级到最新版本的Arduino IDE。8.2 上传失败提示“Failed to connect to ESP32: Timed out waiting for packet header”或类似错误可能原因1没有正确进入下载模式。解决严格按照步骤操作先短接PB5和GND再上电然后断开短接。多尝试几次确保短接可靠。可能原因2选择了错误的串口。解决在设备管理器Windows或ls /dev/tty*Linux/Mac中确认USB-TTL模块对应的串口号并在IDE中正确选择。可能原因3串口被其他软件占用。解决关闭其他可能占用串口的软件如串口助手、旧的Arduino IDE窗口等。可能原因4USB-TTL模块驱动问题或模块本身故障。解决尝试更换一个USB口或换一个已知好用的USB-TTL模块如CH340测试。8.3 上传成功但LED不闪烁串口无输出可能原因1LED引脚号错误。解决确认你的BW16模块板载LED的实际连接引脚。查阅官方Wiki或原理图。可以尝试将代码中的PA12改为其他可能的引脚如PA0,PA1等或者用万用表测量。可能原因2LED点亮逻辑反了。解决将代码中的digitalWrite(PA12, HIGH)和digitalWrite(PA12, LOW)对调试试。可能原因3程序没有运行。解决上传完成后尝试按一下USB-TTL模块的复位键如果有或者重新给模块上电。有些情况下需要手动复位才能从下载模式切换到运行模式。可能原因4串口监视器波特率设置错误。解决确保串口监视器的波特率设置为代码中Serial.begin(115200)指定的115200。8.4 编译错误提示“fatal error: xxx.h: No such file or directory”可能原因缺少必要的库文件。解决根据错误信息提示的缺失头文件如WiFi.h通过库管理器搜索并安装对应的库。对于Wi-Fi通常核心包已包含。对于BLE可能需要手动安装“ESP32 BLE Arduino”库。8.5 Wi-Fi连接非常慢或经常断开可能原因1信号强度太弱。解决让设备靠近路由器或者检查天线是否连接良好如果模块有外接天线。可能原因2电源不稳定。解决Wi-Fi射频工作时电流较大确保供电充足且稳定。尝试使用独立的3.3V稳压电源为模块供电而不是依赖USB-TTL模块的3.3V输出其输出电流可能不足。可能原因3代码中缺少连接状态维护。解决像前面的示例一样在loop()中定期检查WiFi.status()并在断开时尝试重连。8.6 程序占用空间过大导致上传失败可能原因引入了过多大型库或者代码本身过于庞大。解决BW16的Flash通常为2MB对于Arduino程序来说一般足够。但如果真的超了可以尝试在工具-Flash Size中选择正确的尺寸。检查并移除未使用的库引用。优化代码减少全局变量和字符串常量的使用。在工具菜单下尝试调整“优化”等级为“-Os”最小尺寸。我个人在最初上手时被“下载模式”卡了最久总是忘记在通电前短接PB5或者短接不牢靠。另一个坑是误用了5V的USB-TTL模块差点烧坏板子。所以耐心和细致的操作是玩转这类嵌入式开发板的第一步。一旦环境打通后面基于丰富的Arduino生态进行创造就会变得非常顺畅和有趣了。