×

Pro Micro的频率发生器和频率计数器

消耗积分:0 | 格式:zip | 大小:0.17 MB | 2022-11-11

张莉

分享资料个

描述

概述

很多时候,需要产生可编程频率输出或实现用于各种用途的频率计数器。该项目仅使用低成本(≈5-17 美元)Pro Micro(Sparkfun DEV-12640 或等效克隆)模块实现这些功能块中的一个或两个,该模块带有 ATMega32U4 处理器芯片和使用 Arduino IDE 编译器和环境实现的软件。这些功能块可以单独使用,也可以在更大的应用程序中一起使用,或者作为独立设备使用。由于它们是独立的功能,因此将分别进行介绍。作为该项目的一部分,还包括一个通用主模块,可用于设置频率发生器或从频率计数器读取频率。这可以通过串行端口完成,或者,

与本网站上列出的许多项目不同,该项目没有实现一些最终设备,而是专注于频率发生器和频率计数器的功能块。假设用户随后将编写一个主模块,将这些模块部署到所需的任何目的,并且可能包括 LCD 显示器、键盘或其他外部接口,或者可能是用户需要的某个更大项目的一部分。最后,由于频率发生器和频率计数器都依赖于Pro Micro通常未经校准的内部晶振,因此详细说明如何修改模块以提高振荡器的精度。

应该注意的是,也可以使用其他带有 ATMega32U4 处理器的 Arduino 模块,包括 Arduino Leonardo 和 Arduino Micro 以及可能的其他模块。

频率发生器

该库使用 Arduino Pro Micro 模块(使用 ATMega32U4)上的 Timer 4 实现可变频率发生器。该信号可用于向任何用户定义的设备或电路输出可调节频率的方波信号。使用 Pro Micro 模块本身包含的硬件,频率发生器将输出具有 50% 占空比的方波信号,从 1 Hz 到大约 12MHz。它可以在使用模块的所有其他功能的同时使用。此处理器/模块上的定时器 4 的独特之处在于它可以连接到处理器主时钟,也可以连接到 ATMega32U4 中包含的 PLL,提供更高的初始频率和一些额外的缩放值,包括 1.5x 时钟,提供更多的计数组合值以产生更接近任何所需频率的输出信号。

用于设置频率的固件包含一种独特的算法,可通过从三个不同的输入时钟频率之一(通过片上 PLL)、二进制预分频器值和一个计数值。对于所有这些变量,如果必须从外部确定这些变量,则每个变量要获得给定频率的设置可能具有挑战性。通过固件中包含的算法,固件本身为这三个值中的每一个确定最佳值,以使输出频率尽可能接近请求值。一旦计算和设置了这些值,

发电机硬件

Pro Micro 模块将在 Arduino Digital 引脚 5(处理器引脚 PC6)上输出选定的频率时钟信号,作为 0-5V 50% 占空比的方波信号,无需对控制器进行进一步修改。或者,如果需要,也可以将输出配置为在 Arduino 数字引脚 10(处理器引脚 PB6)上输出信号。下图显示了 Pro Micro 模块上频率发生器输出的引脚。

pYYBAGNtm72AGBMGAAFom2-hcEg111.jpg
 

根据您的应用,可能不需要额外的电路,但如果需要与模块输出引脚不同的电平或更大的功率,则可能需要外部放大器、电平转换器或电阻分压器。还显示了一个 5V 电源,如果需要,它可用于为该外部电路供电,其功率要求小于 100mA。

该发生器的频率精度与 Pro Micro 模块上的晶振直接相关,通常在 0.1-0.2% 之间,但通常比这更接近标称频率。如果需要更高的精度,请参阅下面的部分,详细说明对 Pro Micros 晶体振荡器的修改。频率精度还与处理器芯片的各个寄存器中设置的值有关。虽然该算法试图确定 PLL、预分频器和计数器的最佳值,但有些频率是硬件无法获得的,无需额外的软件干预,这超出了本项目的范围。几乎所有较低的频率(低于约 5KHz)都是完美的(或接近完美的),这意味着模块可以输出准确的频率,但随着要求的频率越来越高,将存在无法实现准确频率的“差距”。在这些情况下,将设置可获得的最接近的频率,并且通常对于大多数应用来说足够接近。输出的占空比固定为 50%。

发生器软件接口功能

