找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 15475|回复: 0
打印 上一主题 下一主题
收起左侧

Arduino学习13-最简单的Arduino频率计

[复制链接]
跳转到指定楼层
楼主
想测量一个声音的频率或是占空比,但是又没频率计?我们可以用一块arduino去搞定这事情。

需要的材料仅是一块普通arduino,无需外围元件。

特性:
1. 可以测量20~20kHz的信号,超过的话误差越来越大。
2. 误差大致是±5%。玩玩还行。
3. 输出的结果有:频率,占空比,周期,高电平时间,低电平时间。
4. 只能测量单频,复合波形就不行了。

步骤:
1.写下面程序到arduino里面
  1.     /*
  2.     Arduino Frequency meter
  3.     Ansifa
  4.     2013/1/5
  5.     */
  6.     int divider[6] = {0, 1, 8, 64, 256, 1024};
  7.     int prescaler = 5;
  8.     double count = 0;
  9.     double middle = 0;
  10.     char x = 0;
  11.     ISR(TIMER1_OVF_vect)
  12.     {
  13.         if (prescaler < 4)
  14.         {
  15.             prescaler++;
  16.         }
  17.     }
  18.     void interrupt()
  19.     {
  20.         if (!x)
  21.         {
  22.             count = TCNT1;
  23.             TCNT1 = 0x000;
  24.             TCCR1B = prescaler;
  25.             attachInterrupt(0, interrupt, FALLING);
  26.         }
  27.         else
  28.         {
  29.             middle = TCNT1;
  30.             attachInterrupt(0, interrupt, RISING);
  31.         }
  32.         x = ~x;
  33.     }
  34.     void setup()
  35.     {
  36.         Serial.begin(57600);
  37.         TIMSK1 = 0x01;
  38.         TCCR1A = 0x00;
  39.         attachInterrupt(0, interrupt, RISING);
  40.     }
  41.     void loop()
  42.     {
  43.         Serial.print("Freq: ");
  44.         Serial.print(16000000.0 / divider[prescaler] / count);
  45.         Serial.print(" Hz                Duty: ");
  46.         Serial.print(middle / count * 100);
  47.         Serial.print(" %                Period: ");
  48.         Serial.print(0.0000625 * divider[prescaler]*count);
  49.         Serial.print(" ms                H-time: ");
  50.         Serial.print(0.0000625 * divider[prescaler]*middle);
  51.         Serial.print(" ms                L-time: ");
  52.         Serial.print(0.0000625 * divider[prescaler]*(count - middle));
  53.         Serial.println(" ms");
  54.         if (prescaler > 1)
  55.         {
  56.             prescaler--;
  57.             delay(200);
  58.         }
  59.         delay(100);
  60.     }
复制代码

2. 将你的信号从D2和GND引脚输入。由于没有经过任何放大处理,信号必须满足开关arduino引脚的电平值,就是最好可以有0-5v的振幅。。

电路图太简单


3. 打开串口监视器,调波特率到57600,即可看到结果。因为没有任何防干扰措施,出现偏差特别大的结果请自行忽略。



4. 如果你愿意的话,也可以扩展一下这个电路的性能:
* 振幅不够的话,可以使用运放或者三极管进行预放大;
* 测量频率不够高,可以使用74HEF4060进行分频。74HEF4060可以支持高达2^14=16384级分频,理论可以将量程提高16384倍。但是由于74HEF4060性能限制,可以将输入频率提高到20MHz。但是分频之后就只能看到频率,而测不到波形的占空比了。并且注意不要使用CD4060,那是低速版本。

问题解答:
请教
1)这个interrupt函数用的是递归吗?

2)TCNT1 = 0x000;
  TCCR1B = prescaler;
  TIMSK1 = 0x01;
   TCCR1A = 0x00;

这几句话分别代表什么意思呢?
是定义时钟的寄存器?
这几句

答:
我就是懒得解释才删掉所有注释的。。。

   1)这个interrupt函数用的是递归吗?
   
   不是,因为没有调用,attachInterrupt只是设置上升触发中断还是下降触发,因为输入波形上升下降是轮流发生的,所以设置一个检测完一种立即换另外一个,x就是不断在换。

2)TCNT1 = 0x000;
  TCCR1B = prescaler;
  TIMSK1 = 0x01;
   TCCR1A = 0x00;

这几句话分别代表什么意思呢?
是定义时钟的寄存器?

这几句都是寄存器,TCNT1存着计数器当前值,就是计次结果;TCCR1B预分频器,调整量程;TIMSK1允许计数器1溢出中断;TCCR1A是其他零碎的。。。请参看http://wenku.baidu.com/view/ec6961f09e3143323968931b.html

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表