文号
944646
阅读
8842
回复
11
收藏
7
所有教程由网友发布,仅供参考,请谨慎采纳。科创不对教程的科学性、准确性、可靠性负责。
用RP2040升级替代arduino单片机
2025/06/04
IP:北京

之前主要使用Arduino Pro Micro单片机,几年前遇到过arduino单片机性能不够用的情况,当时就是换了teensy4.0单片机,完全兼容arduino,主频高达600MHz,各方面都好就是贵啊,得200多元一片。最近逛淘宝,发现一款很便宜的单片机RP2040,自称是可以兼容arduino。这个板子体积超小,主频高达133MHz还可以超频,内存也大,才十多块钱一片。抱着试试看的心态,买了一个回来测试,发现确实不错,经过一些简单设置可以兼容arduino,个别函数如定时中断有改变,实际是变得更简单了。这样以相同甚至更低的价格,极小的设置代价,就可以获得性能远超标准arduino板(32U4或328P)的单片机。

我做的试车台推力计使用这个板子替代Pro Micro,主频足够支持1000Hz以上采样率,内部闪存1MB以上,足够保存几百次试车数据,OLED显示刷新率也大为提高,特此推荐给大家。

1,器件

我购买的是无名科技的RP2040,另一个牌子SeeedStudio的XIAO RP2040我也试过,不大对劲,暂不细说。

Screenshot_20250603_200802.jpg

通常情况下选2M(flash闪存)的就足够用了,这个板子性能方面就不用吹了,就看这长达600多页的说明书,你就知道这东西不简单。再看这十多块钱的价格,是不是很感人呢。

所以性能是不用担心的,主要看能不能直接用起来了。

Screenshot_20250603_201842.jpg

2,Arduino IDE下的基本运行

同标准arduino板子一样,要用USB线将RP2040插到电脑USB口,然后按以下3个步骤操作,这里为了逻辑清晰使用倒序,实际应该按3、2、1操作:

2.1,同标准arduino单片机首次使用,总是需要在arduino开发软件IDE工具Tools菜单下,找到板子Board对应类型,2M flash的小板子选DFRobot Beetle RP2040就可以,如果是16M的,选Arduino Nano RP2040 Connect。

2.2,可是你会发现,根本找不到这个板子型号,它不在现有的菜单里。嗯,应该在Tools下面的Board里点Board Manager去搜索一下这个板子的驱动看看。得在弹窗里搜索到RP2040板子的驱动Arduino Raspberry Pi Pico/RP2040… by Earle F. … ,点安装,然后才能在Tools下Board里找到这种板子。

mmexport1749096481983.jpg

2.3,可是你又会发现Board Manager里搜索不到这个板子程序,因为你还需要在IDE界面的File下,点开Preferences,然后把板子管理程序的地址XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Manager里搜索并安装这种RP2040板子的驱动,然后才能在Tools下Board里找到这种板子。

IMG_20250603_203024_edit_54882015274438.jpg

经过这三步,后面就简单了,下面一项Tools下的Port也要选对USB口,通常新板子或板子重启再插入的情况下,是UF2_Board,后来会变成一长串COM12(…RP2040…)。

连上板子以后,在IDE界面的File下Example里找个最简单的程序试一试,比如01. Basics的AnalogReadSerial,上传运行就可以了。打开工具Tools下串口绘图Serial Plotter,可以看到波形,用手触碰A0脚,波形为50Hz正弦波,表明单片机能运行arduino基本程序了。

3,扩展应用

简单的应用到上述2就足够了,这里再补充一些稍复杂一点的应用。

3.1 首先可以#include各种h文件,反正这个板子内存够大。有一些RP2040的特有函数是放在这些h文件里的。

#include <Arduino.h>

#include <stdio.h>

#include <pico/stdlib.h>

#include <hardware/uart.h>

#include <hardware/gpio.h>

#include <hardware/divider.h>

#include <hardware/timer.h>

#include <hardware/clocks.h>

#include <EEPROM.h>

比如定时中断函数就放在timer.h里,然后超频设置函数就放在clock.h里。具体说明可以百度RP2040 C/C++ SDK,有好几百页,各种功能设置相当复杂,这里只举例说两个常用的功能。

3.2 数据存储及模拟EEPROM

这个板子没有EEPROM,但是flash大,可以在Tools下的菜单里选择flash分1MB容量出来做数据存储。上述3.1中include的EEPROM.h,里面有模拟的EEPROM读写函数,可以直接访问部分flash存储空间。在include了EEPROM.h的情况下,在void setup()中开启EEPROM

EEPROM.begin(1024);

然后用for循环顺序写入多个数据点进EEPROM映射的缓存上(此时还没真正写入)

EEPROM.write(j*2+1,F0[j]/2/255);

然后用flash写入命令固定数据到EEPROM定义的flash上,就可以掉电保存了

EEPROM.commit();

读出也是用循环逐点读出数据,每个数据是8位二进制也就是0-255,如果大于255或小于0的数,就得占用2个或以上的存储单元了。

uint8_t FL = EEPROM.read(i*2+0);