该库在一个名为“FrequencyGenerator”的类中实现。这个类有两个函数:“set”和“read”来设置频率发生器和读取发生器设置的当前频率。

** 设置功能 **

使用频率设置命令设置频率,该命令将频率设置为最接近的可获得值。函数 'FrequencyGenerator::set' 接受一个长整数,它是以赫兹为单位输出的频率。这可以从小于 0(返回电流频率)的值到 0(发电机关闭)到超过微时钟频率(8MHz)的 1/2 的值。在现有的 Pro Micro 模块可用的情况下,据观察它的工作频率约为 12MHz。如果设置了请求的频率,则“FrequencyGenerator::set”函数返回设置的频率,如果无法设置为所需的频率,则返回 -1。由于定时器设置为自动重新加载,因此不需要中断或其他软件开销——只需调用该函数,然后硬件将产生输出频率,无需额外干预。

要关闭频率发生器,只需调用频率为零的“FrequencyGenerator::set”函数。这将禁用频率发生器并将其输出引脚置于高阻抗状态。也可以通过使用 -1(或任何负数)调用“FrequencyGenerator::set”函数来请求当前频率。

** 读取功能 **

还提供了一个函数“FrequencyGenerator::read”来请求频率发生器模块的当前频率。返回的值将是控制器输出的实际频率(以及硬件能够输出的最接近的值),并且可能与上次设置的频率略有不同。这以长整数形式返回。

生成器代码详细信息和选项

频率发生器功能包含在文件“FrequencyGenerator.cpp”中。包含类原型的头文件位于文件“FrequencyGenerator.h”中。该模块是专门为 Pro Micro 设备(或具有类似功能块的其他微控制器设备)上的 ATMega32U4 的定时器 4 编写的,假设控制器作为 USB 设备运行,PLL 设置为 96MHz,晶振为 16MHz(这是Pro Micro 设备的默认设置)。它可能会为其他计时器重新设计,但分辨率会更低。

“FrequencyGenerator.cpp”模块中的代码包含将处理器中的各种寄存器设置为所需输入频率的最佳值的算法。它通过连续对每个 PLL 设置进行计算,然后确定哪个 PLL 设置提供最接近所需值的输出频率来实现。预分频器和计数值通过计算所需频率的 log2 来确定,然后将其转换为寄存器的预分频器和计数值。一旦确定了最佳组合,就将物理寄存器设置为这些值。代码中的注释更详细地详细说明了该算法。

在 FrequencyGenerator.cpp 模块中有 2 个条件编译定义,可以定义也可以不定义。其中之一是“FRQGENUSEPB6”,如果定义为非零,将使用 Arduino 数字引脚 10(处理器引脚 PB6)作为发生器的输出,而不是默认的 Arduino 数字引脚 5(处理器引脚 PC6)。另一个定义是“FRQGENDEBUG”,如果定义为非零,则在设置频率以进行调试时会将一些变量值输出到串行端口。

频率计数器

该库使用属于 Pro Micro 模块的硬件定时器/计数器资源来实现频率计数器。它使用定时器 0 和另一个定时器作为 Pro Micro 模块上的“门”定时器。它既可以用作传统频率计数器,通过在固定时间(门限时间)内对输入引脚上发生的脉冲数进行计数,也可以用作周期计数器,其中输入波形的单个或多个周期的时间被测量。传统的频率计数模式最适合测量较快的信号,而周期测量模式在测量较低频率的信号时提供更高的亚赫兹分辨率。该模块的接口是通过 2 到 3 个主要功能。第一个函数向用户提供读取频率,而第二个功能将频率计数器设置为传统计数模式或周期测量模式,还设置门时间或输入脉冲数以进行平均。如果需要,可以使用另一个功能来确定是否有新的“新”读数可用。由于该模块使用硬件定时器和中断例程来实现频率计数器,因此除了用户需要编写的任何代码之外,它还可以在使用 Pro Micro 模块和 Arduino 环境的所有其他功能的同时使用。

当计数器配置为传统计数模式时,定时器 0 配置为对输入脉冲进行计数,第二个定时器(定时器 1)用作门控源。计数时,每次 Timer 0 溢出时,中断例程都会将保存的计数变量加一。门控计时器 (Timer 1) 用于定期将此累积计数移动到另一个变量,然后在请求频率时将其返回给用户,然后重置 Timer 0 计数器中的计数(以及保存的计数变量)下一个周期。门控定时器可以配置为 10 毫秒、100 毫秒、1 秒、10 秒或 100 秒之一。门控定时器也是中断驱动的,因此计数器模块可以准确地计时门控窗口。

