RP2040踩坑记 USB CDC串口无法下载程序(驱动)+不发送数据(DTR)
这几天买个两块INA226自己搞了个简易功率计(C表),如下图:
当时画板子就考虑兼容的板子多一点,支持Mini跟Super Mini类型的板子,一块搞了一个ESP32 C3(左),当时看RP2040-Zero便宜,就手贱又买了片RP2040-zero(右)。
一开始RP2040是刷Micropython用的,测试很成功,功率计能正常读到电压电流。后来嫌micropython慢,所以打算换到Arduino平台重写一下,这一换不打紧,踩了两个大坑。
我用的IDE是VScode+PlatformIO插件,支持巨量的板子,并且C++补全(Arduino)做的非常好,强烈吐血推荐:
看里边也有RP2040的支持,新建一个,从串口调起,下边代码:
#include <Arduino.h> void setup() { // put your setup code here, to run once: Serial.begin(115200); } void loop() { // put your main code here, to run repeatedly: Serial.println("Hello im from RP2040"); sleep_ms(1000); }
这算是Arduino的Hello world了,没理由跑不起来……
然后……
编译成功,下载失败……
看了看Arduino生成的文件,有uf2,那就好说了,按住BOOT->按住RESET->松开RESET->松开BOOT,U盘出来了。把uf2丢进去,板子重启了,这时候出现一个串口,用串口助手连上去,咦?啥都没有?
这就抽象了……难道……USB串口不是默认的Serial,是Serial1或者Serial2?然后去翻官方文档:
Arduino-Pico 核心使用 USB ACM-CDC 模型实现基于软件的串行 USB 端口,以支持各种各样的操作系统。 Serial是 USB 串行端口,虽然Serial.begin()允许指定波特率,但由于它是基于 USB 的,因此会忽略该速率。(还请注意,此 USBSerial端口负责在上传过程中重置 RP2040,遵循 Arduino 标准 1200bps = 重置为引导加载程序)。 RP2040 提供两个基于硬件的 UART,具有可配置引脚选择。 Serial1是UART0,且Serial2是UART1。
这这这这……没错啊,就是默认的Serial……
然后去Google上一顿搜索,还别说,面向google编程是对的,真有人提这事,我看讨论的还挺激烈,有人说有问题,有人说没问题……罢了罢了,我自己试,不是有人说Putty连上去没问题么,我就用Putty……
咦?果然没问题(内流满面)……,我不死心,又打开串口助手,等等……居然能收到了,这个……
我Reset了板子,又收不到了……我……
在我翻了无数个英文帖子后,终于有人说了,这个串口需要DTR=1才能输出……说实话,我第一次见这样的串口……
我打开C#,插入一个串口控件,看属性:
有个DtrEnable,难道是这个?写几句代码试试:
void Btn_OpenClick(object sender, EventArgs e) { if (!serialPort1.IsOpen) { label1.Text+="Port not opened try open!\n"; serialPort1.Open(); if (serialPort1.IsOpen) label1.Text+="Port is opened!\n"; else label1.Text+="Port is open failure!\n"; } else { label1.Text+="Port already opened try to close\n"; serialPort1.Close(); label1.Text+="Port closed\n"; } } void Check_dtrClick(object sender, EventArgs e) { serialPort1.DtrEnable=!serialPort1.DtrEnable; if (serialPort1.DtrEnable) label1.Text+="DTR Enabled\n"; else label1.Text+="DTR Disabled\n"; } void Timer1Tick(object sender, EventArgs e) { if (serialPort1.IsOpen) { if(serialPort1.BytesToRead>0) { label1.Text+=serialPort1.ReadLine(); } } }
运行结果如下:
果然啊,只有DTRenabled以后才能收到数据……Disabled就停了……
等等,这么明显的问题官方会不知道?然后搜手册,我看到这个:
RP2040 特定的 SerialUSB 方法 void Serial.ignoreFlowControl(bool 忽略) 在某些情况下,目标应用程序不会断言 DTR 虚拟线,从而阻止写入操作成功。 因此,SerialUSB::ignoreFlowControl() 方法禁用连接的状态验证,使得程序能够在端口上写入,即使数据可能丢失。
……但是,貌似PlatfromIO带的Arduino-Core貌似比较旧,没这个函数。
总之算是解决了。顺便也通过一个帖子解决了没法下载的问题,原来是我装的驱动不对,在Boot模式,这个板子会出现一个RP2 Boot的设备,当时我给他装的是CDC驱动(Zadig装的),改成WInUSB就行了。
话说回来,这个RP2040下载真是快,可能也跟固件小有关,这个hello world只有100多K,总之,比ESP32下载快多了(虽然不公平)。