原创 基于Atmega8单片机的频率计

2008-3-21 12:42 4062 9 10 分类: MCU/ 嵌入式


实验目标
        频率计是我们经常会用到的实验仪器之一,本实验要使用单片机和计数电路及液晶器件来设计一个宽频的频率计。
期望达到10Hz-1.1G范围的频率精确测量。
实验电路图(初步方案)
1) 计数及显示电路:
点击看大图 
2)前置放大及分频电路:
设计设计测量频率的思路

        频率的测量实际上就是在1S时间内对信号进行计数,计数值就是信号频率。用单片机设计频率计通常采用两种办法,1)使用单片机自带的计数器对输入脉冲进行计数,或者测量信号的周期;2)单片机外部使用计数器对脉冲信号进行计数,计数值再由单片机读取。 

        由于单片机自带计数器输入时钟的频率通常只能是系统时钟频率的几分之一甚至几十分之一,因此采用单片机的计数器直接测量信号频率就受到了很大的限制。 

        本实验电路采用方式2,使用一片 74LS393四位双二进制计数器和Atmega8的T1计数器组成了24位计数器,最大计数值为16777215。如果输入信号经过MB501分频器进行64分频后再进行测量,则固定1S时基下最高测量频率为1073.741760Mhz。 

        为了方便得到准确的1秒钟测量闸门信号,我们使用了Atmega8的异步实时时钟功能,采用32.768Khz的晶振由TC2产生1秒钟的定时信号。

测量频率原理
 
        单片机打开测量闸门,即PB1输出高电平,同时TC2定时器启动。74LS393开始对输入脉冲进行计数,74LS393每计数达256时,Atmega8的T1计数器也向上计数1次。当1S 定时到达时,单片机产生中断,PB1输出低电平关闭测量闸门,然后Atmega8读取74LS393和T1的计数值,然后送LCD显示。
 
        由于1S的测量闸门时间在业余条件下不好测试,因此,实验程序中在LCD上同时显示实时时钟用于判断1S闸门时间的准确性。实验中,我使用CDMA手机上显示的GPS卫星精确时间进行比较。手机时间显示的最小单位是分钟,测量时一旦手机分钟值发生跳变,则立即记录下LCD显示的秒值,这样的话让频率计运行一段时间后,再多次记录下LCD显示的秒,就可以准确判断频率计的异步时钟是否准确。实验过程中,我让频率计走了10个小数左右,测量的1S时钟还是非常准确的。

频率测量源代码:
#include
#include
#include "lcd.h"
#include "bmp.h"

unsigned long counter;
unsigned char countlow;
unsigned char fre[]="00.000000";
unsigned char time[]="00:00:00";

#pragma interrupt_handler timer2_ovf_isr:iv_TIMER2_OVF
void timer2_ovf_isr(void)
{
unsigned char i;
//TCCR2=0;

PORTB &= ~0X02; //关闭闸门

//读取计数值
counter = TCNT1; //读取T/C1计数值(频率值的高16位)
counter = counter*256; //计算频率值的高16位
countlow = (PIND & 0b11000000)|(PINC & 0b00111111);
//读取计数值的低8位
counter = counter + countlow; //计算频率值

PORTD |= 0X01; //74LS393清零
TCNT1 = 0;

PORTD &= ~0X01; //关闭清零
TCNT2 = 0X80; //定时时间1秒

PORTB |= 0X02; //打开闸门

//实时时钟显示
time[7]++;

fre[0]=counter /10000000+0x30;
counter=counter %10000000;
fre[1]=counter /1000000+0x30;
counter=counter %1000000;
fre[3]=counter /100000+0x30;
counter=counter %100000;
fre[4]=counter /10000+0x30;
counter=counter %10000;
fre[5]=counter /1000+0x30;
counter=counter %1000;
fre[6]=counter /100+0x30;
counter=counter %100;
fre[7]=counter /10 + 0x30;
fre[8]=counter %10 + 0x30;

LCD_write_String(0,2,fre);
LCD_draw_map(14,2,Bmp003,7,14); //显示小数点
LCD_draw_map(62,2,MHz,22,14); //显示频率单位

if ( time[7] > (9+0x30) )
{
time[6] ++;
time[7] -= 10;
}
if ( time[6] > (5+0x30) )
{
time[4] ++;
time[6] -= 6;
}
if (time[4]> (9+0x30))
{
time[3]++;
time[4]-=10;
}
if (time[3] > (5+0x30))
{
time[1]++;
time[3]-=6;
}
if (time[1]>(9+0x30))
{
time[0]++;
time[1]-=10;
}
LCD_write_String(2,4,time);
LCD_draw_map(16,4,Bmp002,7,14); //显示“:”字符
LCD_draw_map(37,4,Bmp002,7,14);

}