当计数器处于周期测量模式时,定时器 0 用于对输入引脚上的单次跳变或多次跳变进行计数。系统微秒计数(即 Arduino 环境的一部分)在收到第一个转换时保存,然后当第二个转换发生时,再次读取微秒值并从中减去保存的微秒值以确定周期的输入信号。然后当用户请求频率时,将该值转换为频率并返回给用户。在周期测量模式下,可以使用三种平均模式中的一种。可选择不平均或平均 10 或 100 个输入脉冲。这种平均是通过设置定时器 0 计数器在 1、10 或 100 次转换时产生中断来完成的,

计数器硬件

频率计数器的输入位于 Pro Micro (ATMega32U4) 的 Arduino 数字引脚 6(处理器引脚 PD7)上,并假定为要计数的低脉冲序列。下图显示了计数器输入以及外部门输入引脚(稍后详述)。外部门输入(如果使用)位于 Arduino 数字引脚 9(处理器引脚 PB5)上,但如果需要,可以移动到另一个引脚。

poYBAGNtm8GATlVVAAF48RKP2EI343.jpg
 

显然,输入信号必须是适当的 TTL 电平才能被计数。将较低电平信号放大到这个 TTL 电平(如果需要)的输入放大器超出了这项工作的范围。还展示了一个 5V 电源,如果需要,它可用于为任何外部电路供电,其功率要求小于 100mA。

此计数器的频率精度与 Pro Micro 模块上的晶振直接相关,通常在 0.1-0.2% 之间,但通常更接近实际频率。如果需要更高的精度,请参阅下面的部分,详细说明对 Pro Micros 晶体振荡器的修改。

精度还与传统频率计数器模式的门控定时器和周期测量模式的毫秒定时器的精度直接相关。在这个项目中,这两个定时器都是中断驱动的,这意味着它们在没有任何软件干预的情况下自主发生,并且在 Arduino 环境中尽可能接近立即发生。虽然中断程序有一些开销,但这通常可以忽略不计,并且读取的频率通常非常接近或通常完全正确的频率。

对该项目开发期间可用的不同模块进行的测试表明,在传统的频率计数器模式下,Pro Micro 模块能够可靠地计算高达约 8MHz 的频率(处理器时钟频率的 1/2)。在周期测量模式下,该模式旨在以更高的分辨率测量较低频率,当平均设置为 10 和 100 和 10 KHz 时(平均值为 1),最高 20 KHz 的频率是可能的且可靠的。在周期测量模式下,如果频率高于这些值,模块将报告值“999999”或在极少数情况下报告错误值。

如果应用需要测量高于约 8 MHz 的频率,则可以在将输入信号连接到此计数器模块之前将外部分频器链(预分频器)添加到输入信号中,然后相应地调整此模块返回的值。一个 74196 或一组 74F74 可用于高达约 60-100MHz 的频率,而其他预分频器 IC 可用于更高的频率。如果使用预分频器,则可以将“FrequencyCounter.cpp”模块中名为“FCPRESCALER”的定义调整为除数,以便使用预分频器时返回的输出频率是正确的。

计数器软件接口功能

该库在一个名为“FrequencyCounter. 这个类有两个主要功能和几个可能需要的辅助功​​能,具体取决于选择的具体实现。

** 模式功能 **

第一个函数“FrequencyCounter::mode”用于设置或读取计数模式,包括模式和门时间或平均次数。这使用单个参数调用,该参数指定要使用的模式,或请求当前模式。如果输入参数为 -1(或任何小于 0 的值),则函数返回当前模式值。如果输入参数在 0 到 9 的范围内,则设置以下模式:

pYYBAGNtm8mAZuQdAAH5LO8bQEk980.jpg
 

如果输入参数超出上述值的范围,该函数总是返回当前选择的模式或 -1。模式 6 到 9 可能存在也可能不存在,具体取决于模块的编译方式。如果在没有参数的情况下调用“FrequencyCounter::mode”函数,它将返回当前模式。

** 读取功能 **

