【问题标题】:PIC 18F46K22, MikroC: 'Multitasking' simple and time consuming taskPIC 18F46K22,MikroC:“多任务”简单而耗时的任务
【发布时间】:2013-06-04 10:21:48
【问题描述】:

我收到一条 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 等。

欢迎提出任何建议!

【问题讨论】:

    标签: c multitasking pic uart mikroc


    【解决方案1】:

    进入显示器的数据的变化速度不需要超过观众的感知速度。如果您的更改大于阈值(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)

    【讨论】:

    • 好的,让我们看看我是否理解正确。我可以在 UART 请求/接收例程期间调用 UpdateDisplay,因此当有新的 RPM 值可用时。然后检查该值是否与以前不同。然后才调用 UpdateNeeded = 1。我需要使用 TimerServiceRoutine 作为中断(ISR)吗? TMR0?
    • 差不多。您对“如果值不同”的检查应在 if (UpdateNeeded) { 内,如 if (UpdateValue != OldUpdateValue) { UpdateLCD(UpdateValue); OldUpdateValue = UpdateValue; }
    • 推荐 TimerServiceRoutine() 定期调用,但不在 ISR 内。
    • 嗯,但是如何在 n (60) Hz 时调用?
    • 使用中断时间设置为 16ms 的定时器?这将产生大约 60 次中断一分钟。
    【解决方案2】:

    解决方案#1

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

    否则您的主循环可能每秒执行数千个循环。

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

    通过这种方式,您的主循环可以在不等待 LCD 的情况下运行,同时 LCD 也可以足够快地更新(取决于没有 LCD 任务的主循环的周转时间是否足够低:最好小于典型的LCD 的“忙”时间)。

    解决方案#2

    如果 LCD 过程由于某种原因计算量很大(在图形 LCD 上逐个像素地工作?),这会更复杂并且适用。

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

    如果您希望主任务更准确的计时,则需要将主任务置于中断中(假设您从传感器请求数据,您需要一个计时器 IT 来为这些请求计时)。主循环只能与 LCD 一起使用。

    常见元素

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-12
      • 2017-06-10
      • 2018-03-17
      • 2019-02-21
      • 1970-01-01
      • 1970-01-01
      • 2021-09-02
      相关资源
      最近更新 更多