0
\ \ begingroup \美元

我试图使用ATmega 328/p(arduino uno)上的一个硬件定时器,在接收到输入脉冲后几微秒产生一个短脉冲。

目前我的代码是这样的:

uint16脉冲延迟=12000//半微秒uint16脉冲长度=20;void setup(){pinMode(8,输入);pinMode(9,输出);TCCR1A=0;TCCR1B=_BV(ICNC1)//输入捕获噪声取消|u BV(ICES1)//正边缘| u BV(CS11)///8预分频器TIMSK1=_BV(ICIE1)//启用输入捕获中断}void循环(){}ISR(TIMER1_CAPT)ISR{TCCR1A=_BV(COM1A0)| COM1A1)//设置匹配;//启用匹配中断OCR1A=pulse\u delay;//脉冲开始时间TCNT1=TCNT1-ICR1;//TCNT1现在包含自输入脉冲开始的时间,即使//中断没有立即运行}ISR(TIMER1\u COMPA vect){TIMSK1&=~\u BV(OCIE1A);//禁用匹配中断TCCR1A=\u BV(COM1A1);//清除匹配OC1A上的OC1A=pulse\u delay+pulse长度;}

这段代码理论上应该完成任务,但它根本不产生任何输出-对我的示波器,它看起来像输出引脚只是保持低。

但是,如果我替换最后一行(cr1a = pulse_delay + pulse_length;)的比较匹配中断与以下两行,它输出一个脉冲刚刚好。这个问题是,它使用了更多的CPU时间,它只能从中断开始时计算时间,所以如果中断执行晚,脉冲将更长。

delayMicroseconds (pulse_length);TCCR1C = _BV (FOC1A);//手动触发匹配事件

第一个版本所做的不同之处在于通过定时器上设置的“报警”触发匹配事件,而不是等待手动触发匹配。

为什么第一个版本不能工作,我如何使它工作?

\ \ endgroup \美元
2
  • \ \ begingroup \美元 你忘记在SREG中设置7位了吗?这是全局中断启用位。 \ \ endgroup \美元- - - - - -埃维迪亚 2017年3月1日23:45
  • \ \ begingroup \美元 @Envidia,我已经有了答案:arduino.stackexchange.com/a/35014/401,但事实证明,我忘记了在重新启用中断之前清除FOC1x,因为即使相应的中断被禁用,中断标志也会设置为比较匹配。 \ \ endgroup \美元- - - - - -阿杰曼斯菲尔德 3月17日21:46
0
\ \ begingroup \美元

我没有仔细阅读代码,但它不应该这么复杂。假设所需的持续时间相对于Isr开销来说是合理的,那么您所需要的只是使用信号来触发Isr(计时器不能设置为外部中断),并在该Isr中触发一系列延迟引脚动作。

如果期望的持续时间很短,情况就会变得棘手。

\ \ endgroup \美元
4
  • \ \ begingroup \美元 需要这个复杂的代码,因为脉冲长度需要很短(仅10µ年代),非常精确(额外的等待时间不间断代码完成是不可接受的),我想很多其他代码运行在arduino同时——这不是唯一这arduino会做的,我需要每一个我能得到的周期来完成它的其他任务。 \ \ endgroup \美元- - - - - -阿杰曼斯菲尔德 17年2月23日16:40
  • \ \ begingroup \美元 如果是这种情况,请考虑使用pwm模块生成单个脉冲的方法。您可以提前设置模块周期和占空比,但也可以禁用模块周期和占空比。 \ \ endgroup \美元- - - - - -丹尼夫 2017年2月23日16:57
  • \ \ begingroup \美元 我在这里写一个库,我打算在大量的项目中使用,并希望它(a)工作完美的,(b)尽可能快,以及(c)尽可能少地与其他代码冲突。使用一个额外的库来实现这三个目标中的任何一个都是不利的。 \ \ endgroup \美元- - - - - -阿杰曼斯菲尔德 2017年2月23日17:23
  • \ \ begingroup \美元 无论如何,我已经得到了一个真正的答案:arduino.stackexchange.com/a/35014/401.结果我忘记在重新启用比较匹配中断之前清除中断标志。 \ \ endgroup \美元- - - - - -阿杰曼斯菲尔德 2017年2月23日17:24

你的答案

点击“发布你的答案”,即表示你同意我们的服务条款隐私政策饼干的政策

不是你想要的答案?浏览其他带标签的问题问你自己的问题