第二个函数“FrequencyCounter::read”用于读取频率计数器并返回一个字符串,该字符串是读取频率的数字浮点值。调用此函数时,会使用一个指向将由该函数填充的字符串缓冲区的指针和一个名为“Wait”的参数,如果非零将导致该函数等待,直到频率计数器的新“新”读数为可用的。该函数返回一个指向包含此频率值的字符串的指针,其格式为“12345678”或“12345.67890”(或类似)。传递给此函数的字符串缓冲区位置必须足够大以容纳此函数将创建的字符串——建议使用 15 个或更多字符。参数 'Wait' 应该为零以获取最后读取的频率,或非零以等待新的“新”频率计数。需要注意的是,如果调用函数时将 'Wait' 参数作为非零值,则函数可能需要长达 100 秒才能返回,具体取决于频率计数器模块所处的模式。如果这是不可接受的,还可以使用轮询功能来查看是否有新的频率读数可用。此函数返回一个可以是浮点值的字符串,而不是实际的二进制浮点值类型,因此不需要编译器的浮点函数(占用大量代码空间)。

** 可用功能 **

如上一段所述,还包括确定是否有新的“新”频率读数可用的功能。函数 ''FrequencyCounter::available'' 不需要参数,如果新值准备好则返回 1,如果新值未准备好则返回 0。

大多数用户只需要上面提到的两个或三个功能。在特殊情况下,还可以使用其他一些功能。

** 读取二进制函数 **

当函数 ''FrequencyCounter::read'' 仅使用“Wait”参数(并且没有指向字符串参数的指针)调用时,读取函数返回一个长整数,它是读取频率的未更正计数或周期。然后,用户必须根据应用程序的需要将其缩放/转换为适当的值。与 ''FrequencyCounter::read'' 函数的字符串版本一样,此函数也接受一个 'Wait' 参数,其工作方式与该函数相同。此功能通常不使用,但在其他代码(可能在主机应用程序中)出于任何原因需要读取未更正的二进制值的情况下可用。请参阅此函数的字符串版本的代码,了解如何缩放此值并将其转换为浮点字符串,以了解此未更正的值如何“更正”。

** FreqCtrGateISR 函数 **

最后,如果不需要与系统定时器的默认链接及其 10mS 中断,则用户例程可以调用名为“FreqCtrGateISR”的函数。该函数不是类的一部分,不接受任何参数并且不返回任何内容。(如果使用已发布的默认库文件,则不需要此功能。)

计数器代码详细信息和选项

频率计数器功能包含在文件“FrequencyCounter.cpp”中。包含类原型的头文件在文件“FrequencyCounter.h”中。该模块包含上述功能的代码。根据该项目用户所需的配置,可能还需要模块“SysTimer.cpp”和“PCInterrupt.cpp”。

在传统的频率计数器模式中,该模块需要一个“门控”源,该源通常是一个以固定时间速率发生的不同定时器。如果不使用提供的“SysTimer.cpp”模块,则需要以适当的周期速率(10mS)调用函数“FreqCtrGateISR”。这个模块的精度直接受这个门控时序源的精度影响!

计数器系统定时器和处理器资源

该模块专为使用 Atmel ATMega32U4 的 Arduino Pro Micro 模块而设计,并使用 Timer 0 作为计数输入。最好使用另一个定时器来实现此功能,但不幸的是,定时器 1 的外部时钟引脚(ATMega32U4 引脚 26)没有连接到模块连接器,只有定时器 0 和定时器 1 有外部时钟输入,因此没有其他选择除了使用 Timer 0。众所周知,Timer 0 通常用于 Arduino 系统计时功能(延迟、毫秒、微秒等),因此唯一的选择是将这些功能移至其他计时器。这是通过重新设计作为 Arduino 系统一部分的 stock Wiring.c 模块以为此目的使用不同的计时器来完成的。然后这个“系统”定时器被扩展为也用于频率计数器功能的门定时器。

通过在构建中简单地包含“SysTimer.cpp”,通常由 Timer 0 实现的功能(延迟、毫秒、微秒等)被移动到使用这个备用计时器(可配置为 Timer 1 或 Timer 3),以及一个挂钩到定时器的中断服务程序 (ISR) 是可访问的,允许该定时器用于频率计数器门控功能。最好将定时器 1 用于门,因为它具有最高的中断优先级(甚至高于定时器 0),但定时器 1 或定时器 3 都可以使用。如果用户的应用程序不包含 SysTimer 模块,则它必须使用必须编写的其他代码调用函数“FreqCtrGateISR”。如果需要,SysTimer 模块还可用于频率计数器以外的其他用途。

