c语言 - PIC 18F46K22, MikroC: 'Multitasking'简单耗时的任务



我正在接收一个包含原始传感器数据数组的UART消息。我正在程序的主循环中读取消息。有两件事我需要PIC做不同的值。将其显示在LCD上(有点耗时),并且,至少对于其中一个值,根据该值更改连接到PORTD的led条(相当简单)。

在主循环中,这是我当前的工作方式:

  • 从UART上的外部设备请求传感器数据
  • 从外部设备接收字节数组
  • 进行计算将原始传感器数据转换为实际值/单位
  • 使用此代码在lcd上显示RPM值:

     if (RPM < 99)
     {
       PORTD = 0;
     }
     if (RPM > 100)
     {
       PORTD = 0x01;
     }
     if (RPM > 2400)
     {
       PORTD = 0x03;
     }
     if (RPM > 3700)
     {
       PORTD = 0x07;
     }
     if (RPM > 4900)
     {
       PORTD = 0x0F;
     }
     if (RPM > 6200)
     {
       PORTD = 0x1F;
     }
     if (RPM > 7400)
     {
       PORTD = 0x3F;
     }
     if (RPM > 8700)
     {
       PORTD = 0x7F;
     }
     if (RPM > 10000)
     {
       PORTD = 0xFF;
     }
    
  • 最后在LCD上显示多个值。因此,删除旧值,绘制标签,设置新值,再次绘制标签。

最后一个任务减慢了整个循环,这使得led条函数"滞后"。我得到的建议是在重新绘制标签之前检查值是否发生了变化,以避免不必要的绘制。但是所有的值都是非常快速变化的值,比如RPM之类的。

欢迎任何建议!!

显示的数据不需要比查看者能感觉到的变化快。如果您的更改大于阈值(40至100 Hz),则仅使用在前一时期发生的最后一次更改。

int UpdateValue;
int UpdateNeeded = 0;
void TimerServiceRountine() { // called at N (60) Hz.
  if (UpdateNeeded) {
    UpdateNeeded = 0;
    UpdateLCD(UpdateValue);
  }
  // ...
}
// Call this with each RPM
void UpdateDisplay(int Value) {
  UpdateValue = Value;
  UpdateNeeded = 1;
}

进一步细化:仅当x与之前不同时调用UpdateLCD(x)

解决方案# 1

我的猜测是LCD部分的缓慢是由于您需要等待LCD处理发送给它的命令(某些字母数字LCD常见)。

你的主循环可能每秒运行几千个循环。

如果是这种情况,那么应该在主循环中为LCD输出实现一个状态机。只有当LCD准备好接受新命令时,这个状态机才会在每次主循环运行时,将必要的命令一个接一个地发送给LCD以更新显示。

这样你的主循环可以运行自由等待LCD,而LCD也得到足够快的更新(取决于没有LCD任务的主循环的周转时间是否足够低:最佳小于LCD的典型"繁忙"时间)。

解决方案#2

这是更复杂的,适用于如果LCD过程相当繁重的计算由于某种原因(像素逐像素的工作在图形LCD?)。

即使在这种情况下,与解决方案#1类似的方法也可以很好地工作。如果你能将LCD任务分割成处理时间要求大致相似的更小的块,你可能会加快主循环(一次只处理其中的一个块)。

如果您更喜欢主任务的更准确的计时,则需要将主任务置于中断中(假设您从传感器请求数据,则需要计时器IT来计时这些请求)。主循环只对LCD有效。

共同元素

在所有情况下,你做更多的采样,而一个单一的碎片LCD显示数据建设过程。这需要一些数据管理:在开始构建显示器之前,您必须"采样"(主要是复制,在最后一种解决方案的情况下禁用中断)您的数据到LCD上。

我提出的所有解决方案都是"理想的",因为它们可以使用所有可用的周期"自动"从硬件中提取最多(在显示更新频率方面)。您只需要根据您的情况选择合适的方法。

最新更新