数码之家

 找回密码
 立即注册
搜索
查看: 1260|回复: 9

[STM] arduino的性能测试

[复制链接]
发表于 2022-7-21 10:48:37 | 显示全部楼层 |阅读模式
前言:开发语言没有好与坏,只有适合不适合,希望大家不要开范围炮


MCU:STM32F03RCT6
采样频率:16Mhz
语言:paltformIO(Arduino)
主频:默认,应该是72MHZ
操作IO:PC0-PC7


测试背景:最近折腾一个128*160的8080并口屏,使用arduino写demo测试.库没找到8080并口的,都是IIC和SPI的,就从网上找demo移植了一个,结果刷新速度不尽人意,清一屏差不多1s,明显太不理想了.研究了下最大的原因主要有两点:1.arduino不支持并口操作,只能一位一位的写(我是没找到对应方法),这就导致速度差了8倍 2.arduino在LL库上又进行了多层封装,调用方法本身就有时间开销.
所以测试直接把IO操作换成调用寄存器,结果效果显著,清屏速度差不多能到40帧(速度都是估算,没用精确测试)


以下用逻辑分析仪测试下实际速度
1:digitalToggle切换IO状态
  1. void loop() {
  2.   digitalToggle(PC0);
  3. }
复制代码

2:寄存器切换IO状态
  1. void loop() {
  2.   WRITE_REG(GPIOC->ODR, READ_REG(GPIOC->ODR) ^0x01);
  3. }
复制代码

可见配置单个IO用digitalToggle用时0.625us,寄存器用时0.3125us,差了一倍,但是这个时间并不准确,因为这个时间还包括了方法调用
3:方法内digitalToggle多次切换IO
  1. void loop() {
  2.   digitalToggle(PC0);
  3.   digitalToggle(PC0);
  4. }
复制代码

可见后一次切换明显比前一次时间长,digitalToggle操作实际用时应为0.3125us
4:方法内寄存器多次切换IO
  1. void loop() {
  2.   WRITE_REG(GPIOC->ODR, READ_REG(GPIOC->ODR) ^0x01);
  3.   WRITE_REG(GPIOC->ODR, READ_REG(GPIOC->ODR) ^0x01);
  4. }
复制代码



同样两次寄存器操作,可见寄存器操作实际用时62.5ns,差距明显
5:digitalToggle模拟并口操作
  1. void loop() {
  2.   digitalToggle(PC0);
  3.   digitalToggle(PC1);
  4.   digitalToggle(PC2);
  5.   digitalToggle(PC3);
  6.   digitalToggle(PC4);
  7.   digitalToggle(PC5);
  8.   digitalToggle(PC6);
  9.   digitalToggle(PC7);
  10.   digitalToggle(PC0);
  11.   digitalToggle(PC1);
  12.   digitalToggle(PC2);
  13.   digitalToggle(PC3);
  14.   digitalToggle(PC4);
  15.   digitalToggle(PC5);
  16.   digitalToggle(PC6);
  17.   digitalToggle(PC7);
  18. }
复制代码

8位操作一次用时2.938us
6:寄存器并口操作
  1. void loop() {
  2.   WRITE_REG(GPIOC->ODR, READ_REG(GPIOC->ODR) ^0xFF);
  3.   WRITE_REG(GPIOC->ODR, READ_REG(GPIOC->ODR) ^0xFF);
  4. }
复制代码

用时还是62.5ns,可见和digitalToggle位操作相比写一次并口快了2938/62.5=47倍


后记:
实际上不光是arduino慢,HAL库一样慢,快慢只是相对的,arduino底层也是调用的LL库,自己觉着哪个顺手用哪个就好,需要关注性能的时候可以考虑寄存器混合开发,虽然这样对于arduino来说失去了可移植性,但是实际上特别是搞diy的有几个需要考虑移植呢



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 4家元 +80 收起 理由
玛德陛下 + 10 謝謝分享
jf201006 + 20 原創內容
家睦 + 40
jpdd521 + 10 高手啊,看赏。。。

查看全部打赏

发表于 2022-7-21 10:52:11 | 显示全部楼层
arduino 还是做的效率不错的,尤其是原来的atmel系列优化很好。            m3内核可能会差一点   
回复 支持 反对

使用道具 举报

发表于 2022-7-21 11:04:29 | 显示全部楼层
高手啊,看赏。。。
回复 支持 0 反对 0

使用道具 举报

发表于 2022-7-21 11:24:06 | 显示全部楼层
我都用micropython了,根本不考虑速度
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-21 11:28:30 | 显示全部楼层
jpdd521 发表于 2022-7-21 11:04
高手啊,看赏。。。

就是个老菜鸟
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-21 11:29:26 | 显示全部楼层
丶陪妳看流星 发表于 2022-7-21 11:24
我都用micropython了,根本不考虑速度

语言是死的,人是活的,只要把想要的功能做出来就是高质量优质人才
回复 支持 反对

使用道具 举报

发表于 2022-7-21 16:20:31 | 显示全部楼层
我现在都直接用寄存器操作, 快捷高效, diy不需要考虑什么移植
回复 支持 反对

使用道具 举报

发表于 2022-7-21 16:40:32 来自手机浏览器 | 显示全部楼层
这个厉害
回复 支持 反对

使用道具 举报

发表于 2022-7-22 17:54:24 | 显示全部楼层
本帖最后由 freemancn 于 2022-7-22 18:17 编辑

我也来测试一下。
我用C++写了STM32F103,硬件运行频率和你相同,自己做了硬件抽象层可以兼容不同品牌的MCU。
1.IGpioPin是对GPIO的抽象,是一个虚基类,内部的方法都是虚方法没有方法体。




2.CGpioPin是STM32F103单片机的具体实现,继承IGpioPin。实现所有虚方法,使用的是寄存器操作。这里面方法体是有代码的,由于篇幅原因就不展开显示了。

3.main.cpp在这个里面初始化单片机的运行频率和其它一些东西,然后反转一个GpioPin进行测试。


4.测试结果是


5.当把while循环体改为GpioPin状态反转后的测试结果为。ToggleState使用的是位带操作。





6.程序的编译结果如下图
程序长度:1728 bytes
内存消耗:2188 bytes

编译器是ARM官方的GCC 10.3.1


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 1家元 +20 收起 理由
飞向狙沙 + 20 精彩回帖

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2022-7-23 01:47:10 | 显示全部楼层
Arduino 本来定位就是 业余DIY, 所以牺牲性能增加易用是值得的。各种库、简单到复制粘贴即可。至于追求极限性能效率的可能也不会想着用arduino搞开发。
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-4-26 18:51 , Processed in 0.109200 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

快速回复 返回顶部 返回列表