显然,当为“系统”定时器功能和频率计数器门控功能使用备用定时器时,定时器将不适用于 PWM 功能或任何其他 Arduino“内置”库函数,通常取决于定时器 0 或为Arduino 软件中的“系统”定时器。

需要注意的是,如果使用 USB 与 Pro Micro 模块通信,则返回的计数可能不如使用其他或不使用外部通信方式时精确。这是因为 USB 中断的优先级高于用于门控定时器的定时器 1/定时器 3 定时器。一种可能的替代方法是为门控时间设置另一个定时器并将其输出到引脚上,然后使用引脚更改或外部中断作为门控定时器源(引脚更改和外部中断的优先级高于 USB 中断)。另请注意,当测量高于约 2MHz 的频率时,返回的计数在极少数情况下可能会少一两个计数。这是因为该模块中的代码必须清除计数器,将其关闭然后重新打开,这需要几个 CPU 周期。

计数器外部门控

该频率计数器模块也可以设置为使用外部选通。为此,将“FCEXTERN”定义为非零,并在此草图中包含模块“PCInterrupt.cpp”。然后通过将“模式”功能设置为 6,由“FCEXTGATEMSK”定义的 Arduino 引脚将用作门输入。默认情况下,此信号在 Arduino 数字引脚 9(处理器引脚 PB5)上输入,但如果需要,可以移动到另一个引脚。有关“PCINTMASKxx”引脚列表,请参见“PCInterrupt.h”——这些引脚中的任何一个都可以使用。激活时,此引脚上的低电平打开栅极,高电平时关闭栅极。包括外部门功能是可选的,但包括在分发文件中的定义。添加外部门控功能会使模块的代码大小增加约 250 字节。如果不包括在内,

使用外部门功能和另一个定时器设置为自主工作,然后在其他引脚上输出其信号,然后将此引脚连接到“外部门”输入是解决上述 USB 问题的一种可能方法,该问题可能会影响计数,因为外部门输入的优先级都高于 USB 中断。

计数器周期测量模式

在周期测量模式下使用频率计数器模块时,定时器 0 用于检测输入引脚上的转换,然后使用 Arduino 系统微秒计数器测量这些转换之间的微秒数。在这种模式下,输入仍然在同一个 Timer 0 输入引脚上,但不是计算在给定时间内发生的脉冲数,而是将 Timer 0 设置为在第一次、第十次或第 100 次转换时产生中断测量计时器 0 输入和在其中两个转换之间经过的微秒数,然后将其转换为频率。这允许在最短时间内更准确地测量低频信号。当定时器 0 设置为计数 10 次转换时,这有效地平均了输入信号的 10 个周期,当设置为 100 时,它平均输入信号的 100 个周期。包括周期测量模式是可选的,并且仅在定义“FCPERIOD”被定义为非零值(它用于分发文件)时才包括在内。包括周期测量模式会增加模块的代码大小约 1000 字节。

周期测量模式的计数器超时

使用传统频率计数模式时,函数'FrequencyCounter::read'保证在固定时间后返回;但是在周期测量模式下,如果没有输入信号,则永远不会发生新的“新”频率计数,读取函数也不会返回。在某些情况下,这可能是有问题的。为保证此功能在给定时间后始终返回,频率计数器模块包含一个超时计数器,当使用周期测量模式时,该超时计数器将在给定时间后超时。这个超时定时器使用与门计数器相同的定时器中断,并且是函数“FreqCtrGateISR”的一部分。如果未找到输入,则在此计时器超时后,将报告一个新的零赫兹频率(并且频率读取函数将返回)。此超时值默认为 5 秒,但如果需要,可以通过更改定义的“PERIODTIMOUT”的值来更改。如果此定义为 0,则期间测量功能将不包含任何超时功能。

主模块

