共2条
1/1 1 跳转至页
问
请问谁用AVR做过频率计,
我用Input Capture做的测周期,
但是发现总是不准.相差能在4%左右.实在太大了.
我的要求是最大千分之一.
不知谁做过这个,能否指点一二?
答 1: 测量的频率范围是多少?如果频率不是很低,用计数法更好些。 答 2: 我也准备做一个频率计,能否将你的代码参考一下?我是参加电子设计竞赛的学生,没有商业上的问题
如果你也用的是ATmega8的芯片,我十分愿意共同开发,不要报酬。 答 3: 没道理啊.没道理不能用Input Capture测频测周啊.
AVR的DataSheet上就说Input Capture可以用来测频的.
而且,我觉得程序应该没有什么问题,
一进Capture的中断就立即读取ICR的值,应该没错吧.
即便考虑进中断的四个时钟周期,那也只是0.5us的误差吧,
误差率应在0.5us/1ms=0.05%以下吧.(我现在只是做1KHz以下的测周)
可是误差怎么会这么大呢?
用计数器会不会好一点?
这是不是AVR本身的bug?或者是我在使用中遗漏了什么重要环节?
想了很久,改了很久,都没有什么变化.
请高手指教.
答 4: 我的程序不具有什么参考价值过纯中,你好.
我的程序不具什么参考价值,
只是随手写来测试一下AVR的Input Capture和Timer的准确度.
只写了一小部分(测周),
如果你要的话,可以等我写完后交换代码看一看.
我也是参加了今年的竞赛,QQ:151018994
可以交流 答 5: 发现问题了.原来是内部晶振的问题.原来是内部晶振不准.
换了外部的就好了.
只不过还是有点问题,就是精度只能到0.3%左右,
达不到0.1%的要求.:( 答 6: 信号源的波形和精度能达到要求吗? 答 7: ICP的噪声抑制使用了吗? 答 8: 用了噪声抑制.用了噪声抑制,信号源的精度没问题.
在低频时测量精度高(能达到5位有效数字,最后一位有时有点小变化,问题不大),100Hz以上精度就不太高,(第3位数字会变).比如844.33,测出来就变成855.21 我想不明白为什么.
我是这样测的:
1Hz-10Hz 以32us为单位进行测量.即TCCR1B=0xC4;(C表示上升沿,带噪声抑制,4表示256预分频)
10hz-100hz 以8us为单位进行测量.
100Hz-1KHz 以1us为单位进行测量.
这样测出来的数据应该都在1000-10000之间,误差率应在0.1%以下,
我这样算没错吧...
可是最后出来误差率在0.3%左右....
有可能是什么原因呢?
答 9: 被测信号作为闸门测量方法看上去好像没有问题,100Hz-1KHz 以1us为单位进行测量时数据在1000-10000之间,理论上只存在+-1误差。
你能确定信号源频率正确吗?844.33用什么测量的?要用好的频率计确认,示波器看的不准。还有信号源本身稳不稳定,精度能达到0.1%吗? 答 10: 今天我也写出了频率计的基本代码。不过好像问题多多,首先一个频率自适应问题就需要大量编码,不然如果被测信号频率低的话,16位的计数器很容易就溢出了n次了。
blackthick的程序应该写了差不多了,不知道你是怎么解决的?
如果你愿意请将代码发至:
ericguo@eastday.com 答 11: 过纯中不好意思,我只写了测周(量程自转换)的部分,
因为这几天比较忙,所以一直没动那个程序.
我过两天写好了再跟你探讨吧.OK?
答 12: 其实测频还是用CPLD做比如方便.用CPLD测又准又简单,
一个状态机就可以解决量程自转换的问题.
用单片机好像真的很麻烦,
还要一些外围的分频器之类的.:( 答 13: 我的程序使用32位软计数器来解决问题最高频率<100KHz// Eric Guo writed at 2003-08-02, GPL license.
#include <AVR/io.h>
#include <AVR/interrupt.h>
#include <AVR/signal.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "zlg7289.h"
volatile union cap_tags{
u32 l;
struct {u16 i0, i1; } i;
} cap_new, cap_old;
volatile u08 CAN_show;
void display_num(unsigned long num);
void mcu_init(void)
{
ACSR =(1<<ACBG)|(1<<ACIC)|(1<<ACIS1)|(1<<ACIS0);
TCCR1A=0x00;
TCCR1B=0x81; // CLK/1
ICR1 =0;
TCNT1 =0;
ASSR = 1<<AS2; // Page 99
TCCR2 = 0x05; // Div128
TIMSK =(1<<TICIE1)|(1<<TOIE1)|(1<<TOIE2); // enable capture
}
SIGNAL(SIG_INPUT_CAPTURE1)
{
cap_old.l=cap_new.l;
cap_new.i.i0=ICR1;
CAN_show=1;
}
SIGNAL(SIG_OVERFLOW1)
{
cap_new.i.i1++;
CAN_show=0;
}
INTERRUPT(SIG_OVERFLOW2)
{
while(CAN_show==0) ;
if(cap_new.l>cap_old.l)
{
float fre;
fre=F_CPU/(cap_new.l-cap_old.l);
display_num( fre );
}
}
int main(void)
{
zlg7289_reset();
mcu_init();
sei();
cap_old.l=0;
cap_new.l=0;
CAN_show=0;
while(1)
{
// let the interrupt do jobs.
}
return 0;
}
void display_num(unsigned long num)
{
char zlg_line[0x10];
u08 i, j;
zlg7289_disp(0, 0, ZLG7289_RESET);
ultoa(num, zlg_line, 10);
for(i=strlen(zlg_line)-1, j=0; i>0; i--, j++)
zlg7289_disp(zlg_line[i], j, ZLG7289_TYPE0);
zlg7289_disp(zlg_line[0], j, ZLG7289_TYPE0);
}
// 大家以后还是用代码说话。 答 14: 我现 在也正在编一个频率计的程序我用的是AT90S8515,我正在编,望各位大侠有好的建议,给我 发E-MAIL.
同时我 也正在编串口通讯和LCD控制,请各位大侠给点建议和指导。
我的 E-MAIL:wanglele615@163.com
我用Input Capture做的测周期,
但是发现总是不准.相差能在4%左右.实在太大了.
我的要求是最大千分之一.
不知谁做过这个,能否指点一二?
答 1: 测量的频率范围是多少?如果频率不是很低,用计数法更好些。 答 2: 我也准备做一个频率计,能否将你的代码参考一下?我是参加电子设计竞赛的学生,没有商业上的问题
如果你也用的是ATmega8的芯片,我十分愿意共同开发,不要报酬。 答 3: 没道理啊.没道理不能用Input Capture测频测周啊.
AVR的DataSheet上就说Input Capture可以用来测频的.
而且,我觉得程序应该没有什么问题,
一进Capture的中断就立即读取ICR的值,应该没错吧.
即便考虑进中断的四个时钟周期,那也只是0.5us的误差吧,
误差率应在0.5us/1ms=0.05%以下吧.(我现在只是做1KHz以下的测周)
可是误差怎么会这么大呢?
用计数器会不会好一点?
这是不是AVR本身的bug?或者是我在使用中遗漏了什么重要环节?
想了很久,改了很久,都没有什么变化.
请高手指教.
答 4: 我的程序不具有什么参考价值过纯中,你好.
我的程序不具什么参考价值,
只是随手写来测试一下AVR的Input Capture和Timer的准确度.
只写了一小部分(测周),
如果你要的话,可以等我写完后交换代码看一看.
我也是参加了今年的竞赛,QQ:151018994
可以交流 答 5: 发现问题了.原来是内部晶振的问题.原来是内部晶振不准.
换了外部的就好了.
只不过还是有点问题,就是精度只能到0.3%左右,
达不到0.1%的要求.:( 答 6: 信号源的波形和精度能达到要求吗? 答 7: ICP的噪声抑制使用了吗? 答 8: 用了噪声抑制.用了噪声抑制,信号源的精度没问题.
在低频时测量精度高(能达到5位有效数字,最后一位有时有点小变化,问题不大),100Hz以上精度就不太高,(第3位数字会变).比如844.33,测出来就变成855.21 我想不明白为什么.
我是这样测的:
1Hz-10Hz 以32us为单位进行测量.即TCCR1B=0xC4;(C表示上升沿,带噪声抑制,4表示256预分频)
10hz-100hz 以8us为单位进行测量.
100Hz-1KHz 以1us为单位进行测量.
这样测出来的数据应该都在1000-10000之间,误差率应在0.1%以下,
我这样算没错吧...
可是最后出来误差率在0.3%左右....
有可能是什么原因呢?
答 9: 被测信号作为闸门测量方法看上去好像没有问题,100Hz-1KHz 以1us为单位进行测量时数据在1000-10000之间,理论上只存在+-1误差。
你能确定信号源频率正确吗?844.33用什么测量的?要用好的频率计确认,示波器看的不准。还有信号源本身稳不稳定,精度能达到0.1%吗? 答 10: 今天我也写出了频率计的基本代码。不过好像问题多多,首先一个频率自适应问题就需要大量编码,不然如果被测信号频率低的话,16位的计数器很容易就溢出了n次了。
blackthick的程序应该写了差不多了,不知道你是怎么解决的?
如果你愿意请将代码发至:
ericguo@eastday.com 答 11: 过纯中不好意思,我只写了测周(量程自转换)的部分,
因为这几天比较忙,所以一直没动那个程序.
我过两天写好了再跟你探讨吧.OK?
答 12: 其实测频还是用CPLD做比如方便.用CPLD测又准又简单,
一个状态机就可以解决量程自转换的问题.
用单片机好像真的很麻烦,
还要一些外围的分频器之类的.:( 答 13: 我的程序使用32位软计数器来解决问题最高频率<100KHz// Eric Guo writed at 2003-08-02, GPL license.
#include <AVR/io.h>
#include <AVR/interrupt.h>
#include <AVR/signal.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "zlg7289.h"
volatile union cap_tags{
u32 l;
struct {u16 i0, i1; } i;
} cap_new, cap_old;
volatile u08 CAN_show;
void display_num(unsigned long num);
void mcu_init(void)
{
ACSR =(1<<ACBG)|(1<<ACIC)|(1<<ACIS1)|(1<<ACIS0);
TCCR1A=0x00;
TCCR1B=0x81; // CLK/1
ICR1 =0;
TCNT1 =0;
ASSR = 1<<AS2; // Page 99
TCCR2 = 0x05; // Div128
TIMSK =(1<<TICIE1)|(1<<TOIE1)|(1<<TOIE2); // enable capture
}
SIGNAL(SIG_INPUT_CAPTURE1)
{
cap_old.l=cap_new.l;
cap_new.i.i0=ICR1;
CAN_show=1;
}
SIGNAL(SIG_OVERFLOW1)
{
cap_new.i.i1++;
CAN_show=0;
}
INTERRUPT(SIG_OVERFLOW2)
{
while(CAN_show==0) ;
if(cap_new.l>cap_old.l)
{
float fre;
fre=F_CPU/(cap_new.l-cap_old.l);
display_num( fre );
}
}
int main(void)
{
zlg7289_reset();
mcu_init();
sei();
cap_old.l=0;
cap_new.l=0;
CAN_show=0;
while(1)
{
// let the interrupt do jobs.
}
return 0;
}
void display_num(unsigned long num)
{
char zlg_line[0x10];
u08 i, j;
zlg7289_disp(0, 0, ZLG7289_RESET);
ultoa(num, zlg_line, 10);
for(i=strlen(zlg_line)-1, j=0; i>0; i--, j++)
zlg7289_disp(zlg_line[i], j, ZLG7289_TYPE0);
zlg7289_disp(zlg_line[0], j, ZLG7289_TYPE0);
}
// 大家以后还是用代码说话。 答 14: 我现 在也正在编一个频率计的程序我用的是AT90S8515,我正在编,望各位大侠有好的建议,给我 发E-MAIL.
同时我 也正在编串口通讯和LCD控制,请各位大侠给点建议和指导。
我的 E-MAIL:wanglele615@163.com
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动——B站互动赢积分】活动开启啦! | |
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |