【问题标题】:lpc17xx frequency detection of square wave using pollinglpc17xx使用轮询的方波频率检测
【发布时间】:2015-06-17 05:13:58
【问题描述】:

我必须通过轮询 5 个不同的引脚来读取高达 20KHz 的 5 个不同频率(方波)。 我只使用一个定时器中断,每 1 毫秒。 引脚的轮询将在 ISR 中完成。

目前我想到的算法是: 1.计数HIGH 2.计数LOW数 3.检查HIGH+LOW之和是否=时间段。 这个算法看起来很慢,不实用。

是否有任何过滤器函数可以用来检查引脚上的频率,这样我所要做的就是调用该函数? 任何其他算法,用于频率检测都会很好。

我的代码中仅限于 1 个中断(定时器中断)

【问题讨论】:

  • 仅供参考:如果有帮助,我会使用 KEIL uvision
  • 在任何情况下,轮询都是一种可怕的方式。设备应至少有 1 个带输入捕获的计时器,这几乎非常适合此功能。
  • 1.您正在测量什么样的信号(频率范围,噪声)? 2. 你有哪些 CPU 和 IO 能力? 3.为什么只有1KHz的定时器?如果您的信号低于 100Hz,那没关系,但如果您的芯片可以处理,为什么不使用 50KHz 或更高的频率进行更精确的测量

标签: algorithm microcontroller cortex-m3 lpc nxp-microcontroller


【解决方案1】:

您需要记住输入信号的属性是什么

  • 因为您仅限于单个中断(这很奇怪)
  • 而定时器只有 1 KHz
  • 输入信号不得高于 0.5 KHz
  • 如果信号中有噪声,频率很容易超过该限制多次

速度

  • 您写道,简单的计数周期方法很慢
  • 你有什么 CPU 和 IO 能力?
  • 我习惯了 Atmel AVR32 AT32UC3 芯片,比 ARM 皮质芯片早 2 代
  • 我有大约 96MIPS 和 2-5 MHz 引脚 R/W 频率,没有 DMA 或中断
  • 那么这种方法到底有什么慢?

我会像这样使用您的约束对其进行编码(它只是不使用您的平台的 C++ 伪代码):

const int n=5;
volatile int T[n],t[n],s[n],r[n]; // T last measured period,t counter,s what edge is waitng for?
int T0[n]={?,?,?,...?}; // periods to compare with

void main() // main process
 {
 int i;
 for (i=0;i<n;i++) { T[i]=0; t[i]=0; s[i]=0; r[i]=0; }
 // config pins
 // config and start timer
 for (;;) // inf loop
  {
  for (i=0;i<n;i++)            // test all pins
   if (r[i]>=2)                 // ignore not fully measured pins
    {
    r[i]=2;
    if (abs(T[i]-T[0])>1)     // compare +/- 1T of timer can use even bigger number then 1
     // frequency of pin(i) is not as it should be
    }
  }
 }

void ISR_timer() // timer interrupt
 {
 // test_out_pin=H
 int i;
 bool p;
 for (i=0;i<n;i++)
  {
  p=get_pin_state(i);                                // just read pin as true/false H/L
  t[i]++;                                             // inc period counter
  if (s[i]==0){ if ( p) s[i]=1; }                   // edge L->H
  else         { if (!p) s[i]=0; T[i]=t[i]; t=0; r[i]++; } // edge H->L
  } 
 // test_out_pin=L
 }
  • 您还可以扫描最后一个引脚状态和实际状态之间的比较
  • 这将消除s[] 的需要
  • 类似p0=p1; p1=get_pin_state(i); if ((p1)&amp;&amp;(p0!=p1)) { T[i]=t[i]; t[i]=0; }
  • 这样您还可以更轻松地实现 SW 故障过滤器
  • 但我认为他的 MCU 也应该有硬件过滤器(就像大多数 MCU 一样)

如果没有你奇怪的限制,我该怎么做?

  • 我会使用外部中断
  • 通常可以将它们配置为在信号的特定边沿触发
  • 还包括噪声的硬件过滤
  • 在每次中断时获取内部 CPU 时钟计数器值
  • 如果不可用,则为定时器/计数器状态
  • 用最后一个测量值减去
  • 发生溢出时从溢出中恢复
  • 如果需要,请更改为 sHz
  • 通过这种方式,我可以使用 30MHz 时钟可靠地扫描 MCU 上的引脚,频率高达 15MHz(将其用于 IRC 解码器)
  • 是的,IRC 有时可以为您提供高于 1 MHz 的频率(在状态之间的边缘)
  • 如果你也想要这个比例,你可以:
  • 有 2 个中断,一个用于上升沿,第二个用于下降沿
  • 或者只使用一个并在每次命中后重新配置边缘(我前段时间使用的 Atmel UC3L 芯片由于内部错误而与这个有问题)

[注释]

  • 您访问的引脚必须位于同一个 IO 端口
  • 这样您就可以一次读取所有内容,然后只需在之后解码引脚即可
  • GPIO 模块通常也是可配置的,因此请检查它使用什么时钟供电
  • 通常有 2 个时钟用于 GPIO 模块与 CPU 内核的接口
  • 第二个用于 GPIO 本身,因此请检查两者
  • 您也可以使用 DMA 代替外部中断
  • 如果您可以配置为通过 DMA 将 IO 端口读取到某处的内存中
  • 然后您可以检查独立于 IO 的后台进程

【讨论】:

  • @Akshay 1. 输入信号的比率与您不单独计算整个周期而不是低和高部分无关。 2.是的,第一次测量无效,您可以使用附加标志来处理或忽略取决于使用情况。之后,除非存在噪音,否则测量会关闭 +/-1T。当您有高达 20KHz 的信号时,那么您至少需要 40KHz 的定时器频率,而且我会更愿意使用至少 50-100KHz 的频率来确定。无论如何,中断处理程序只是几条指令,所以如果你不在 32KHz CPU 时钟上运行,你应该没问题,唯一的问题可能是与 GPIO 接口
  • @Akshay 因为我不熟悉你的芯片,所以那里可能会减速(连接 GPIO 或读取引脚/端口本身)你需要测量结果只需轮询中断中的一些输出引脚,然后通过示波器对其进行测量,以查看 ISR 运行的频率、同步、长时间。这应该清楚地表明这是否足够稳定/足够快......您可以通过它调整频率
  • @Akshay 更新了添加附加标志的代码,因此测试仅适用于完全测量的信号。顺便说一句,边缘中断方法也只需要单个中断....并且它需要的 CPU 和 IO 功率比轮询方法要少得多
  • @Spektre- 我将 ISR 用于多种其他功能,例如估计经过的时间等。频率读数将是 ISR 中的附加功能。我的 CPU 以 120Mhz 运行。 GPIO 引脚以最大 50Mhz 读取
  • @Akshay 然后只需对其进行编码并尝试它是否足够快,但不要忘记增加定时器频率(1KHz 对您的任务不可用)如果 ISR 的其余部分需要 1KHz,那么您可以轻松将频率设置为 Nx1KHz 并仅在每个第 N 个 ISR 调用中处理其余部分(为此需要一个 counter、一个 ++ 和一个 if
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 2011-04-20
  • 2020-07-16
  • 2021-04-01
  • 1970-01-01
  • 2016-11-26
  • 1970-01-01
相关资源
最近更新 更多