在Arduino编程中,经常会遇到一些函数,它们虽然易于使用,但在执行效率上却不尽如人意。这些函数在与更高效的实现方式比较时,其笨重和缓慢的特性就变得显而易见。通常,这些低效函数的支持者会辩解说,它们主要是为业余爱好者设计的,这些用户往往更看重易用性而非效率。
本文并不是要介绍最快的实现方式,而是要介绍一种在保持原有Arduino函数易用性的同时,提高效率的实现方法。
几年前,当还在大学时,进行了一项研究,目的是使Arduino库更加高效。虽然成功了,但它从未在实验室之外使用过。但现在已经清理了代码,使其使用起来更加容易。
使用这个代码相当简单。只需要将FastIO.h
和FastIO.c
复制到Arduino核心目录下:
[Arduino Folder]\hardware\arduino\avr\cores\arduino
然后在草图中包含头文件:
#include
Arduino上的每个引脚都连接到AVR微控制器的一个引脚上。这些引脚被分配到不同的端口上。这些端口在AVR的内存中以不同的地址映射。为了操作这些引脚,必须写入这些特定的内存区域。
Arduino是如何仅通过使用引脚编号来访问其引脚的呢?实际上,Arduino已经将其所需的所有信息保存在内存中。所以,当调用digitalWrite
到一个特定的引脚时,Arduino软件会在其内存中搜索所需信息(引脚所属端口的地址以及它在端口上的位置)。Arduino软件还需要一些额外的信息,即引脚是否也连接到计时器,如果是,那么是哪一个计时器以及在哪个位置。
所有这些开销使得Arduino的内置函数非常慢。实现试图通过使所有所需信息对函数随时可用来减轻这种开销。这样,函数可以在被调用时立即开始操作引脚,而不是搜索信息。
它通过将信息存储在4字节的数组中来工作。第一个字节包含引脚在特定端口上的位置。第二个字节包含引脚所属端口的地址。如果引脚也连接到计时器,那么第三个字节包含控制引脚功能的计时器引脚。第四个字节包含连接到引脚的计时器的地址。如果引脚没有连接到计时器,那么第三个字节和第四个字节都将等于零。
在函数调用时,将传递这个数组的引用给函数,而不是简单地传递引脚编号。
内置的digitalWrite
函数需要大约5微秒来改变引脚状态,这对于运行在16MHz(62.5ns周期)的微控制器来说是非常慢的。实现通过将时间减少到大约250纳秒,使这个函数的速度提高了20倍。所有这些性能提升都是在不改变草图代码的情况下实现的,这也是这个实现的主要目标。
作为一个额外的好处,使用代码时,编译后的草图大小也更小(一举两得)。
正如在这里看到的,几乎可以在不改变草图的情况下实现接近原生的速度。