Embedded 嵌入式系统-轮询

Embedded 嵌入式系统-轮询,embedded,interrupt,sensors,polling,Embedded,Interrupt,Sensors,Polling,我有大约6个传感器(GPS、IMU等),需要不断地从中收集数据。出于我的目的,我需要从每个数据包(在一个小的时间范围内)读取一个完整的数据包。现在我正在使用中断,但这会导致来自某些传感器的数据比其他传感器的数据多,而且,正如前面提到的,我需要将数据进行匹配 是否最好转向基于轮询的系统,在该系统中,我可以按设定的顺序轮询每个传感器?通过这种方式,我可以在每个“周期”获得来自每个传感器的数据 然而,我担心轮询的速度,因为该系统需要接近实时运行。轮询与“主定时器中断”相结合可能是您的朋友。假设您的“最

我有大约6个传感器(GPS、IMU等),需要不断地从中收集数据。出于我的目的,我需要从每个数据包(在一个小的时间范围内)读取一个完整的数据包。现在我正在使用中断,但这会导致来自某些传感器的数据比其他传感器的数据多,而且,正如前面提到的,我需要将数据进行匹配

是否最好转向基于轮询的系统,在该系统中,我可以按设定的顺序轮询每个传感器?通过这种方式,我可以在每个“周期”获得来自每个传感器的数据

然而,我担心轮询的速度,因为该系统需要接近实时运行。

轮询与“主定时器中断”相结合可能是您的朋友。假设您的“最慢”传感器可以每隔20毫秒提供数据,而其他传感器的读取速度更快。这是每秒50次更新。如果这足够接近实时(对于IMU来说可能很接近),也许您可以这样进行:

  • 设置一个20ms计时器
  • 计时器关闭时,在中断服务例程内设置一个标志:

    volatile uint8_t timerFlag = 0;
    
    ISR(TIMER_ISR_whatever)
    {
        timerFlag = 1;  // nothing but a semaphore for later...
    }
    
  • 然后,在主循环中,当
    timerFlag
    表示时间到了时,执行以下操作:

    while(1)
    {
        if(timerFlag == 1)
        {
            <read first device>
            <read second device>
            <you get the idea ;) >
            timerflag = 0;
        }
    }
    
    while(1)
    {
    如果(timerFlag==1)
    {
    timerflag=0;
    }
    }
    
  • 通过这种方式,您可以读取每个设备并保持其读数同步。这是在嵌入式空间中解决这一问题的典型方法。现在,如果你需要的数据速度超过20毫秒,那么你可以缩短计时器,等等。在这种情况下,最大的问题是“你能以多快的速度进行轮询”和“你需要以多快的速度进行轮询”。只有通过实验和了解各种设备的特性和计时才能告诉你这一点。但我提出的是一个通用的解决方案,当所有的时间都“合适”时

    编辑,另一种方法

    一个更基于中断的示例:

    volatile uint8_t device1Read = 0;
    volatile uint8_t device2Read = 0;
    etc...
    
    ISR(device 1)
    {
        <read device>
        device1Read = 1;
    }
    ISR(device 2)
    {
        <read device>
        device2Read = 1;
    }
    etc...
    
    
    // main loop
    while(1)
    {
        if(device1Read == 1 && device2Read == 1 && etc...)
        {
            //< do something with your "packet" of data>
            device1Read = 0;
            device2Read = 0;
            etc...
        }
    }
    
    volatile uint8\u t device1Read=0;
    易失性uint8_t设备2读取=0;
    等
    ISR(设备1)
    {
    设备1读取=1;
    }
    ISR(设备2)
    {
    设备2读取=1;
    }
    等
    //主回路
    而(1)
    {
    如果(device1Read==1&&device2Read==1&&etc…)
    {
    //<用你的“数据包”做点什么>
    device1Read=0;
    device2Read=0;
    等
    }
    }
    

    在本例中,您的所有设备都可以是中断驱动的,但主循环处理仍然受最慢中断的节奏控制。可以使用来自每个设备的最新完整读取,无论速度或延迟如何。这种模式更接近您的想法吗?

    轮询是一个非常好且易于实现的想法,以防您的传感器可以立即提供数据(与您所需的输出频率相比)。当您的数据源需要大量(甚至可变)时间来提供读取或需要异步“启动/收集”周期时,它确实会陷入噩梦。您必须对轮询周期进行排序,以适应“最慢”的数据源

    如果您知道每个数据源的平均“数据转换率”,那么解决方案可能是设置一些计时器(每个数据源),在
    轮询时间触发-数据转换率
    ,并从这些计时器ISR开始测量。然后在
    轮询计时器+一些安全裕度处触发最后一个计时器,以收集所有转换结果

    另一方面,你从“快速”数据源“测量过多”的明显问题不会给我带来太多麻烦,只要你对浪费的CPU/传感器负载没有任何合理的处理


    最后一种更简单的方法是:简单地将数据源从“最慢”排序为“最快”,并按该顺序开始测量,然后按相同的顺序等待结果并进行投票。

    所以问题是。。。?测试你的轮询循环时间,看看它是否符合你的要求……我个人不喜欢轮询。你的传感器没有中断吗?只轮询和只中断都与实时无关,你必须进行系统工程,这将给出所有答案。在确定每个事件路径的时间时,轮询当然是最容易的,只要最慢的路径不干扰其他路径的要求,就可以了。有时你只能通过轮询或中断来完成这项任务,但最终可能会出现在中间。中断并不意味着你在那里处理它们,顺便说一句,这有时是不好的,所以没有一个答案。@Clifford确实如此。在这样的情况下,外设的采样率相差悬殊,我所做的就是使用计数器“减速”时差。平衡机器人的IMU可能需要每秒50次更新才能保持直立,而GPS只能轮询50次中的1次。这就是我不喜欢轮询的原因。使用这种方法,您必须计算所有传感器组合的数据处理延迟,并确保第一个传感器的轮询间隔不超过20ms(例如)。“将来一旦您添加了一个新的传感器,或者传感器在数据处理或轮询间隔方面发生了变化,您的所有循环方案都会失败,变得完全无法维护和无法扩展。”Alex同意。我喜欢尽可能地打断别人。然而,OP的问题是关于投票的,事实上,这样做是可能的。OP可能不想在这里扩展任何东西,只是一个一次性的解决方案。因此,我没有做出判断,而是用一个可能的解决方案回答了她的问题。@JLH我更喜欢使用中断。然而,我不确定如何确保每个“周期”中每个传感器的读数。我的系统中的每个数据块都必须有来自六个传感器的数据。是否有一个基于中断的解决方案可以简化可伸缩性?@Ana这是您的难题——每个设备的中断意味着数据