4
\ \ begingroup \美元

在Arduino Uno(=ATMEGA328 / P.),如何手动清除计时器1输出比较信号?

代码的目的是在从输入脉冲中精确间隔后生成一些输出脉冲。有两个输出通道需要驱动,可能具有不同的延迟。脉冲长度并不重要,只需要至少8μs长,但上升沿的时序需要准确。

目前我的代码是这样的:

#define mains_period 16667 //在microSeconds ISR(Timer1_capt_vect){gtccr = _bv(tsm);TCNT1 = TCNT1  -  ICR1  -  MAINS_PERIOD + 1 + 300;gtccr = 0;} ISR(timer1_compa_vect){delaymicroseconds(8);OC1A = 0;// <----------我在这里做什么?} ISR(timer1_compb_vect){delaymicroseconds(8);OC1B = 0;// <----------我在这里做什么?void setup(){tccr1a = _bv(com1a0)| _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1); // set output on compare match, normal mode, prescaler /8 TCCR1B = _BV(CS11) | _BV(ICNC1) | _BV(ICES1); // input capture noise cancel, positive edge TIMSK1 = _BV(ICIE1) | _BV(OCIEA1), | _BV(OCIEB1); // generate interrupts for input capture, A/B compare match pinMode(8, INPUT); //set data direction pinMode(9, OUTPUT); pinMode(10, OUTPUT); }

我可能会重新配置定时器的输出模式以清除匹配,然后强制匹配,但似乎应该是更直接的方式来做才能做到这一点:

ISR (TIMER1_COMPA_vect) {delayMicroseconds (8);TCCR1A & = ~ _BV (COM1A0);TCCR1C = _BV (FOC1A);TCCR1A | = _BV (COM1A0);}

只是清除输出引脚寄存器位(PORTB & = ~ _BV (PORTB1);)在这种情况下不起作用,因为只要在PIN上启用了备用功能(如定时器输出)时,端口寄存器都被忽略。

或者,如果有一种方法可以让定时器输出清除溢出(某种未记录的16位PWM模式?)甚至更好,但我怀疑有办法做到这一点。

\ $ \ endgroup \ $
1
  • \ \ begingroup \美元 我不太清楚你到底想要达到什么目的。你想要外置触发器后的单次脉冲吗?或者是外部触发后的一连串脉冲?还是别的什么?你要多久洗一次脉搏? \ $ \ endgroup \ $- - - - - -Dibosco. 18年1月19日8:53
2
\ \ begingroup \美元

可以配置定时器来切换OC1A

tcr1a |= (1 << com1a0);

在中断例程中,使用控制寄存器触发额外的比较事件。这没有像改变定时器值一样的副作用。

tccr1c | =(1 << FOC1A);

要立即更改,请将类型设置为清除或设置模式并触发更改

tccr1a =(1 << com1a0);tccr1c | =(1 << FOC1A);

看到https://www.sparkfun.com/datasheets/Components/SMD/ATMega328.pdf第137页

\ $ \ endgroup \ $
    0
    \ \ begingroup \美元
    ISR (TIMER1_COMPA_vect) {delayMicroseconds (8);OC1A = 0;// <----------我在这里做什么?}

    在isr中有延迟对编码不是很好。

    做它的多种方式。这是一个:

    1)设置时间库,尚未启动计时器;

    2)设置比较为所需的输出,中断启用。oc1a / b针根据您的需求设置/清除;

    3)设置中断,观察输入脉冲。

    4)在输入脉冲isr时,启动定时器;

    5)在输出比较isr中,清除/设置OC1A/B引脚,禁用输出比较中断和复位/禁用定时器。

    编辑:应该注意的是,上述方法假设ISR开销的琐碎量。对于短持续时间或慢处理器,可能不是这种情况。

    \ $ \ endgroup \ $
    1
    • 1
      \ \ begingroup \美元 我的问题是如何一个清除OC1A / B。我知道使用中断的延迟是一个坏主意,我稍后会改变,但我需要一些方法来实际清除输出位。 \ $ \ endgroup \ $- - - - - -ajmansfield. 17年2月20日20:01

    你的答案

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

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