/******************************************************************************/
void main(void)
{
unsigned char i;
OSCCAL=0xA3; // 8M系统内部时钟校准

//设置MCU的I/O口
DDRB |= LCD_RST | LCD_DC | LCD_CE | SPI_MOSI | SPI_CLK ;

DDRB |= 0x02; //计数闸门
DDRD |= 0X01; //74LS393清零
//DDRD |= 0X08; //LED
//DDRD &= ~0X20;
DDRC &= 0B11000000;
DDRD &= 0B00111111;

SPSR |= BIT(SPI2X); // 设置SPI时钟倍速
SPCR |= BIT(SPE)|BIT(MSTR); // 使能SPI接口,主机模式,4M时钟

LCD_init();
//LCD_clear(); // 清屏
LCD_draw_map(12,0,Bmp001,60,13);

ASSR = 1 <TCNT2 = 0X80; //定时时间1秒
TCCR2 = (1<TIMSK |= BIT(TOIE2); //允许TC2溢出中断

TCCR1B |= BIT(CS12)|BIT(CS11)|BIT(CS10); //时钟外部T1输入,上升源驱动

SEI();

while(1)
{

}
}



3310液晶显示源代码:



位图数据表
unsigned char Bmp001[]=
{
/*------------------------------------------------------------------------------
; 源文件 / 文字 : 频率计实验
; 宽×高(像素): 60×13
; 字模格式/大小 : 单色点阵液晶字模,纵向取模,字节倒序/120字节
; 数据转换日期 : 2004-9-23 17:39:05
------------------------------------------------------------------------------*/
0x20,0xFC,0xE0,0x3E,0xA8,0x26,0xFA,0x0A,0xEE,0x0A,0xFA,0x00,0x84,0x8C,0x54,0xA4,
0xD4,0xAE,0xD4,0xA4,0x54,0x8C,0x04,0x00,0x20,0xE2,0x04,0x00,0x20,0x20,0x20,0xFE,
0x20,0x20,0x20,0x00,0x10,0x0C,0x44,0x94,0x24,0x06,0xF4,0x04,0x04,0x14,0x0C,0x00,
0x42,0x7A,0x42,0xFE,0x20,0x90,0x28,0xA6,0x28,0x90,0x20,0x00,0x09,0x08,0x05,0x02,
0x09,0x08,0x05,0x02,0x01,0x02,0x0D,0x00,0x02,0x02,0x02,0x02,0x02,0x0F,0x02,0x02,
0x02,0x02,0x02,0x00,0x00,0x0F,0x04,0x02,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
0x01,0x09,0x09,0x09,0x05,0x03,0x01,0x03,0x05,0x09,0x01,0x00,0x02,0x0A,0x09,0x07,
0x08,0x0B,0x08,0x0B,0x0C,0x0B,0x08,0x00
};

unsigned char MHz[]=
{
/*------------------------------------------------------------------------------
; 源文件 / 文字 : MHz
; 宽×高(像素): 38×16
; 字模格式/大小 : 单色点阵液晶字模,纵向取模,字节倒序/76字节
; 数据转换日期 : 2004-9-27 14:27:15
------------------------------------------------------------------------------*/

//0x00,0xF8,0x30,0xC0,0x00,
//0x00,0x00,0xC0,0x30,0xF8,0x00,0x00,0xF8,0x80,0x80,0x80,0x80,0x80,0xF8,0x00,0x00,
//0x40,0x40,0x40,0xC0,0x40,0x00,

//0x00,0x1F,0x00,0x00,0x07,
//0x18,0x07,0x00,0x00,0x1F,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,
//0x10,0x1C,0x12,0x11,0x10,0x00

//0xF8,0x70,0xE0,0x10,0xC8,0x34,0xFA,
0x00,0xF8,0x30,0xC0,0x00,0xC0,0x30,0xF8,0x00,
0xF8,0x40,0x40,0x40,0x40,0xF8,0x00,0x20,0x20,0xA0,0x60,0x20,0x00,
//0x07,0x00,0x01,0x06,0x01,0x00,0x07,
0x00,0x07,0x00,0x01,0x06,0x01,0x00,0x07,0x00,
0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x04,0x06,0x05,0x04,0x04,0x00

};

unsigned char Bmp002[]=
{
/*------------------------------------------------------------------------------
; 源文件 / 文字 :":"
; 宽×高(像素): 7×14
; 字模格式/大小 : 单色点阵液晶字模,纵向取模,字节倒序/48字节
; 数据转换日期 : 2004-9-23 17:12:47
------------------------------------------------------------------------------*/
//0x00,0x00,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00
0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x00
};
unsigned char Bmp003[]=
/*------------------------------------------------------------------------------
; 源文件 / 文字 :"."
; 宽×高(像素): 4×16
------------------------------------------------------------------------------*/
//{0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00};
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00};
//{
/*------------------------------------------------------------------------------
; 源文件 / 文字 : 没有输入信号
; 宽×高(像素): 72×13
; 字模格式/大小 : 单色点阵液晶字模,纵向取模,字节倒序/144字节
; 数据转换日期 : 2004-9-23 17:16:17
--------------------------------------------------*/
/*
0x10,0xE2,0x74,0x10,0x68,0xDE,0x42,0x42,0xDE,0x20,0x20,0x00,0x84,0x44,0x24,0xF4,
0x9C,0x96,0x94,0x94,0xF4,0x04,0x04,0x00,0x68,0x5E,0xE8,0x48,0xD0,0x48,0xD4,0x12,
0xD4,0x08,0xD0,0x00,0x00,0x00,0x00,0x82,0x62,0x1C,0x60,0x80,0x00,0x00,0x00,0x00,
0x40,0xF0,0x0E,0x04,0x54,0x54,0x54,0x56,0x54,0x54,0x04,0x00,0x40,0x40,0x5E,0xD2,
0x52,0x52,0x52,0x52,0x5E,0x40,0x40,0x00,0x02,0x0F,0x00,0x08,0x08,0x05,0x02,0x02,
0x05,0x08,0x08,0x00,0x00,0x00,0x00,0x0F,0x02,0x02,0x02,0x0A,0x0F,0x00,0x00,0x00,
0x02,0x02,0x0F,0x01,0x0F,0x05,0x0F,0x00,0x03,0x08,0x0F,0x00,0x08,0x04,0x02,0x01,
0x00,0x00,0x00,0x01,0x02,0x04,0x08,0x00,0x00,0x0F,0x00,0x00,0x0F,0x05,0x05,0x05,
0x05,0x0F,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x09,0x09,0x09,0x07,0x00,0x00,0x00
};
*/
字符数据表


