我正在尝试将Arduino Uno用作较大的电路的一部分,该电路可以同步两个平方电压波形(这些波形被馈送到Uno的引脚中)。 Uno将由较大电路另一部分的数字信号激活,并且该激活信号将一次持续几秒钟。当激活信号为HIGH时,Uno的工作就是检测其测量的方波何时同步:它将监视它们并在彼此相隔约100微秒内达到零交叉点时产生自己的脉冲(即波本身就是〜50Hz。
因为100us是一个很短的窗口,所以我认为我将尝试直接位操作,而不是使用DigitalRead()或DigitalWrite()。但是,这是我第一次尝试位操作,而且我的C经验通常很有限。我在这里有了代码的初稿-如果你们中的任何人都能告诉我它的逻辑是否合理,我将不胜感激!
它看起来很长,但是只有几行内容有价值,其余是一堆复制/粘贴的块(毫无疑问,这意味着还有很多更优雅的编写方法)。
// Synchronism detector
// This code is built to run on an Arduino Uno.
// The hardware timer runs at 16MHz. Using a
// divide by 8 on the counter each count is
// 500 ns and a 50Hz wave cycle is 40000 clock cycles.
#include <avr/io.h>
#include <avr/interrupt.h>
void setup(){
// Set clock prescaler
// This is set to 'divide by 8' but if I can get away
// with using delay statements that doesn't really matter
TCCR1B &= ~(1 << CS12);
TCCR1B != ~(1 << CS11);
TCCR1B &= ~(1 << CS10);
// Set up pins
// 3rd bit of port D will be the activation flag
// 4th and 5th bits will be read pins for the incoming waves
DDRD = DDRD & B11100011
// Note that I'll also have the incoming waves going into the int0 and int1 pins
// 6th bit will be a write pin for the outgoing signal
DDRD = DDRD | B00100000
PORTD = PORTD & B11011111
// Set initial values for zero-cross detect flags
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
}
void loop(){
// Poll activation flag
if (((PIND & B00000100) >> 2) == 1)
// Poll wave input pins
wave_0 = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
// Check zero crossing detection,
// Start with wave 0, rising edge
if (wave_0 == 1 && wave_0_prev == 0))
attachInterrupt(int1,sync_interrupt, RISING);
delay(.0001);
detachInterrupt(int1);
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
)
// Wave 0, falling edge
if (wave_0 == 0 && wave_0_prev == 1))
attachInterrupt(int1,sync_interrupt, FALLING);
delay(.0001);
detachInterrupt(int1);
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
)
// Wave 1, rising edge
if (wave_1 == 1 && wave_1_prev == 0))
attachInterrupt(int0,sync_interrupt, RISING);
delay(.0001);
detachInterrupt(int0);
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
)
// Wave 1, falling edge
if (wave_1 == 0 && wave_1_prev == 1))
attachInterrupt(int0,sync_interrupt, FALLING);
delay(.0001);
detachInterrupt(int0);
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
)
}
sync_interrupt(){
// Set output bit high
PORTD = PORTD | B00100000
delay(.001}
// Set output bit low
PORTD = PORTD & B00100000
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
}
再次感谢您的帮助。
答案 0 :(得分:1)
好,所以我不太确定此特定设备的中断标志到底是什么,但是我个人认为,最简单的方法是将其设置为为每个中断设置2个中断输入并设置每个中断代码块,以通过从输出引脚跳转来激活定时器中断。这样,如果一个在某个时间段内未激活而另一个被激活,则可以重置中断标志;如果第二个被激活,则可以在同步波形时运行希望运行的代码