嵌入式“智能”字符LCD驱动器。这是一个好主意吗?

时间:2010-05-23 15:53:59

标签: language-agnostic embedded electronics lcd

我正在进行一个嵌入式项目,我正在编写字符LCD驱动程序。

目前,LCD驱动程序仅支持“哑”写入。例如,假设第1行上有一些文本,我调用写入该行的函数。该函数将简单地寻找行的开头并写入文本(加上足够的空格来擦除最后写的内容)。

这很好,但我觉得它有时非常低效,因为有些线条很简单: “有些阅读:有些价值”

而不是“蛮力”取代整行,我想开发一些代码,以找出更新 LCD上信息的最佳方法。

(就像背景一样,它需要2个字节来寻找任何一个char位置。然后我就可以开始写字符串了)

我的想法是首先要有一个循环。这个循环会将输入与最后一次写入进行比较,这样做可以涵盖两件事:

答:收集最后一次写入和输入之间的所有差异。对于每个连续的段(相同或不同),将两个字节添加到字节计数中。这在B中引用,以确定我们是否在浪费串行带宽。

B:循环将决定这是否真的很聪明。如果我们最终使用更多字节来更新线而不是“强力”线,那么我们应该返回并让暴力方法接管。我们应该在满足这个条件时立即退出智能写入功能,以避免浪费时间。

该函数的下一部分将采用所有差异,在LCD上寻找所需的字符,然后编写它们。

因此,如果LCD上已经有这样的字符串: “当前温度:80F” 我们想要更新它 “当前温度:79F”

该功能将通过并看到只需寻找“8”并写“79”就需要更少的带宽。 “7”将覆盖“8”,“9”将覆盖“0”。这样,我们不会浪费时间写出整个字符串。

这看起来像是一个实用的想法吗?

6 个答案:

答案 0 :(得分:2)

假设显示器的偏移量自动递增,并且输出每个连续字符只需一次写入,我会倾向于每次只编写整个显示行,除非您尝试修复特定的性能问题。即:不必要的优化是潜在的未来维护问题,您的“优化”时间将更好地用于实际影响整个应用程序性能的事情。

注意:如果显示更新实际上是影响性能问题的应用程序,那么您可能感觉它需要多快...然后您(而不是我们)可以成为您自己的优化指南就够了。

答案 1 :(得分:2)

优化它没有任何意义。以9600波特率传输20个字节需要硬件21毫秒。并且需要几微秒的软件。足够快,能够比人眼所感知的更快地更新显示器2倍。并且它不像你需要“带宽”,没有任何额外的数据,我可以想到你我想在串行频道上进行多路复用。

答案 2 :(得分:0)

您计划的实施似乎过于复杂而无法解决问题。如果处理器不快,那么所需的所有比较实际上可能会减慢操作速度。

如果您只需要更新温度值,您应该只更新温度值并忽略固定文本。您需要在内存中为每个需要更新的字段设置坐标。然后只需将写入位置移动到该位置并写入值。这就是我通常的做法。

如果屏幕更新仍然太慢,您可以考虑使用汇编语言。例如,几年前我为带有点阵LCD显示器的手表型设备制作了软件。显示更新太慢(例如滚动时更新整个显示器几乎一秒钟),因此我只在Assembly中编写了最低级别的例程(用30行的Assembly替换了大约20行的C)。结果函数的大小只有优化的C函数的一半,速度快了3倍,现在显示更新速度已经足够了。

答案 3 :(得分:0)

  

这样,我们不会浪费时间写作   整个字符串。

你不应该浪费太多时间,当然要少于完成所有这些检查所需的时间。

液晶显示器的连接是什么? SPI / I 2 C /中并行?

无论是什么,如果接口上的SoC支持DMA,请使用它。

如果没有,则不应在tx字节之间等待,特别是如果处理器的指令时钟远远高于数据链路的时钟。这可能是正确的,因为我使用过的大多数字符显示器都具有较低的最大时钟规格。

如果您可以控制中断路由(正在执行此操作以节省电量),请使用中断例程来处理发送每个字节或使用“混合”方法。这是一篇有趣的写作here

答案 4 :(得分:0)

对于字符显示,这种更新优化是{{​​1}}库的全部内容。回到白天,当我们与具有1200波特或更低波特率的哑终端和电话线的大型计算机交谈时,通常很难快速更新屏幕以使程序通过慢速调制解调器链路感觉交互。 curses库通过保留用户屏幕上应该包含的内容的缓存并发送接近最佳数量的移动和擦除命令来实现显示,该命令散布有正常字符以供显示。它确实要求终端支持某种形式的光标定位。

curses库以多种形式存在,例如,ncurses是众所周知的,开源的,并且在GPL下获得许可。

原则上,你可以让ncurses与你的显示控制器交谈,让它做所有艰苦的工作。

悬而未决的问题是,是否值得付出努力。在9600波特,您可以每秒发送960个字符。这足够快,每秒12次完全重绘4行20列LCD。因此,除非您在PIC或ATtiny中运行,否则您可能需要在软件中实现UART并且需要循环来实际执行某些有用的操作,因此过于聪明可能没什么优势。

也就是说,一旦绘制固定文本通常仍然有意义,只需更改显示的值即可。

答案 5 :(得分:0)

文字模式LCD

我同意其他人的意见,如果你是在文字模式下写作,那么在角色层面上没有任何意义。进行计算所需的处理时间可能需要与实际编写内容的时间一样长。

此外,每个字符级别将咀嚼一些内存,因为您需要缓冲当前显示的内容(即上次写入的内容)。

您可以通过将屏幕分成多个部分(线条往往是最方便的)来简化过程,然后标记该线条何时发生变化。如果您想要写入屏幕的内存缓冲区并稍后进行同步(例如,在定时中断中),这将非常有用。

按设计减少

您可以通过确保只编写更改的内容来减少应用程序级别的写入时间,而不是将其留给驱动程序来实现。这可以通过指定特定的值单元来实现,基本上执行以下操作:

char text[50];
int val;
...
lcd_print("The count is ", 0, 0); // Print static text at the coords (0,0)
sprintf(text, "%d", val);
lcd_print(text, 0, 13); // Print changing text at (0,13)
...
sprintf(text, "%d", val);
lcd_print(text, 0, 13); // Print changing text at (0,13)

而不是:

char text[50];
int val;
...
sprintf(text, "The count is %d", val);
lcd_print(text, 0, 0); // Print all text at the coords (0,0)
...
sprintf(text, "The count is %d", val);
lcd_print(text, 0, 0); // Print all text at the coords (0,0)

图形模式LCD

另一方面,如果您的写入过程非常昂贵,例如我的(大约20个字节,在图形模式下绘制一个字符),那么在字符基础上节省时间将是有用的。您可以使用两种方案。第一个是您所描述的,但您可能还想考虑(如果使用图形模式)通过文本行缓冲水平像素线的概念。

基于每个字符编写每个字符需要手动将写入光标移动到像素线,假设您的绘图是水平的,然后是从上到下。可以通过在文本行上写下所有字符的所有顶行来删除此步骤,或者甚至更好地更改子集(即“ABC”,然后在“XXXDEFGHX”中单独“I” - &gt;“ABCDEFGHI”)。< / p>

当然,使用后一种方法的确切保存将取决于构成字符高度的像素行数。线越多,保存越多(因为您需要将光标移动更多次)。