如介绍中所述,该项目还包括一个“主”模块(FreqGenCtrApp.ino),用于测试频率发生器和频率计数器模块。它提供了一个简单的 ASCII 命令接口,其中大部分是 1 或 2 个字符命令来控制作为该项目一部分的模块,或者可以通过添加 4 个按钮开关和一个 LCD 显示器来创建一个独立的设备。它可以与频率发生器模块或频率计数器模块或两者一起使用。该模块的使用是可选的,只是为了提供一种方便的方式来测试和验证该项目的两个功能块的操作,并向用户展示如何调用该项目中的每个功能。

串行接口

“FreqGenCtrApp.ino”模块包含代码和定义,允许它使用 USB 虚拟 com 端口作为它的命令接口,或者它可以选择使用 Pro Micro 的 UART 串​​行接口作为同一接口。将“COMM”#define 定义为“Serial”将使用 USB 接口,而将其定义为“Serial1”将使用 UART 接口。该模块还包含一个简单的 printf 接口,允许使用编译器的 printf 函数。

** 串行命令 **

主模块解释的命令大多是 1 或 2 个字符的命令,以 (Enter) 终止以调用它们。对于设置类型命令,命令字母可以选择后跟等号、值和 对于返回值的查询命令,只需输入后跟 的命令字母。然后它们调用生成器或计数器模块中的函数并返回这些函数的结果。命令是:

pYYBAGNtm86AQCT-AAJn8APmw4U779.png
 

独立设备

因为相信许多用户会想要一个简单的独立频率发生器和/或频率计数器而不自己编写它,所以主模块还包括一个简单的控制器,它使用 4 个按钮开关和一个 2x16 LCD 显示器来实现两者的这些功能。其中两个按钮控制频率发生器,而另外两个按钮用于设置频率计数器门模式。这种自包含的独立设备可以用来代替或补充前面详述的串行接口。

发电机设置控制会将输出频率更改为从 10Hz 到 4MHz 的 18 种不同设置之一,以 1、2、5 的顺序在所有十年中进行。频率计数器选择器将选择频率计数器能够设置的 9 种模式和选通时间中的任何一种。这包括 10mS、100mS、1、10 和 100 秒的选通时间和外部选通模式,以及 3 种周期测量模式,平均为 1、10 或 100 次平均值。实现这一独立功能所需的只是一个 LCD 显示屏和四个按钮开关。LCD 显示器使用标准的 Arduino “LiquidCrystal”库。按钮接口被实现为简单的去抖动数字输入。

该项目的主要 Arduino 模块 (FreqGenCtrApp.ino) 有许多定义,这些定义控制模块的编译方式,从而控制程序将执行的功能。除了控制频率发生器和频率计数器模块的包含的定义外,还有两个定义启用独立模式代码、串行接口代码以及是否有 LCD 显示器。定义“FREEIF”控制是否包含独立按钮界面。定义“COMIF”控制串行接口是否可用。最后,定义“HASLCD”应包含 LCD 显示功能。即使不包括独立接口,LCD 显示器也可以与串行接口一起使用。

下面的示意图显示了 LCD 显示器和使用独立模式或在设计中添加 LCD 显示器所需的四个按钮开关的连接。

pYYBAGNtm9SAXs9TAAGCLgMD6So283.jpg
 

所示的大部分部件都可从 Digikey 或 Mouser 获得。Pro-Micro 模块可从 Sparkfun(部分 DEV-12640)获得,或者可以在 eBay 上以更少的价格获得等效的克隆。显示的 LCD 显示器是 Hantronix HDM16216H-5-S00S(无背光)或 HDM16216L-5-L30S(LED 背光),但其他显示器也可以使用,只要它们与 Arduino LCDDisplay 库一起使用。电位器和电阻器可以是所需/可用的任何通用部件。四个开关应为适合工程机械设计的任意瞬时触点按钮开关。

使用这个附加接口允许频率发生器和频率计数器模块用作独立的测试设备。

为 Pro Micro 模块供电

在本文档中,没有提及如何为 Pro-Micro 模块以及可能的 LCD 显示器供电。假设它将通过将 USB 电缆连接到 Pro Micro 模块上的 USB 连接来供电。USB 连接为模块和所需的任何外部电路提供 5V 电压,只要任何外部电路所需的功率小于约 100mA。USB 电缆的另一端可以连接到计算机以获取电源并访问虚拟 COM 端口和编程,或者如果将系统用作独立设备,则可以连接到简单的 5V 壁式电源。只有在不使用 USB 连接的情况下,Pro Micro 模块也可以通过 7-16V 直流电源的“RAW”输入或通过稳压 5V 直流电源的“VCC”引脚供电。

