【发布时间】:2018-04-14 13:45:51
【问题描述】:
我正在使用 ATtiny85 和 128x64px OLED 构建一个小玩具控制台。在我最初的构建中,我使用了内置的 shiftOut() 和 digitalWrite() 函数将显示数据转移到屏幕控制器。
这让我获得了大约 5fps,这有点令人失望。
我编写了自己的函数,该函数使用直接端口操作来发送数据,并且速度显着提高了 ~23fps,这还不错。这是那个函数:
void shift_out_block(block)
{
byte b;
for (byte i = 0; i < 8; i++)
{
b = pgm_read_byte(block+i);
for (byte j=0 ; j < 8 ; j++)
{
if ( !!( b & (1 << j)) )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
}
}
}
23fps 还可以,但不是 30 甚至 60fps(如果是 24fps,我实际上会把它留在这里,但是奇数......)。
我明白为什么删除库调用和操作端口直接改善了很多事情 - 库被编写为在各种不同的 MCU 上工作。
我隐约记得循环解开是一个事情,所以我解开了内部for 循环:
void shift_out_block()
{
byte b;
for (byte i = 0; i < 8; i++)
{
b = pgm_read_byte(block+i);
if ( !!( b & (1 << 0)) )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
if ( !!( b & (1 << 1)) )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
if ( !!( b & (1 << 2)) )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
if ( !!( b & (1 << 3)) )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
if ( !!( b & (1 << 4)) )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
if ( !!( b & (1 << 5)) )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
if ( !!( b & (1 << 6)) )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
if ( !!( b & (1 << 7)) )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
}
}
完全不费力,复制粘贴 7 次。给了我将近 75fps - 原始函数在 ~42ms 内执行,新的 ugly 只需要 ~13ms。
出于兴趣,我将 send bit 部分拆分为一个单独的函数并调用了 8 次:
void shift_out_bit(bool bit)
{
if ( bit )
{
PORTB |= 1 << SDA;
}
else
{
PORTB &= ~(1 << SDA);
}
PORTB |= 1 << SCL; // HIGH
PORTB &= ~(1 << SCL); // LOW
}
void shift_out_block()
{
byte b;
for (byte i = 0; i < 8; i++)
{
b = pgm_read_byte(block+i);
shift_out_bit( !!( b & (1 << 0)) );
shift_out_bit( !!( b & (1 << 1)) );
shift_out_bit( !!( b & (1 << 2)) );
shift_out_bit( !!( b & (1 << 3)) );
shift_out_bit( !!( b & (1 << 4)) );
shift_out_bit( !!( b & (1 << 5)) );
shift_out_bit( !!( b & (1 << 6)) );
shift_out_bit( !!( b & (1 << 7)) );
}
}
~22ms 执行,或 45.4545454545 fps,这甚至不是一个好数字。
无论如何,我都不是 C 程序员 - Python 是我经常出没的地方(我最初确实在 Python/RPi 中启动了这个项目,但非常很快就放弃了!) .
为什么在这种情况下这样的核心语言功能会慢得多?随着我的项目变得越来越复杂,我还应该考虑哪些其他优化?
【问题讨论】:
-
很抱歉,如果您知道这一点,但这看起来您有点在抨击 I2C。 ATtiny85 具有硬件 I2C。
-
另一个可能没用的评论是您正在测试 if( !!( b & (1
-
-
void shift_out_block(block)甚至不是一个有效的函数头。如果您不了解和理解该语言,就无法编写好的代码。 -
我有点抨击 SPI ;) 和双重!!是从其他地方复制和粘贴的,我还没有弄清楚它实际上做了什么,看看我是否可以简化它!