- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
问题
我正在寻找有关如何优化将整数数字(例如uint32_t num = 1234567890;
)打印到具有Arduino UNO的字符显示器的输入。 要考虑的主要指标是内存使用情况和编译大小。 显示太慢了,以至于速度的提高没有意义,最小的代码长度虽然不错,但这不是必需的。
目前,我正在使用num%10
提取最低有效位,然后通过num/10
删除此位,依此类推,直到提取了num
的所有位。使用递归,我可以反转打印顺序,因此只需很少的操作(作为显式代码行)即可按正确的顺序打印数字。使用for
循环,我需要找到用于写入数字的字符数,然后存储它们,然后才能以正确的顺序打印它们,这需要一个数组和3个for
循环。
根据Arduino IDE,当打印各种有符号和无符号整数时,递归使用 2010/33 字节的存储/内存,而迭代使用 2200/33 字节与 2474/52 字节(使用Adafruit_CharacterOLED
库)扩展了类Print
。
是否有比我使用下面的递归和迭代编写的函数更好的实现方法?如果没有,您想要哪个,为什么? 我觉得可能有一种更好的方法来用更少的资源来执行此操作-但也许我是Don Quixote与风车作战,并且代码已经足够好了。
背景
我正在使用NHD-0420DZW字符OLED显示器,并已使用Newhaven数据表和LiquidCrystal库作为编写我自己的库的指南,并且该显示器运行良好。但是,为了最大程度地减少代码膨胀,我选择不让显示库成为Print
的子类,它是Arduino核心库的一部分。这样,已经实现了存储空间(〜400字节)和内存(〜19字节)的显着节省(ATmega328P具有32k的存储空间和2k的RAM,因此资源稀缺)。
递归
如果我使用递归,则打印方法相当优雅。该数字除以10,直到达到零的基本情况。然后,打印最小编号的最低有效数字(数字的MSD),以及下一个最小编号的LSD(数字的第二MSD),依此类推,导致最终的打印顺序颠倒。这可以使用%10
和/10
操作纠正数字提取的相反顺序。
// print integer type literals to display (base-10 representation)
void NewhavenDZW::print(int8_t num) {print(static_cast<int32_t>(num));}
void NewhavenDZW::print(uint8_t num) {print(static_cast<uint32_t>(num));}
void NewhavenDZW::print(int16_t num) {print(static_cast<int32_t>(num));}
void NewhavenDZW::print(uint16_t num) {print(static_cast<uint32_t>(num));}
void NewhavenDZW::print(int32_t num) {
if(num < 0) { // print negative sign if present
send('-', HIGH); // and make num positive
print(static_cast<uint32_t>(-num));
} else
print(static_cast<uint32_t>(num));
}
void NewhavenDZW::print(uint32_t num) {
if(num < 10) { // print single digit numbers directly
send(num + '0', HIGH);
return;
} else // use recursion to print nums with more
recursivePrint(num); // than two digits in the correct order
}
// recursive method for printing a number "backwards"
// used to correct the reversed order of digit extraction
void NewhavenDZW::recursivePrint(uint32_t num) {
if(num) { // true if num>0, false if num==0
recursivePrint(num/10); // maximum of 11 recursive steps
send(num%10 + '0', HIGH); // for a 10 digit number
}
}
void NewhavenDZW::print(uint32_t num) {
if(num < 10) {
send(num + '0', HIGH);
return;
}
uint8_t length = 0;
for(uint32_t i=num; i>0; i/=10) // determine number of characters
++length; // needed to represent number
char text[length];
for(uint8_t i=length; num>0; num/=10, --i)
text[i-1] = num%10 + '0'; // map each numerical digit to
for(uint8_t i=0; i<length; i++) // its char value and fix ordering
send(text[i], HIGH); // before printing result
}
if
语句停止前导零并能够打印
0
)。当必要的
if
语句被加上时,与darune(273)相比,它还需要更少的指令(88)。
void NewhavenDZW::print(uint32_t num) {
char buffer[10];
char* p = buffer;
do {
*p++ = num%10 + '0';
num /= 10;
} while (num);
while (p != buffer)
send(*--p, HIGH);
}
for
循环试图做的,但是很幼稚。正如Igor G指出的那样,试图最小化缓冲区数组的大小确实没有任何意义。
void NewhavenDZW::print(uint32_t num) {
char text[10]; // signed/unsigned 32-bit ints are <= 10 digits
uint8_t i = sizeof(text) - 1; // set index to end of char array
do {
text[i--] = num%10 + '0'; // store each numerical digit as
num /= 10; // its associated char value
} while (num);
while (i < sizeof(text))
send(text[i++], HIGH); // print num in the correct order
}
pow10 == 100
与
pow10 == 1
相同,但是保留了两次循环迭代以在编译大小相同的情况下打印零。
void NewhavenDZW::print(uint32_t num) {
for (uint32_t pow10 = 1000000000; pow10 != 0; pow10 /= 10)
if (num >= pow10 || (num == 0 && pow10 == 100))
send((num/pow10)%10 + '0', HIGH);
}
最佳答案
试试这个。我的avr-gcc-5.4.0 + readelf
告诉函数主体只有138个字节。
void Send(uint8_t);
void OptimizedPrintf(uint32_t val)
{
uint8_t buffer[sizeof(val) * CHAR_BIT / 3 + 1];
uint8_t* p = buffer;
do
{
*p++ = (val % 10) + '0';
val /= 10;
} while (val);
while (p != buffer)
Send(*--p);
}
关于c++ - 迭代与将整数打印到字符LCD/OLED显示器的递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57798199/
我有一个基于 ARM 的板( http://wiki.friendlyarm.com/wiki/index.php/NanoPi_M1 )并在其上使用 Ubuntu-server 16.04。我有一个
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭11 年前。 Improve th
我对我的第一个 LCD 示例感到疯狂。 我使用Arduino Uno,我想用最简单的例子尝试液晶屏:Hello World液晶示例。 我以与上面示例相同的方式连接引脚,但 LCD 首先在第一行显示 1
我已经非常接近在 LCD 上按预期输出了。问题是,当我从整数中提取数字以将数字作为整数并将余数作为我的分数时,我似乎无法获得正确的输出。 在小数点之前,输出看起来很好,但在小数点之后,则不然。 voi
我已经对 Atmega-16 微 Controller 进行了编程,以连接 LM016L LCD 显示器。程序如下: #include #include #define MrLCDsCrib PO
我正在编写一个在微处理器和 LCD 屏幕上从 3 开始倒数的函数。 void countdown() { _delay_ms(1000); draw_string("3",40,20); _delay
我被要求为 a display like the one in this ad 设计一个 LCD 墙应用程序. 要求是墙可以显示全屏视频或将墙分成不同的部分以显示多个视频或图像和视频。 我想了解可以使
我在这里有一个小问题。我有一个与arduino接口(interface)的16x2 lcd。在下面的闪烁中我可以使光标闪烁,但我想闪烁数字而不是光标。如何在这里使用 arduino。 Keypad s
我为带有 HD44780 Controller 的 LCD 创建了一个库,从数据表中我读到代码 0x18 会将整个显示向左移动一个位置,但是当我这样做时,显示消失了。我还读到 0x1C 将整个显示向右
我正在尝试为 20x2 LCD 制作一些自定义字符。我正在使用 Atmega µController 来控制具有 4 位接口(interface)的 LCD。我对 LCD 的所有命令似乎都能正常工作(
这是我尝试显示湿度传感器数据的代码到我的液晶显示器... 当我运行这个程序时, Traceback(most recent call last): File "lcd.py", line 7 in l
我正在尝试通过 USB 串行端口将整数从 MATLAB 发送到 Ardunio Uno,然后将它们显示在 LCD 上。我的问题是 128 到 159 的数字在 Arduino 显示器上显示为 63。
我用Tiva c驱动LCD,但有些字符和数字显示错误,例如N显示为L,2和3显示为0,但其他字符和字母显示正确。 下面是显示字符的函数: void LCD_voidWriteCharacter(cha
我已将 LCD 显示器连接到我正在从事的项目中。我有很多输入/输出,我想根据输入的状态显示不同的消息。现在,在我开始复杂化/添加更多硬件之前。我需要一些帮助。当没有输入处于事件状态时,我希望 LCD
我有一个带有 I2C 背负式适配器的 2 x 16 LCD 显示器。作为一个简单的开始,我只是显示编码器值。但是,当我转动编码器时,我会在不同区域的液晶显示屏上看到奇怪的文字。有时显示会恢复并仅显示“
我正在用 做一个小项目arduino 以太网 板。我是arduino的新手,想知道是否关注液晶显示器是否与我的 arduino 兼容。如果兼容,我是否需要更多硬件,例如电缆等... 我的 Arduin
我正在尝试使用 Jfxtras 中的 LCD 仪表。这是我必须创建仪表的代码: final Gauge lcd = GaugeBuilder.create() .gau
我有一个数组,其输入是由用户使用键盘给出的。所有输入都存储在名为 storeKeys 的数组中。数组的索引由变量storeKeysIndex保存,初始化为0,当按下一个键时,按下的键的值存储在stor
目前我正在制作一个用于将自定义文本打印到 LCD 的类。 我将 lcd 对象作为构造函数中的参数传递给类。 Display.h #ifndef Display_h #define Display_h
我只想以 LCD 格式显示系统时钟时间。我还希望使用 hh:mm:ss 格式显示时间。我的代码如下。但是当我运行它时,它并不像我预期的那样。谁能解释一下为什么? import sys from PyS
我是一名优秀的程序员,十分优秀!