my_avr 发表于 2008-3-14 17:47:31

搞了两天,终于可以用M8的模拟比较器实现频率测量[共享]

先说说问题所在:直接用M8内部的模拟比较器进行比较的话,在阈值电压处老出现多次跳变,没办法,只能采用滞回比较器.想了个法子,把M8的内部比较器和另外一个IO实现了滞回比较器.
电路图:
1http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_230795.JPG

/*************************************************************************
*                     AnalogCompa.h
*文件说明:模拟比较器相关的头文件
*编写作者:my_avr
*编写时间:2008年3月13日
**************************************************************************/
#ifndef _ANALOGCOMPA_H_
#define _ANALOGCOMPA_H_ 1

extern volatile unsigned int Pulse;
extern volatile unsigned int Timer;
extern volatile unsigned int Frequency;

extern void AnalogCompaInit(void);


#endif

/**********************************End of file*****************************/


/*************************************************************************
*                  AnalogCompa.c
*文件说明:模拟比较器的初始化程序和测试程序。
                   当AIN0(+)的电压大于AIN1(-)的电压时,
                   模拟比较器的输出(ACO)为高电平,可以选择该电平触发中断的方式:
                   ACIS1   ACIS0
                     0       0                比较器输出变化即可产生中断
                     0       1                保留
                     1       0                比较器输出的下降沿产生中断
                     1       1                比较器输出的上升沿产生中断
*编写作者:my_avr
**************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>

#include "AnalogCompa.h"

volatile unsigned int Pulse;
volatile unsigned int Timer;
volatile unsigned int Frequency;

/************************************************************************
*函数名称:AnalogCompaInit()
*函数功能:初始化模拟比较器
*输入参数:无
*输出参数:无
*编写作者:my_avr
*编写时间:2008年3月13月
*相关说明:触发中断方式为方式0,即比较器输出的电平变化产生中断
*************************************************************************/
void AnalogCompaInit(void)
{
        DDRD&= ~((1<<PD7)|(1<<PD6));                                //AIN为输入
        PORTD &= ~((1<<PD7)|(1<<PD6));                                //AIN上拉电阻关闭
        DDRD|= (1<<PD5);
        PORTD &= ~(1<<PD5);
       
        SFIOR &= (~(1<<ACME));                                                //模拟比较器的负极连接AIN1
        ACSR|= (1<<ACI);                                                        //先清除中断标志位
        ACSR&= ~((1<<ACBG)|(1<<ACIS0)|(1<<ACIS1));//设定工作方式
        ACSR|= (1<<ACIE);                                                        //允许模拟比较器中断
       
        Pulse   = 0;
        Timer   = 0;
        Frequency = 0;
}

/************************************************************************
*函数名称:SIGNAL()
*函数功能:模拟比较器中断处理函数
*输入参数:无
*输出参数:无
*编写作者:my_avr
*编写时间:2008年3月13月
*相关说明:
*************************************************************************/
SIGNAL(SIG_COMPARATOR)
{
        if ((ACSR & (1<<ACO)) > 0)
        {
                PORTD |= (1<<PD5);
        }
        else
        {
                PORTD &= ~(1<<PD5);
        }
       
        Pulse ++;
       
        if (Timer == 0)
        {
                Timer   = 100;                        //测量1秒钟
                Frequency = Pulse;
                Pulse   = 0;
        }
}



/*******************************End of file********************************/



/*************************************************************************
*                        main.c
*文件说明:主文件
*编写作者:my_avr
*编写时间:2008年3月13日
**************************************************************************/

#include <avr/io.h>
#include <avr/interrupt.h>

#include "AnalogCompa.h"
#include "UART.h"

volatile unsigned char DelayTimer;

/********************************************************************
*函数名称:void TimerInit(void)
*函数功能:初始化定时时钟,T2,CTC模式,10ms自动重载
*输入参数:无
*返回参数:无
*编写作者:my_avr
*编写时间:2007年8月13日
*相关说明:
********************************************************************/
void TimerInit(void)
{
        TCNT2= 0x00;
        OCR2   = 77;
        TIFR|= (1<<OCF2);                                                        //清匹配中断标志位
        TIMSK |= (1<<OCIE2);                                                //允许匹配中断
        TCCR2= (1<<WGM21)|(1<<CS20)|(1<<CS21)|(1<<CS22);        //1024分频,CTC模式
        /*
                Fi = F_CPU(8000) / (OCR0(77+1) * n(1024) ) = 0.1KHz
                Ti = 1/Fi = 1/0.1 = 10ms
        */
}

/**********************************************************************
*函数名称:SIGNAL(SIG_OUTPUT_COMPARE2)
*函数功能:T2匹配中断函数,中断一次给延时变量减一
*输入参数:无
*返回参数:无
*编写作者:my_avr
*编写时间:2008年3月13月
*相关说明:
**********************************************************************/
SIGNAL(SIG_OUTPUT_COMPARE2)
{
        if (Timer > 0)
        {
                Timer--;
        }
       
        if (DelayTimer > 0)
        {
                DelayTimer--;
        }
}

/************************************************************************
*函数名称:main()
*函数功能:测试函数
*输入参数:无
*输出参数:无
*编写作者:my_avr
*编写时间:2008年3月13月
*相关说明:
*************************************************************************/
int main(viod)
{
        unsigned char temp;
       
        DDRB       = 0xFF;
       
        DelayTimer = 150;
       
        AnalogCompaInit();
        TimerInit();
        UARTInit();
       
        sei();                                        //打开全局中断
       
        while(1)                                //循环等待中断
        {
                if (DelayTimer == 0)
                {
                        DelayTimer = 150;
                       
                        cli();
                        temp = (unsigned char) Frequency;
                        sei();
                       
                        PutByte(0xAA);
                        PutByte(ACSR);
                        PutByte(temp);
                }
        }
}

/******************************End of file********************************/

my_avr 发表于 2008-3-14 17:49:13

有另外一个文件是串口发送的程序,很简单的,就不发上来了.包含几个函数
UARTInit();
PutByte();

my_avr 发表于 2008-3-14 17:50:48

注意电路的AIN0,AIN1,PD5处的电路,其实是一个经典的滞回比较器的电路

j805 发表于 2008-3-14 18:09:38

最高可以测多高的频率????

my_avr 发表于 2008-3-14 18:14:47

这个电路主要目的是为了测量工频
主要目的是展示怎么处理缓慢变化的交流信号及其测量

moouse 发表于 2012-11-8 06:57:04

这个要顶一下

Lauchael 发表于 2014-2-22 12:45:51

Marking,谢谢分享。

xou822 发表于 2014-2-22 19:15:04

谢谢分享   
页: [1]
查看完整版本: 搞了两天,终于可以用M8的模拟比较器实现频率测量[共享]