ATmega8 单片机怎么测频率?

有一个正弦波输入ATmega8的单片机内
我知道用ICP1来输入,然后来一个输入捕捉,用TCNT1来记录,可是我不知道怎么来中断
最好有一些类似的代码,这是不是一个复杂的
还有,我已经用了TCCR1来创造输出PWM的波了,那么怎么样再设置这个呢?
我找了好多网站,他们都是很复杂的那种.
请大家能告诉主要思路怎么样的吗?谢谢,我已经纠结这个问题两天了,谢谢高手们了,答案录用的话,再追加100分,谢谢!
我是用C来编的....
万分感谢

正弦波先要整形成方波再送入M8进行中断,不然容易出错

例子;给你参考一下吧  外部中断来了 你就在外部中断函数里面写你中断以后你要执行的程序就可以了,就这么简单  PWM占空比,周期  都可以通过定时器寄存器初值来设定

//ICC-AVR application builder : 2009-09-11 19:02:05

// Target : M8

// Crystal: 8.0000Mhz

#include <iom8v.h>

#include <macros.h>

void port_init(void)

{

 PORTB = 0x00;

 DDRB  = 0x00;

 PORTC = 0x00; //m103 output only

 DDRC  = 0x00;

 PORTD = 0x00;

 DDRD  = 0x00;

}

//TIMER1 initialize - prescale:64

// WGM: 0) Normal, TOP=0xFFFF

// desired value: 1mSec

// actual value:  1.000mSec (0.0%)

void timer1_init(void)

{

 TCCR1B = 0x00; //stop

 TCNT1H = 0xFF; //setup

 TCNT1L = 0x83;

 OCR1AH = 0x00;

 OCR1AL = 0x7D;

 OCR1BH = 0x00;

 OCR1BL = 0x7D;

 ICR1H  = 0x00;

 ICR1L  = 0x7D;

 TCCR1A = 0x00;

 TCCR1B = 0x03; //start Timer

}

#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF

void timer1_ovf_isr(void)

{

 //TIMER1 has overflowed

 TCNT1H = 0xFF; //reload counter high value

 TCNT1L = 0x83; //reload counter low value

}

#pragma interrupt_handler int0_isr:iv_INT0

void int0_isr(void)

{

 //external interupt on INT0

}

//call this routine to initialize all peripherals

void init_devices(void)

{

 //stop errant interrupts until set up

 CLI(); //disable all interrupts

 port_init();

 timer1_init();

 MCUCR = 0x00;

 GICR  = 0x40;

 TIMSK = 0x04; //timer interrupt sources

 SEI(); //re-enable interrupts

 //all peripherals are now initialized

}

//

void main(void)