编译和归档信息

该项目和库是使用 Arduino IDE 版本 1.8.5 开发的。较新的版本,包括最新版本(版本 1.8.15)也应该能够毫无问题地使用。IDE的“工具”中的设置应该是:

董事会:阿杜诺·莱昂纳多

端口:COMxx(由您的系统分配)

程序员:ArduinoISP

频率发生器和频率计数器模块最初是在一个项目目录“FreqGenCtrApp”中编写和调试的,其中包含以下文件:

pYYBAGNtm9iAT2N_AAKC7bGOxo4114.jpg
 

如前所述,所有上述文件都可以在单个目录中并以这种方式编译,或者它们可以是频率发生器库或频率计数器库的一部分。如果使用这些库,每个库中都有一个示例文件夹,其中包含一个仅用于频率发生器或频率计数器的主应用程序文件,以及一个包含组合应用程序的文件夹。

poYBAGNtm9yARJmwAAES5R37Y2M355.jpg
 

FrequencyGenerator 库文件位于 Github 上,地址为https://github.com/Rick-G1/FrequencyGenerator

FrequencyCounter 库文件位于 Github 上,地址为https://github.com/Rick-G1/FrequencyCounter

当我可以弄清楚如何在“草图”/“包含库”/“管理库......”中的 Arduino IDE 下制作这些库时,这些库应该在那里可用。

频率发生器/计数器和时基精度

用于发生器和频率计数器的时基是微处理器的时钟,它是一个晶体振荡器,具有其固有的精度和稳定性,但由于它没有经过校准,它通常会与其标称频率 16MHz 相差几赫兹。这通常在大约 0.1% 到 0.2% 之间,但可能会更多,具体取决于所使用的 Pro Micro 模块。由于晶体频率可能会有所不同,因此频率发生器的输出和频率计数器读取的值将以相同的百分比变化。

在编写本文档期间检查了手头上的几个模块,发现它们中的大多数都在 0.1% 以内,只有少数在 0.2% 的准确度值以内。如果此精度水平足以满足预期应用,则无需进一步努力即可使用此频率发生器或计数器功能。

如果需要更高的精度,可以修改 Arduino 模块以包含微调电容器以将模块晶体频率精确调整到 16MHz,或者将外部高精度 16MHz 时钟信号注入模块以提高生成频率的精度或控制器进行的频率测量。显然,需要一个校准的频率计数器来将 Arduino Pro Micro 模块校准到准确的频率。

在测量任何晶体振荡器的频率时,不要直接在晶体本身的任一引脚上测量晶体频率。仅仅增加测量设备的电容就足以显着改变晶体振荡器电路的频率。相反,将控制器设置为在其输出引脚之一上输出已知频率的时钟信号,并改为测量该信号。由于该项目的一部分包含频率发生器功能,因此该输出信号是用于测量和校准控制器晶体时基精度的完美信号。频率发生器功能可设置为8MHz,非常适合检查和调谐模块上的晶振。

添加微调电容器

可用于调整系统时基的方法之一是在 Arduino 模块中添加一个微调电容器。然后通过使用连接到校准频率计数器的项目的频率发生器部分输出已知频率并调整此微调电容器以设置输出频率,系统时基可以精确设置为 16MHz,频率发生器输出的精度和计数器的时基为零,或与用于调整它的参考设备一样准确。