延时函数:

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户141311 2009-5-19 15:53

看看,也打算用AVR
相关推荐阅读
用户1184391 2008-04-21 21:52
常用零件PCB封装图解
 134567...
用户1184391 2008-04-17 23:10
最常用的电子元器件
常用元器件的识别 电阻 电阻在电路中用“R”加数字表示,如:R1表示编号为1的电阻.电阻在电路中的主要作用为 分流、限流、分压、偏置等. 1、参数识别:电阻的单位为欧姆(Ω),倍率单位有:千欧(KΩ)...
用户1184391 2008-04-17 23:00
二级管的分类及特性
二级管的分类及特性 一、根据构造分类   半导体二极管主要是依靠PN结而工作的.与PN结不可分割的点接触型和肖特基型,也被列入一般的二极管的范围内.包括这两种型号在内,根据PN结构造面的特点,把晶体二...
用户1184391 2008-04-07 15:35
基于单片机的相位测量的一种方法
测量原理:将相位差转换成时间,然后用单片机来测量时间间隔。被测信号e1和e2经整形电路形成方波,方波的上升沿和下降沿分别与振荡信号的正负过零点对应。整形电路的输出均分为2路,一路送异或门,异或门输出矩...
用户1184391 2008-04-02 21:59
各大公司电子类招聘题目精选(单片机)
1、简单描述一个单片机系统的主要组成模块,并说明各模块之间的数据流流向和控制流流向。简述单片机应用系统的设计原则。(仕兰微面试题目)2、画出8031与2716(2K*8ROM)的连线图,要求采用三-八...
用户1184391 2008-04-02 21:51
单片机C51语言学习资料
 基础知识:单片机编程基础单片机的外部结构:1、 DIP40双列直插;2、 P0,P1,P2,P3四个8位准双向I/O引脚;(作为I/O输入时,要先输出高电平)3、 电源VCC(PIN40)和地线GN...
EE直播间
更多
我要评论
1
9
关闭 站长推荐上一条 /3 下一条