更复杂的数据存储办法是直接把数据存成文件,这个板子甚至可以把flash设置成U盘来使用,就是说你可以把数据存到板子上成为一个文本文件,然后插上USB线在电脑就能看见这个文件,直接能拷走文件。比如下例简单代码就能在电脑上看到一个新的U盘,里面有一个数据文件。在16M板子的情况下,可以得到一个15MB的U盘,可以存储数百次试车数据。

#include <Arduino.h> // 引入 Arduino 核心头文件

#include <stdio.h>

#include <pico/stdlib.h>

#include <FatFS.h>

#include <FatFSUSB.h>

void setup() {

  Serial.begin(115200);

  char buff[32];

  int cnt = 1;

  sprintf(buff, "%d\n%d\n%d\n", cnt+2, 190, 5000);

  sprintf(buff+strlen(buff), "%d\n%d\n%d\n", cnt+5, 333, 422);

  FatFS.begin();

    File f = XXXXXXXXXXXXXXXXX("counts.txt", "w");

    f.write(buff, strlen(buff));

    f.close();

  FatFS.end();

  // Start FatFS USB drive mode

  FatFSUSB.begin();  

}

void loop()

{

}

3.3 定时中断

以我写的推力测量代码为例,使用定时中断,会精确地每20ms采集一次数据,这样计算比冲的时候会比较准确。RP2040不能直接使用TimerOne.h或Timer2.h这两个库,不过它有更简单的定时中断函数:

struct repeating_timer timer;

然后在void setup(){}里,添加1行代码add_repeating_timer_ms(-20, F_Smp, NULL, &timer); 就可以启动定时中断,第一个参数-20就表示每20ms会中断,强制跳到函数F_Smp里去执行一次(推力测量)。

bool F_Smp(struct repeating_timer *t)

{  

……

}

一个完整的定时中断例程如下,会每20ms在串口上输出数字,以及在数字口2输出一个50Hz方波,定时间隔最高可以设置-2也就是2us,能产生500kHz方波,不过这个时候串口输出就得注释掉,中间有个for循环20次是用来延时的,调整占空比便于观测

#include <Arduino.h>

#include <stdio.h>

#include <pico/stdlib.h>

#include <hardware/uart.h>

#include <hardware/gpio.h>

#include <hardware/divider.h>

#include <hardware/timer.h>

#include <hardware/clocks.h>

#define BUILTIN_LED 2

struct repeating_timer timer;

int i;

float x1=1;

int j;

bool repeating_timer_callback(struct repeating_timer *t)

{

  gpio_put(BUILTIN_LED, 1);

  Serial.println(i);

  for(j=0;j<20;j++)

  {

    i=i*1;

  }  

  gpio_put(BUILTIN_LED, 0);

  return true;

}

void setup() {

  // put your setup code here, to run once:

  Serial.begin(115200);

  set_sys_clock_khz(266000, true);

  gpio_init(BUILTIN_LED);

  gpio_set_dir(BUILTIN_LED, 1);

  gpio_pull_up(BUILTIN_LED);

  delay(100);

  add_repeating_timer_us(-20000, repeating_timer_callback, NULL, &timer);

}

void loop(){

  delay(25000);

  Serial.println("XXXXXX...............Timer %d fired!");//, (int)id);  

  bool cancelled = cancel_repeating_timer(&timer);

}

这里只展示了RP2040如何替代Ardunio的方面,这当然只是RP2040强大性能的冰山一角,爱学习的朋友们可以查阅其C/C++ SDK说明书,比如定时器timer在第297页,有例程演示如何设置定时中断。

Screenshot_20250604_201906.jpgScreenshot_20250604_202024.jpgScreenshot_20250604_202144_cn.wps.moffice_eng.jpg

值得注意的是,说明书中的C/C++例程一般是主函数int main(){}方式,要把那里面语句放到arduino的void setup(){}和void loop(){}板子才认,厉害一点的也可以直接在arduino IDE下用C编程,略微麻烦一些。还有两个连接,有arduino IDE下对树莓派Pico编程的代码说明:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

总之,使用RP2040板替代标准arduino板,简单易行,可以在不增加成本的情况下,获得极大的性能升级,值得推广。






[ 修改于1年4个月前 - 2025/06/13 11:49:11 ]
11
6
1年5个月前IP:广东
944700
1楼

这个芯片确实非常棒。架构非常简洁,例如IO口根本不像其它MCU还分什么ABCD...port,而是统一操作,一个32bit ulong数按位操作就可以随意操作所有IO,对于有些场合(例如高位宽并行)就非常合适。另外它的双核编程也是不错,特别适合略复杂的分工合作。它最大的硬件亮点是PIO,通过微码以200M(典型超频时钟频率)节拍级精确度控制引脚,可以当做简单FPGA来用,玩法花样很多。更好的是它的开源生态很好。我去年发现了这个芯片,现在已经很喜欢它了,我觉得比STM32好玩得多。

引用
评论(1)
1
Tangshm作者
1年5个月前IP:北京
944715
2楼
引用量子隧道发表于1楼的内容
这个芯片确实非常棒。架构非常简洁,例如IO口根本不像其它MCU还分什么ABCD...port,而是统一操作,一个32bit ulong数按位操作就可以随意操作所有IO,对于有些场合(例如高位宽并行)就...