要安装微调电容器,请从模块上拆下 C2 电容器并安装一个范围约为 5 至 40pF 的微调电容器。可用于此目的的建议部件是 Knowles Voltronics JR300 (5.5-30pF) 或 JR400 (8-40pF)(Digikey 1674-1020-1-ND 或 1674-1021-1-ND)。这是一个小型表面贴装部件,可以粘在处理器芯片上,然后用小电线将其连接到 GND 和 C2 被移除的焊盘。由于微调电容会随着温度的变化而存在一定的可变性,因此振荡器的稳定性直接关系到微调电容的稳定性。如果需要更高的稳定性,另一种更稳定的方法是将 C2 替换为较小值的电容器(可能 5-15pF),然后使用具有较小电容范围(因此总电容变化较小)的微调电容器(如 JR150 或 JR200 ) 使得固定电容和可变电容的总电容可以变化到接近 22pF 的值。重要的是要注意这部分,一个端子连接到转子(和调节螺钉的金属)。此端子应连接到 Arduino 模块的 GND 连接,另一个端子应连接到未接地的 C2 焊盘(并连接到 Pro Micro 模块上微处理器的引脚 17)。这将提供频率最稳定的电路。连接微调帽的 GND 连接的方便位置是模块电容器 C19 的负极。接下来显示了建议的微调电容器的图片以及 Pro Micro 模块的修改细节。微调电容器图片顶部的端子是“转子”端子。连接完成后,最好将微调帽粘在微处理器芯片的顶部,以防止其移动,从而提高晶体频率的稳定性。您可能还需要考虑通过在电线周围涂上热胶或环氧树脂来稳定接线以保持最大的准确性,以防止它们被意外损坏或移动。微调电容器图片顶部的端子是“转子”端子。连接完成后,最好将微调帽粘在微处理器芯片的顶部,以防止其移动,从而提高晶体频率的稳定性。您可能还需要考虑通过在电线周围涂上热胶或环氧树脂来稳定接线以保持最大的准确性,以防止它们被意外损坏或移动。微调电容器图片顶部的端子是“转子”端子。连接完成后,最好将微调帽粘在微处理器芯片的顶部,以防止其移动,从而提高晶体频率的稳定性。您可能还需要考虑通过在电线周围涂上热胶或环氧树脂来稳定接线以保持最大的准确性,以防止它们被意外损坏或移动。

pYYBAGNtm9-AVSAVAAIBoGpY2wM386.jpg
 

一旦对模块进行了修改,就可以进行调整。为了获得最准确的调整,在进行调整之前,让模块在预期使用的温度下保持通电至少 15 分钟(几个小时更好)。然后启用控制器的频率输出并将其设置为 8MHz。设置输出信号后,使用校准的频率计数器并测量此输出信号(在数字引脚 5 上)(或数字引脚 10)。如外部频率计数器所示,将微调电容器调整为 8MHz。

注入外部时钟

为了获得更高的精度,可以使用外部时钟为控制器芯片提供时钟(因此也提供时基)。使用这种方法,频率发生器和计数器的精度与外部时钟电路的精度直接相关。各种具有极其精确和稳定输出的外部振荡器可供选择,从低成本 IC 到非常昂贵、高度稳定的 TCXO 模块。这些模块的唯一要求是它们必须在 3.3V 或 5V 信号电平下输出 16MHz。然后可以将该外部时钟的输出注入到修改后的 Pro Micro 模块中,如图所示。在本例中,外部时基通过一个电阻器注入“A3”引脚,以防止在外部时钟通电但模块未通电的情况下使模块过载。10-47Ω 1/8W 电阻器可用于此目的。

poYBAGNtm-OAZb5EAAHANZBSZeM614.jpg
 

显然,当使用该引脚时,A3 引脚的正常模拟输入功能将丢失。详细信息还显示了 GND(振荡器公共端)和 5 伏电源的位置,如果外部振荡器的电流小于 100 毫安,外部振荡器可以使用该电源为其供电。5V 电源信号来自 USB 输入电源,可能会在 5V 之间变化 10-15%(有时只有 4.5V 左右)。

使用外部时钟源时,处理器上的熔丝可以重新编程为外部时钟模式,但这不是必需的,因为注入时钟的引脚是晶振的输入,因此处理器会“看到”来自外部源的 16MHz 并使用它。您也可以移除 Pro Micro 模块上的晶体,但这也不是使用外部时钟所必需的。

结论

该项目详细介绍了仅使用低成本 Pro-Micro 模块来实现频率发生器和频率计数器模块。频率发生器可输出1Hz至约12MHz的方波信号,而频率计可在传统频率计模式下对1Hz至约8MHz输入的脉冲进行计数,在周期测量模式下可对从远小于1Hz至约20KHz的脉冲输入进行计数。虽然该项目的主要重点是模块本身,但还提供了一个简单的主程序来测试这些功能,带有一个串行端口或 4 个按钮开关和一个 LCD 显示器。这些模块的编写使得它们是自包含的功能块,并且可以毫不费力地添加到用户代码中。希望拥有这些模块能够通过简单地包含这些模块来帮助用户,


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !