Arduino-无中断计数脉冲

Arduino-无中断计数脉冲,arduino,Arduino,我想知道是否有一种方法可以在不执行中断程序的情况下对Arduino上的数字脉冲进行计数 进一步说明:我有一个传感器,它输出的数字脉冲与我想要计算的某个测量值成比例。不仅可以不用中断处理程序,还可以少用或不用软件,通过软件轮询或中断计数处理更快的脉冲率 大多数Arduinos基于的Atmel AVR具有计数器/定时器硬件,可直接对输入引脚中的脉冲进行计数。您所要做的就是为计数器操作配置硬件并读取计数器寄存器。8位设备上的16位计数器有一个小的复杂性,但这很容易克服。Arduino为默认PWM操作配

我想知道是否有一种方法可以在不执行中断程序的情况下对Arduino上的数字脉冲进行计数


进一步说明:我有一个传感器,它输出的数字脉冲与我想要计算的某个测量值成比例。

不仅可以不用中断处理程序,还可以少用或不用软件,通过软件轮询或中断计数处理更快的脉冲率

大多数Arduinos基于的Atmel AVR具有计数器/定时器硬件,可直接对输入引脚中的脉冲进行计数。您所要做的就是为计数器操作配置硬件并读取计数器寄存器。8位设备上的16位计数器有一个小的复杂性,但这很容易克服。Arduino为默认PWM操作配置定时器,但可以按照说明进行覆盖(有关更多详细信息,请参阅AVR用户手册)-您需要在CTC模式下使用定时器/计数器

基于ARM的Arduninos和几乎任何其他微控制器都将拥有类似的硬件设施;有些具有更大的灵活性,可以在哪些引脚上用于硬件计数

在AVR上有8位和16位计数器,如果需要更大的计数,可能必须处理溢出中断。如果您将定期轮询计数器,您甚至可以在不中断的情况下处理该计数器,而只需在下一次溢出之前轮询溢出标志,即可以比输入脉冲速率低得多且可能是非周期的速率进行轮询

在您的情况下,您可能需要以比计数器以最大预期脉冲速率溢出的时间更短的规则周期读取脉冲计数。例如,如果您使用的是8位计数器,最大脉冲率为1KHz,则需要每256/1000秒或更短的时间轮询一次,但通过使周期尽可能长可以获得最大的精度。例如,您可能有如下内容(这不是真正的代码,只是一个片段):

获得更好的线性响应但非确定性读出的另一种方法是轮询溢出标志,并测量计数固定数量脉冲所需的时间,因此从固定计数的时间而不是固定时间的计数来确定测量值

for(;;)
{
    int start = getMillisec() ;

    while( !counterOVF() )
    {
        // Do nothing (or something useful but quick)
    }

    int t = getMillisec() - start ;
    frequency = 256 * t / 1000 ; 
}

你可以使用模拟,前面有一点数字。
如果您的输入最大频率为1kHz,则使用此信号触发单稳态(边缘触发),脉冲输出为1ms(1/fmax)。然后低通滤波(R串联,C接地,多极重复),最后读取最后一个电容器上的模拟电压。如果R*C相对较小,模拟信号将反应迅速,但会产生涟漪。如果它很大,反应时间会受到影响,但信号会更稳定。

是的,您可以通过轮询来实现这一点,但是这会让处理器忙,并且您应该注意,任何持续时间可能少于轮询间隔的状态都可能会丢失。在没有ISR的情况下,计数脉冲的方法是使用硬件计数器,通过定期处理它们的状态并设置它们的计数限制来避免溢出。非常感谢您的提问。如果我理解正确的话,你的第一个想法是通过硬件测量脉冲,第二个想法让处理器一直忙着。问题是,我的微控制器已完全加载(这就是为什么简单的ISR递增计数变量无法工作的原因),并且无法轮询,因为它需要执行其他任务。此外,我没有更多的硬件计数器可用。还有其他选择吗?我听说可以使用模拟端口(依赖于与PWM的相似性)。非常感谢在这两种情况下,硬件计数器都在进行计数,在第二种情况下,我的示例轮询溢出标志,但这只是为了演示原理,不是根本解决方案;它同样可以是一个中断处理程序-优点是每256个脉冲(假设8位计数器)而不是每一个脉冲得到一个中断,因此中断开销要低得多。只有当传感器输出为固定频率PWM时,才可以使用模拟输入(并且您添加了适当的模拟滤波,截止频率略低于该频率),但您的问题暗示它是一个可变频率,而不是PWM(否则,计数脉冲会有什么帮助?)。
for(;;)
{
    int start = getMillisec() ;

    while( !counterOVF() )
    {
        // Do nothing (or something useful but quick)
    }

    int t = getMillisec() - start ;
    frequency = 256 * t / 1000 ; 
}