首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >软件PLL在arduino从GPS产生锁定为1pps的3.2 Khz采样频率

软件PLL在arduino从GPS产生锁定为1pps的3.2 Khz采样频率
EN

Stack Overflow用户
提问于 2019-06-06 18:09:28
回答 1查看 466关注 0票数 0

我想用Arduino设计一个锁相环。为我的数据采集模块生成1 PPS锁定的3.2 Khz采样频率(来自GPS),

不使用PLL产生的采样时钟会随时间漂移。这会导致错误的样本采集。如果使用PLL产生采样时钟,并锁定参考频率(1 PPS) ::不同位置的数据采集模块将能够在同一时刻采集样本。

EN

回答 1

Stack Overflow用户

发布于 2019-06-06 23:40:33

从字面上看,你可以做一个锁相环。

您需要两个中断:

  1. First将在1 PPS输入的脉冲前沿触发。
  2. second将以每秒3200次的速度被调用,每次定时器回绕时都会调用。

首先,将定时器周期长度设置为5000个CPU周期。

定时器中断非常简单,只需增加一些计数器变量,当它达到3200时,将其重置为零。

一秒脉冲中断的作用如下:

  • 如果计数器变量值为零-这意味着定时器以准确的频率工作-如果计数器变量值大于0但小于1600 (即定时器工作速度比所需的快),则不执行任何
  • 操作-如果计数器变量值为1600或更大(每秒一次中断发生的速度比计数器达到3200快),则将定时器周期增加1
  • 。将定时器周期减少1

对于第一次启动,将计数器变量设置为0,计时器值设置为2500 (周期的一半),计时器周期设置为5000,并等待第一个脉冲出现,然后启动计时器。

代码示例可能如下所示(假设使用Arduino UNO,1个PPS连接到INT0输入,由上升沿触发):

代码语言:javascript
运行
复制
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引脚上产生输出信号,你可以这样初始化定时器:

代码语言:javascript
运行
复制
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中断中启动计时器,如下所示:

代码语言:javascript
运行
复制
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10); // Start in FastPWM - CTC mode, 1:1 prescaler

输出应显示在PB2/OC1B引脚= Arduino UNO引脚10处

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56475382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档