是哦,近两年才推出的,新一代单片机在技术上确实有飞跃,价格还友好啊!向下兼容也很好,很容易推广到arduino普通用户,专业开发者和高手就更不用说了。

引用
评论
Tangshm作者
1年4个月前IP:北京
944894
3楼

低成本RP2040,7.5元一个!

Screenshot_20250615_192017.jpgIMG_20250615_193751_edit_590645855161955.jpg

引用
评论
1年4个月前IP:上海
944898
4楼

RP2040开发板我也有一片 但是我觉得这个是要慎重选择的 选择这个 不如把学习方向换为传统STM32或者RISC-V

它本身也是也是cortex M0+的 和低端STM32内核一样 虽然有PIO 可以模拟一些简单或者特殊外设 但是在外设方面 还是弱于传统STM32的 尤其在定时器方面

产品线也比较少 应用上比较受限 开发环境较其他的STM32 选择也少

如果不是用开发板 需要自己设计硬件 得使用片外flash 有点麻烦 也没有什么集成好的模组可选择

不过在用micropython的时候 因为较大的flash和RAM 比其他STM32有较大的性价比 可以当成Arm+micropython的最具性价比选择

至于用flash当U盘或EEPROM的想法 实验性或者DIY玩玩可以 但正式的应用要谨慎考虑flash的寿命 采用磨损均衡的算法


引用
评论
2
Tangshm作者
1年4个月前IP:北京
944909
5楼

对于非专业的爱好者,STM32学习成本会不会比较高?我现在教理科学生arduino三个学时就学完大部分内容了。

这篇文章主要想说RP2040确实可以兼容arduino,很小代价获得性能大幅提升。要说arduino、树莓派、STM32学哪个好,这得看专门讨论了,网上有不少帖子说这个问题。

爱好者级别的应用中flash擦除寿命也不是问题,本身就有10万次,加上它容量大,文件写满才会擦除覆盖。像我另一个帖子做的推力采集,5000段数据才会满,估计多数人一辈子也不会试那么多次车😀

引用
评论
1年4个月前IP:广东
944929
6楼

Arduino及各种衍生品,不适合深造、谋生、产品量化。

假如你要经常编译……那开发时间成本也远比传统IDE高得多。


引用
评论
Tangshm作者
1年4个月前IP:北京
944930
7楼

网上有不少探讨Ardunio、树莓派、STM32的适用范围,是可以分得比较清楚的。首先,对于非电专业的爱好者来说,arduino应该是很好的选择,最容易上手。其次,很多个性化研究中的小任务、小装置,使用Ardunio也足以胜任,很灵活高效,比如我们在的大型仪器上增加外围组件、增加辅助功能,都使用arduino。而专业开发、量产的工业品,肯定都是直接用芯片、画PCB,即使用STM32也不会用开发板来搭。

引用
评论
1年4个月前IP:广东
944955
8楼
引用Tangshm发表于7楼的内容
网上有不少探讨Ardunio、树莓派、STM32的适用范围,是可以分得比较清楚的。首先,对于非电专业的爱好者来说,arduino应该是很好的选择,最容易上手。其次,很多个性化研究中的小任务、小装置,使...

看来楼主是学校里的老师。那么楼主的选择没错,arduino或树莓派是首选。搞研究和教学的人搭实验环境,MCU环境首先考虑的就是性能够用下的开发友好。这个需求和我的需求是一致的。我同事用STM32,我经常帮他debug,做过比较,我觉得STM32的程序远远不如树莓派的清晰。以数据搬运为例,SPI-DMA-以太网或SPI,做个程序打通这条搬运路径,树莓派的程序组织清晰模块隔离严谨,而STM32的就互相纠缠,DMA的结束中断回调函数和SPI还能扯到一起,结构上挺垃圾的,当然适应了就好。我不以嵌入式MCU谋生,所以只要树莓派够用我就继续蜷缩在树莓派之中。相对于学STM32的低性价比(高代价:浪费生命的顺从性学习内容过多;低性能:会STN32的满大街都是,再怎么学也是和月薪仅一两万的工程师竞争),把我省出来的时间用来做电子娱乐和电子进阶明显更划算。

引用
评论
Tangshm作者
1年4个月前IP:北京
944971
9楼

对啊,都是有利有弊,根据需求选合适的方案就行~

引用
评论
7个月14天前IP:广东
949284
10楼

在arduino生态里, tenny4.x确实是无敌的存在, 甚至在传统mcu的里rt106x也有一席之地。

平民芯片pico这个确实性能够好,相比之下avr就没啥玩头。


再几个好玩的就是esp32的wifi,nordic的蓝牙.

引用
评论
Tangshm作者
5个月29天前IP:北京
949912
11楼

今天小试了一下microPython,编各种接口程序都挺好,比arduino IDE还简单一点,但是文件系统就很麻烦,找了半天也没找到资料,有没有高手知道怎么弄?就是给它设置一个U盘存数。在arduino IDE环境下有FatFSUSB.h,一条语句就搞定了

引用
评论
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的