用于数字读取和计数脉冲的Arduino uno中的CPU周期

用于数字读取和计数脉冲的Arduino uno中的CPU周期,arduino,arduino-uno,pulse,cpu-cycles,Arduino,Arduino Uno,Pulse,Cpu Cycles,我试图在200ms时间量子中计算脉冲数 代码如下: #包括 #包括 elapsedMillis Elapsedmime; #定义传感器A0 #定义时间量子200 int计数器=0; 布尔状态; 无效设置() { 序列号:开始(250000); pinMode(传感器,输入); } void循环() { 计数器=0; ElapsedTime=0; while(ElapsedTime

我试图在
200ms
时间量子中计算脉冲数

代码如下:

#包括
#包括
elapsedMillis Elapsedmime;
#定义传感器A0
#定义时间量子200
int计数器=0;
布尔状态;
无效设置()
{
序列号:开始(250000);
pinMode(传感器,输入);
}
void循环()
{
计数器=0;
ElapsedTime=0;
while(ElapsedTime
我需要知道数字读取周期。 我正在比较传感器的最后一个状态和当前状态,如果进行了更改(从低到高),计数器将递增。但是,我的计数器总是
0

  • 代码是否正确(条件为<代码>如果时)
  • 我需要延期吗
  • 能数一数这些脉冲吗
以下是微波传感器的逻辑分析仪输出:



编辑:如果我添加
延迟(1)
,则计数器不再是0。

由于这些脉冲似乎短于微秒,您就不能使用大约需要80个机器周期(约5us
@16MHz
)的
数字读取功能

更不用说在每个循环迭代中打印这么多数据了

因此,您的频率超过
1MHz
,并且您的代码可能能够计算大约
10kHz
(最多,可能更少)

无论如何,您应该使用HW
定时器/计数器1
,时钟源位于
T1
输入端。这一个能够以主时钟频率的一半(50%脉冲宽度)计数脉冲

使用
计时器/计数器1
非常简单:

TCCR1A = 0; // default mode, no output compare modes
TCCR1B = _BV(CS10) | _BV(CS11) | _BV(CS12); // clock select mode 7 - External clock source on T1 pin. Clock on rising edge.

每200毫秒读取一次TCNT1,然后最终重置为0,或者只记住最后一个值并做出改变(不要忘记它只是16b的数字)。

KIIV很好地解释了代码不起作用的原因,在这里我想建议一种实现相同目标的替代方法


代码:

const byte interruptPin=2;
易失性无符号长计数器=0;//2^32-1脉冲后溢出
无效设置(){
引脚模式(中断引脚、输入\ U上拉);
连接中断(数字插针到中断(中断插针)、计数、上升);
连载《开始》(19200);
}
void循环(){
序列号。打印(“脉冲号:”);
串行打印LN(计数器);
延迟(1000);
}
无效计数(){
计数器+++;//切勿在ISR中使用print()!
}
请注意,我更改了输入引脚,因为引脚上有一些可以与此技术一起使用,这取决于您使用的电路板:

可用于中断的电路板数字引脚
Uno,Nano,Mini,其他2,3
Mega,Mega2560,MegaADK 2,3,18,19,20,21
Micro,Leonardo,其他基于32u4的0,1,2,3,7
除4外,将所有数字管脚归零
MKR1000版本10,1,4,5,6,7,8,9,A1,A2
截止日期,101个全数字管脚

您可以使用timer1计算经过的时间

// Set Timer1 without prescaler at CPU frequency
TCCR1A = 0; // TCCRx - Timer/Counter Control Register. The pre-scaler can be configured here. 
TCCR1B = 1;

noInterrupts ();  // Disable interrupts.

uint16_t  StartTime = TCNT1;  // TCNTx - Timer/Counter Register. The actual timer value is stored here.
digitalRead(pin); // your code.
uint16_t EndTime = TCNT1
uint16_t ElapsedTime = EndTime - StartTime;

interrupts (); //Enable interrupts.
作为第二种解决方案,您可以设置和取消设置pin,并使用逻辑分析仪计算时间

DDRD = DDRD | B10000000; // Set digital pin 7 as output.
PORTD = PORTD | B10000000; // Set digital pin 7.
digitalRead(pin); // your code.
PORTD = PORTD & B01111111; // Unset digital pin 7.

感谢您的回答,我在哪里可以找到任何操作的CPU周期文档?现在打印的内容已经超出了while循环。几乎没有,我使用的是我自己的“基准”。但是可以切换一些输出并测量频率。也许在某个地方有一些关于这个主题的文章。谢谢。我将阅读提到的文档并测试代码。我需要在200ms内连续计数脉冲,因此我认为延迟(1000)不合适。延迟超过打印功能,使用中断服务例程
count()
连续计数脉冲。您可以减少延迟,但只能在一定程度上减少延迟。现代Arduino实现使用中断来处理
print()
,这意味着如果滥用此指令,可能会错过一些脉冲或出现其他奇怪的行为。鉴于您的脉冲频率很高,您当然不希望在每次脉冲后都使用
print()
。也许每100/1000个脉冲是一个更好的主意。您的代码正在运行。我以前没有用过ISRs,我应该多读一些,谢谢你的建议。