![e1b71d1950a4d4393ff8f6f7e201060c.gif](https://i-blog.csdnimg.cn/blog_migrate/f4b712ca86801e7088e51d2f3c7d4aa2.gif)
在《都2020年了,还有必要学Arduino吗》一文中,小编提到过随着嵌入式平台和框架之间的相互学习和融合,Arduino爱好者的工具箱里的工具也越来越多了,比如时下最流行的支持Arduino IDE开发的“四剑客”:
Arduino UNO R3
![5cab88bf88af17c693d58a66b3d70515.png](https://i-blog.csdnimg.cn/blog_migrate/350414204fda25a5ba346589d0fa9d25.jpeg)
UNO作为Arduino官方的标准开发板,血统当然最纯正,各种资源也最丰富。奈何这位“正宫太子”资质确实平平,一颗ATMega328P 8位AVR的心,这几年让人觉得有点“力不从心”了。
STM32F103C8T6 BluePill核心板在《如何使用Arduino IDE开发STM32(上)》中,我们提到过这块外号叫“BluePill(蓝色药丸)”的STM32F103C8T6核心板,蓝色药丸兄可谓出身世家,STM32家族庞大,兄弟众多,各个领域都有涉及。虽然作为家族小弟,这位仁兄有着32位的ARM心,72MHZ的主频,要身材有身材要模样有模样,还不骄不躁,价格亲民。10块钱不香么,您还要啥自行车?
ESP8266和ESP32两兄弟这两兄弟可谓是两匹土著黑马,完全没有显赫的家世,纯凭自己骨骼奇异、天赋异禀,借着物联网的大潮顺势而起,备受众人喜爱。在左邻右舍你一勺我一碗的给养下,什么C/C++、Lua、MicroPython、JS、mRuby、BASIC...什么功夫都会点。兄弟特点也很直白,小弟ESP8266只钻研WiFi门,然后就是头铁价格低,不服就肝。大哥ESP32双核心,左手练WiFI,右手练蓝牙,弟弟会的大哥我也全会,价格也很亲民。那有人可能会问,这“四剑客”里如果分个高下,谁的性能最牛呢?把四块开发板的参数列张表的话:
![a80a0d472a15cfe4c5050d963a5972c4.png](https://i-blog.csdnimg.cn/blog_migrate/cf52c9ff3f84e57d2d0a12511ad28069.png)
纯从参数上判断的话,很多硬件参数是高下立判的,比如说如果我们要比较四块开发板的处理能力最快,那从主频上看,应该是ESP32最猛,毕竟是双核,ESP8266应该比STM32F103稍快,最后才是8位的UNO R3。理论上应该是这样的,但实际上是这样的么?如果是,那到底快多少呢?今天我们就来实践一下。
![1a196c0f324af0578be7aab288676290.png](https://i-blog.csdnimg.cn/blog_migrate/d11ea3c8622e1e022a93d7b8762cb399.jpeg)
判断快的方法其实很简单:大家在同一时间间隔里处理同样的工作,谁的干的活越多谁就越快,或者大家干等量的工作,谁用的时间最少谁就越快。接下去我们就设计几种工作进行比较。
素数运算素数又称质数,指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。不废话,上代码:
//素数运算实验
long start = 0;
long max_seconds = 30;
long i = 2; // Start at 2
long found = 0; // Number of primes we've found
long lastPrime = 0;
void setup() {
Serial.begin(57600);
while (!Serial) { }
Serial.println("Prime calculation starting.");
start = millis();
}
void loop() {
int prime = is_prime(i); // Check if the number we're on is prime
if (prime == 1) {
//Serial.print(i);
//Serial.println(" is prime ");
lastPrime = i;
found++;
}
int running_seconds = (millis() - start) / 1000;
if (max_seconds > 0 && (running_seconds >= max_seconds)) {
Serial.print("\nFound ");
Serial.print(found);
Serial.print(" primes in ");
Serial.print(max_seconds);
Serial.println(" seconds");
Serial.print("Highest prime found was: ");
Serial.println(lastPrime);
delay(60000);
i = 2;
found = 0;
start = millis();
}
i++;
}
int is_prime(long num) {
// Only have to check for divisible for the sqrt(number)
int upper = sqrt(num);
// Check if the number is evenly divisible (start at 2 going up)
for (long cnum = 2; cnum <= upper; cnum++) {
long mod = num % cnum; // Remainder
if (mod == 0) {
return 0;
} // If the remainer is 0 it's evenly divisible
}
return 1; // If you get this far it's prime
}
这段代码的作用就是让单片机在30秒的时间内找尽可能多的素数,然后输出找到的素数数目和最大的素数。这里考验的是单片机纯整数运算的能力。
![e1f9c277e69420e6e4cc82412f4d5796.png](https://i-blog.csdnimg.cn/blog_migrate/974c2beabdb92e27bd918408cdcdbd68.png)
我们让四剑客都运行一遍相同的程序。结果如下:
![1c1b99261816b242d6cd4fe8fbbeda61.png](https://i-blog.csdnimg.cn/blog_migrate/5537b8437227f7c1f5ee085e49431ddb.png)
这里让小编比较惊讶的是STM32F103竟然秒掉了ESP8266,理论被打脸
![2d42104ca6478fd2cd058480e8d125a9.png](https://i-blog.csdnimg.cn/blog_migrate/2dac8edd176c7b47ceea41df0af17b60.png)
?当然ESP32大哥遥遥领先,默认还只用了一个核。
浮点运算所谓的浮点运算,简单地理解就是小数的加减乘除运算。因为单片机里处理的都是整数,小数就要用类似科学计数法的方式来表示。小数计算比整数复杂多了,有些单片机比如ESP32内置了单独的浮点计算器。测试代码如下,即输出10万次浮点运算的耗时:
//浮点运算实验
#pragma GCC optimize ("-O0") //disable the optimizer
float tt, aa = 12345.8;
long loops = 100000;
void setup() {
Serial.begin(115200);
while (!Serial) { }
Serial.println("Floating point calculation starting.");
}
void loop() {
long start = millis();
for (long i = 0; i < loops; i++) {
tt = 5000.0 * aa / i;
}
Serial.println(millis() - start); //milliseconds毫秒
Serial.println("=====");
delay(2000);
}
测试结果如下:
I/O速度测试最后,我们要来进行比较的是输入和输出的速度比较。比如pinMode,digitalWrite还有digitalRead这几个函数的运行速度。
//I/O速度测试实验
#pragma GCC optimize ("-O0") //disable the optimizer
int tt = 0;
long loops = 100000;
#if defined(ARDUINO_ARCH_AVR) //Arduino
#define testPin 2
#else
#if defined(ARDUINO_ARCH_ESP8266) //ESP8266
#define testPin D2
#else
#if defined(ARDUINO_ARCH_ESP32) //ESP32
#define testPin 2
#else
#define testPin A0 //STM32
#endif
#endif
#endif
void setup() {
Serial.begin(115200);
while (!Serial) { }
Serial.println("I/O speed test starting.");
}
void loop() {
long start = millis();
for (long i = 0; i < loops; i++) {
pinMode(testPin, OUTPUT);
digitalWrite(testPin, LOW);
digitalWrite(testPin, HIGH);
pinMode(testPin, INPUT);
digitalRead(testPin);
if (digitalRead(testPin)) {
tt = 150 * 1234;
} else {
tt = 554 % 12;
}
}
Serial.println(millis() - start); //milliseconds毫秒
Serial.println("=====");
delay(2000);
}
测试结果如下:
总结首先我们得承认三组实验还可以做的更加严谨,比如像开发板的不同设计、编译器设置、SDK的类型和版本等都会影响速度;还有对比结果可以更详细,比如整数运算和浮点运算都可以分加减乘除、digitalRead和digitalWrite、analogRead和analogWrite都应该分开测速...等等。
![514bf0d335352bfada1f3eb82fee102a.png](https://i-blog.csdnimg.cn/blog_migrate/fe583e8ed1c102705b2c7b4512340127.png)
但通过上面的三组实验粗略比较,相信大家已经对“四剑客”的“谁最快”、“快多少”有了大致的了解。但“快”并不是我们选择的唯一标准,最快的并不是最好的,适合你项目的才是最好的。
![db4a4f9af08994cabd23b65a1cfaa216.png](https://i-blog.csdnimg.cn/blog_migrate/9be724e996a08417dd33e182c69d4896.jpeg)
比如你的项目需要WiFi不需要蓝牙,而且对于性能并没有太高的要求,那就选NodeMCU/ESP8266;比如你的项目不需要无线连接,需要比较好的性价比,那就选STM32F103C8T6核心板,如果不会设置各种库和环境、简单能上手就行,那就乖乖选Arduin UNO R3吧。
![d7f33f2f6a1ec3b6a4ed9669a7c65427.png](https://i-blog.csdnimg.cn/blog_migrate/66353d9509d205b598e85cde9e169bf2.jpeg)
如果你不想选择,“四剑客”全都要,那欢迎光临我们的小店,四种开发板全有售。