我想使用Arduino设计一个锁相环。为我的数据采集模块生成以1 PPS锁定的3.2 Khz采样频率(来自GPS),
不使用PLL生成的采样时钟随时间漂移。导致错误的样品采集。如果使用锁定了参考频率(1 PPS)的PLL生成采样时钟,则::位于不同位置的数据采集模块将能够在同一时刻采集样品。
答案 0 :(得分:0)
从字面上看,您可以进行锁相环。
您需要两个中断:
首先,将计时器周期长度设置为5000个CPU周期。
计时器中断非常简单,只需增加一些计数器变量,当它达到3200时,将其重置为零即可。
一秒脉冲中断的作用如下:
对于第一次启动,将计数器变量设置为0,将计时器值设置为2500(周期的一半),将计时器周期设置为5000,然后等待直到出现第一个脉冲,然后启动计时器。
代码示例可能是这样的(假设使用Arduino UNO,并且将1个PPS连接到INT0输入,由上升沿触发):
volatile uint16_t counter = 0; // counter variable
ISR(TIMER1_COMPA_vect) { // Timer interrupt
if (++counter >= 3200) counter = 0;
}
// edited: INT0_vect
ISR(INT0_vect) { // External Interrupt Request 0
if ((TCCR1B & ((1 << CS12) | (1 << CS11) | (1 << CS10))) == 0) {
// if timer is not running (the first pulse)
TCCR1B = (1 << WGM12) | (1 << CS10); // Start in CTC mode, 1:1 prescaler
} else { // Once-per-second pulse
uint16_t cnt = counter;
if (cnt >= 1600) {
uint16_t ocr_val = OCR1A - 1; // edited: uint16_t
OCR1A = ocr_val;
if (TCNT1 >= ocr_val) { // for the case, when OCR1A was changed below the current value of TCNT1
TCNT1 = 0;
}
} else if (cnt > 0) {
OCR1A++;
}
}
}
// initialization code
TCCR1A = 0; // for now timer is disabled
TCCR1B = 0;
OCR1A = 4999; // 5000 timer period
TCNT1 = 2500; // starts from the middle of the first period
TIMSK1 = (1 << OCIE1A); // allow the output compare 1 interrupt
EICRA = (1 << ISC01) | (1 << ISC00); // The rising edge of INT0 generates an interrupt request
EIMSK = (1 << INT0); // Allow int0 interruput
sei(); // Enable interrupts.
如果要在OC1B引脚上生成输出信号,则可以这样初始化计时器:
TCCR1A = (1 << COM1B1) | (1 << WGM11) | (1 << WGM10); // edited: COM1B1
OCR1B = 2499; // PWM with pulse length half of the period
DDRB |= (1 << DDB2); // edited: port initialization
并在INT0中断中像这样启动计时器:
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10); // Start in FastPWM - CTC mode, 1:1 prescaler
输出应该出现在PB2 / OC1B引脚= Arduino UNO引脚10