您当前的位置:五五电子网电子知识单片机-工控设备AVR单片机ATMEGA8单片机频率计程序与电路图 正文
ATMEGA8单片机频率计程序与电路图

ATMEGA8单片机频率计程序与电路图

点击数:7266 次   录入时间:03-04 11:49:30   整理:http://www.55dianzi.com   AVR单片机
原理上采用32.768K外部晶振产生异步时钟信号 ,作为M8定时器2的时钟源,设定1024的预分频,可以得到TCNT2溢出的精确时间为1s,在溢出中断时控制74ls00与非门进而控制被测信号的通断,累计1s 内计数器获得的值,经过简单的运算则可获得被测信号的频率

M8 采用内部 8M 内部RC震荡 工作模式 , 电路采用74ls393 对被测信号进行预分频,相当于扩张T1计数器的位数,T1 为16位,74ls393为8位,扩展后为24位,T1不溢出的话 最高可测 16.777216M ,溢出则累计中断次数然后进行累加即可。(另外添加74ls393进行预分频的目的是为了解决T1引脚时钟信号不宜大于 单片机 工作频率的二分之一的问题)

目前测频 4M 已经成功通过,由于没有函数信号发生器,所以其他高频还没有做测试

PCB原理图




/////////////////////////////以下为程序, 只有一个文件 main.c /////////////////////////////////

#include <avr/io.h>
#include <avr/iom8.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <stdio.h>

/*----------------------常用参数定义-------------------*/

#define P0 0
#define P1 1
#define P2 2
#define P3 3
#define P4 4
#define P5 5
#define P6 6
#define P7 7

#define FREQ 8
#define uint unsigned int
#define uchar unsigned char

/*----------------------某些端口操作-------------------*/

#define SET_DOOR PORTB|=_BV(P1)
#define CLR_DOOR PORTB&=~_BV(P1)

#define SET_CLEAR PORTB|=_BV(P2)
#define CLR_CLEAR PORTB&=~_BV(P2)

/*----------------------1602定义-------------------*/

#define SET_LCD_RS PORTD|=_BV(P2)
#define CLR_LCD_RS PORTD&=~_BV(P2)

#define SET_LCD_RW PORTD|=_BV(P3)
#define CLR_LCD_RW PORTD&=~_BV(P3)

#define SET_LCD_E PORTD|=_BV(P4)
#define CLR_LCD_E PORTD&=~_BV(P4)

#define SET_74LS595_SHIFT PORTB|=_BV(P0)
#define CLR_74LS595_SHIFT PORTB&=~_BV(P0)

#define SET_74LS595_DI PORTD|=_BV(P6)
#define CLR_74LS595_DI PORTD&=~_BV(P6)

#define SET_74LS595_CLK PORTD|=_BV(P7)
#define CLR_74LS595_CLK PORTD&=~_BV(P7)

void LCD_ON(void);     //启动LCD
void LongConvertToChar(unsigned long WD);
void LCDInit(void);
void WritEDAtaLCD(unsigned char WDLCD);
void WriteCommandLCD(unsigned char WCLCD);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y,unsigned char *DData);
void WritEDAtaTo595(unsigned char WDLCD);

const unsigned char Owner[] = {"Hello World !!!"};
const unsigned char uctech[] = {"INPUT FREQUENCE:"};
const unsigned char   Init[] = {"Initialization."};
unsigned char net[16] =         {"Axin & Cornsoup"}; 
unsigned char Net_Pointer=0;//net[] 的指针

unsigned char Timer1_Counter_H=0;
unsigned char Timer1_Counter_L=0;
unsigned long Frequence=0;
unsigned char T2_OV_Time=1; //T2溢出对应的时间
unsigned char T1_OV_Times=0; //T1溢出次数


/*----------------------串口定义-------------------*/

unsigned char SetPrintfConvertMode=0; //使用printf作其他转换,并非输出到UART

void Uart_Init(void);

int System_putchar(char c, FILE *stream);
int System_getchar(FILE *stream);

FILE mystd = FDEV_SETUP_STREAM(System_putchar, System_getchar,_FDEV_SETUP_RW);

/*----------------------常用函数定义------------------*/

void delay_nms(unsigned int ms)                //N ms延时函数
{
uint i;
for(i=0;i<ms;i++)
   _delay_loop_2(FREQ*250);
}

/*----------------------系统初始化函数定义------------------*/

void IO_INIT(void);


/////////////////////////////////////////////////////////////////


int main(void) 
{
wdt_dISAble();
IO_INIT();
Uart_Init();
LCD_ON();                    //初始化 LCD1602 并显示制作者信息
delay_nms(1500);
DisplayListChar(0, 0, uctech); //输出英文 "Input Frequence:" 到LCD1602 第一行

DisplayListChar(0, 5, Init);    //显示稍等

CLR_DOOR;                       //关闭阀门
_delay_loop_2(5);
SET_CLEAR;
_delay_loop_2(5);               //清空74ls393数据
CLR_CLEAR;

TCNT1H=0;
TCNT1L=0;                        //清空T1计数器

ASSR=_BV(AS2);                          //允许异步时钟
TCCR2=_BV(CS22)|_BV(CS20);        
TCCR1B=_BV(CS12)|_BV(CS11);            //外部T1引脚输入 下降沿有效 (一定要下降沿)
TIMSK=_BV(TOIE1)|_BV(TOIE2);           //允许溢出中断

sei(); 

while(1); 
}


/*----------------------系统初始化函数实体------------------*/

void IO_INIT(void)
{
DDRB|=0x0f;
PORTB&=0x0f;
DDRC|=0x00;
PORTC&=0x00;
DDRD|=0xdc;
PORTD&=0xdc;
}

/*----------------------系统中断函数实体-----------------*/

ISR(TIMER1_OVF_vect) //定时器1溢出中断 
{
T1_OV_Times++;
}


ISR(TIMER2_OVF_vect) //定时器2溢出中断 

if(T2_OV_Time==2)
   {
    CLR_DOOR;

    Timer1_Counter_L=TCNT1L;   //读取TCNT1数据要按照顺序,先低8位后高8位
    Timer1_Counter_H=TCNT1H;
  
    Frequence=((unsigned long)Timer1_Counter_H<<16)|((unsigned long)Timer1_Counter_L<<8)|((PINC&0x3c)>>2)|((PINC&0x03)<<6)|(PINB&0x30);
   
    if(T1_OV_Times!=0)        //其实这个是多余的,这里目的是测量16.7M 以上的频率 不过我们测量的频率不可能达到这个
     {
      Frequence+=(unsigned long)0xffff*0xff*T1_OV_Times;
      T1_OV_Times=0;
     }
   
    //printf("\n\NTCNT1H: 0X%X TCNT1L: 0X%x",Timer1_Counter_H,Timer1_Counter_L);

[1] [2]  下一页


本文关键字:单片机  程序  电路图  AVR单片机单片机-工控设备 - AVR单片机