{

 init_devices();

 //insert your functional code here...

补充:

建议你仔细看M16的资料 关于定时器及PWM那块 这是别人无法代替的

输出比较寄存器1A - OCR1AH 与 OCR1AL

输出比较寄存器1B - OCR1BH 与 OCR1BL

16 位定时器/ 计数器寄存器的说明 T/C1 控制寄存器A - TCCR1A

                                T/C1 控制寄存器B - TCCR1B

TCCR1A  用来对模式进行选择 详情还得看资料  内容太多 

TCCR1B  分频选择

如TCCR1A:

7 6 5 4 3 2 1 0

COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10

其中 如图

温馨提示:内容为网友见解,仅供参考
第1个回答  2009-09-11
你的正弦波整形过了吧,其实不难,你用两个计数器就可以实现,程序如下,这里加了1602LCD,你不用的话就删掉,这个程序绝对好用,我用过好几次了,注释写的很清楚,可测到M级的频率,T1引脚接整形后的方波

//使用内部RC振荡器 8M

#include <iom8V.h>
#define uchar unsigned char
#define uint unsigned int
#define SET_E PORTC|=0x04 // LCD: E = 1
#define CLR_E PORTC&=~0x04 // LCD: E = 0
#define CLR_RW PORTC&=~0x02 // LCD: R/W = 0
#define SET_RS PORTC|=0x01 // LCD: R/S = 1
#define CLR_RS PORTC&=~0x01 // LCD: R/S = 0
#define LCD_Data PORTB // 数据端口PB口

uchar Table[]="0123456789";
uchar Data[]={0,0,0,0,0,0,0}; //显示初始值
uchar k;
uint n;

//延时函数
void DelayMs(uint i) //Ms级延时,参数i为延时时间
{uint j;
for(;i!=0;i--)
{for(j=1142;j!=0;j--) ;}
}

//LCD写数据
void WriteData(uchar WD)
{
SET_RS;
LCD_Data=WD;
CLR_RW;
CLR_E;
DelayMs(2);
SET_E;
}

//LCD写指令
void WriteCommand(uchar WC)
{
CLR_RS;
LCD_Data=WC;
CLR_RW;
CLR_E;
DelayMs(2);
SET_E;
}

//初始化
void Init(void)
{
DDRB=0xff; //设置B口为推挽1输出
PORTB=0xff;
DDRD=0x00; //设置D口为不带上拉电阻输入
PORTD=0x00;
DDRC=0xff; //设置C口为推挽1输出;
PORTC=0xff;
OSCCAL=0xaa; //校正内部RC振荡器频率,不同的芯片参数有差异
LCD_Data = 0;
WriteCommand(0x38);
//DelayMs(5);
WriteCommand(0x38); //显示模式设置
WriteCommand(0x08); //关闭显示
WriteCommand(0x01); //显示清屏
WriteCommand(0x06); // 显示光标移动设置
WriteCommand(0x0c); // 显示开及光标设置
TCCR0=0x05; //T/C0工作于定时方式, 内部1024分频
TCCR1B=0x06; //T/C1工作于计数方式,外部下降沿计数
SREG=0x80; //开中断
TIMSK=0x05; //T/C0、T/C1中断允许
TCNT0=4; //T/C0计数器初始值
}

//按指定位置显示字符
void Display(uchar x, uchar y, uchar *p)
{uchar i,j;
for(i=x;i<x+7;i++)
{
if (y==0)
{
j=0x80+i; //当要显示第一行时地址码+0x80;
WriteCommand(j); //发送地址码
j=i-x;
WriteData(Table[p[j]]);
}
else
{
j=0xc0+i; //当要显示第二行时地址码+0xc0;
WriteCommand(j); //发送地址码
j=i-x;
WriteData(Table[p[j]]);
}
}
}

//计数值处理函数。参数i:计数值;参数p:处理数据存放的数组名
//功能:此函数用于将计数值拆分为BCD码,用于查表显示
void Process(unsigned long i,uchar *p)
{
p[0]=i/1000000;
i=i%1000000;
p[1]=i/100000;
i=i%100000;
p[2]=i/10000;
i=i%10000;
p[3]=i/1000;
i=i%1000;
p[4]=i/100;
i=i%100;
p[5]=i/10;
i=i%10;
p[6]=i;
}

//主函数
void main(void)
{
DelayMs(500); //启动等待,等LCD讲入工作状态
Init(); //初始化I/O口

while(1)
{
}
}

//T/C1中断函数,作计数器
#pragma interrupt_handler Timer1_ovf:9
void Timer1_ovf(void)
{
n++;
}

//T/C0中断函数,作定时器
#pragma interrupt_handler Timer0_ovf:10
void Timer0_ovf(void)
{
TCNT0=4;
k++;
if(k==31) //若计时满1秒
{
uint m;
unsigned long f;
k=0;
m=TCNT1L;
m=(TCNT1H<<8)+m; //取T/C1 n次中断后计数的尾数
TCNT1H=0;
TCNT1L=0;
f=(unsigned long)65536*n+m; //取频率值
Process(f,Data); //计数值处理
Display(0,0,Data); //显示
n=0;
}
}

ATmega8 单片机怎么测频率?
正弦波先要整形成方波再送入M8进行中断,不然容易出错 例子;给你参考一下吧 外部中断来了 你就在外部中断函数里面写你中断以后你要执行的程序就可以了,就这么简单 PWM占空比,周期 都可以通过定时器寄存器初值来设定 \/\/ICC-AVR application builder : 2009-09-11 19:02:05 \/\/ Target : M8 \/...

单片机的晶振频率怎么确定?
根据使用需要确定,举例:如果要产生标准的串口波特率,应使用11.0592MHz,如果要让51单片机产生整数的时钟频率可使用12MHz或者24MHz单片机。另外根据单片机本身的参数,不要选择过高的频率,否则会工作不稳定。举例:Atmega8L-8PU,这个单片机后面一个8的意思就是建议最大工作频率不要超过8MHz,如果超过8MHz...

单片机的工作频率问题
1、单片机时钟频率有限,操作频率更低,你不可能用单片机去解调射频信号。2、必须象收音机那样具有接收、选频、放大、变频、中放、解调等高频电路。3、单片机可以用来控制高频电路的频率、增益等参数,还可以用单片机对接收的基带信号进行处理。

单片机ATmega8L管脚图及各脚说明分别是什么?
单片机ATmega8L管脚图:单片机ATmega8L各个管脚说明:1、2脚:天线端。3、4脚:增益调节端,调节外接电阻可调节灵敏度,即调节检测距离。5脚:触发禁止控制端,当5脚电压<0.3UDD时,禁止触发;当5脚电压>0.3UDD时,允许触发。6脚:接电源滤波电容器端。7脚:电源负端USS。8脚:重复触发控制端,8...

ATMEGA8,ATMEGA48之类的单片机,程序相互刷写而输出一样,需要满足什么条 ...
频率一样 即晶振一样,分频也一样就可以了 没有太多的注意事项 补充说明:世界上没有任何完全相同的东西 即使选择相同的晶振也会有微量的偏差 不过这不影响到你的使用 嘿嘿 希望能帮到你!

请教一下各位:AVR单片机ATmega8L的出厂默认时钟一定都是内部1MHZ RC...
出厂默认时钟确实是内部1MHZ RC震荡时钟,如果是其他频率的就应该是翻新的。读出的熔丝位应该是0001,你如果读出来是0000,如果你接了外部时钟,你去掉外部时钟看看是不是还能与芯片通信(仅限USBASP连接方式,JTAG方式是万能通信的),如果去掉外部时钟就不能通信了,说明你的芯片熔丝位确实是0000,那八...

用于ATmega8单片机的C语言设计,急!
define XTAL 4 uint8 count_sonic=0;uint8 High_Time=0;uint8 Low_Time=0;uint16 Count_24us=0;uint8 Time1_Ovf_Flag=0;\/*=== 微秒级精确延时函数,晶振8M:Delay = 0.125 *((tt*4-1)+9)微秒 其中9包括了调用方的 r16 赋值 1t rcall 3t nop 1t ret 4t brne指令在当判断...

Atmega8的详细参数
ATmega8 参数 ATmega8存储器 Flash ROM 8KB SRAM 1024B EEPROM 512B ATmega8性能参数特性 工作频率 0-8MHz (ATmega8L) 0-16MHz (ATmega8) 工作电压 2.7-5.5V (ATmega8L) 4.5-5.5V (ATmega8) I\/O口 23个 16位定时器 \/ 计数器 1 8位定时器 \/ 计数器 2...

AT89C52和Atmega8哪个单片机更好,两者的相同点和不同点有哪些?
ATmega8性能比AT89C52好很多,第一是速度,同样的频率下mega8比89C52快不止10倍。第二,mega8比89C52外设丰富的多,比如定时器,AD转换等。第三,mega8稳定性好,抗干扰强。第四,mega8 I\/O驱动灵活,上拉,推免,集电极开路可任意选择。mega8还有更多比89C52强的地方这里就不多说了,现在哪个好你应该...

如果我的单片机的基准电压为3.3V,而外部的模拟量输入为0—5V我要对这 ...
具体要看单片机AD的测量电压范围。比如说,有的AD基准电压为2.5V,但是,输入电压可以是两倍或4倍的基准。你说的基准电压,应该是单片机的工作电压,一般AD不采用3.3V基准。如果外部信号超过了AD测量范围,可以采用电阻分压的方法,但是要注意阻抗匹配。最好是输入阻抗较高,而输出阻抗较低。如果信号源...

相似回答
大家正在搜