Forum: Mikrocontroller und Digitale Elektronik Frequenzmessug mit ATMEGA 168


von Peter (Gast)


Lesenswert?

Hallo Forum

Ich möchte mittels eines Atmega 168 eine Frequenzmessung eines 
Rechtecksignals realisieren. Meiner meinung nach eignet sich der capture 
modes des Timers1 am besten dazu. Das Programm funktioniert im debugger 
auch schon. Bei einer fallenden flanke wird der capture interrupt 
ausgelöst und der timerwert gespeichert. überläufe des Timers werden 
auch berücksichtigt. Soweit müsste alles unktionieren
Wenn ich allerdings das programm auf den uc spiele und ein pwm signal am 
port B0 anlege kommt nur müll raus. Ich hoffe es kann mir jemand helfen
Die Routine zur Displayausgabe habe ich seperat getested müsste auch 
funktionierne. Villeciht kann sich jémand die Mühe machen und das 
Programm mal anschauen, währe echt nett
Danke

mfg




//*********** 
Includes***************************************************
#include <avr\io.h>
#include <avr\interrupt.h>
#include  <util\delay.h>



//********************************************************************** 
**


//*********** Systemkonstanten******************************************
#define F_CLOCK    2E7     // 20MHz CPU Takt
#define Zahn    6     // 6 Grad Zahn Teilung


//**********************************************************************


//*********** Globale Variablen******************************
double test,b_f;// b_f=1 wenn negative flanke
long int ueberlauf=0;
double init=0; //initialisierung bei 1.neg Flanke
unsigned int   counter=0;
double  counterold=0; //Zählerstand N-1.fallende Flanke
double counternew=0; //Zählerstand N fallende Flanke
double diff=0;  //Differnez Zählerstand N und Zählerstand N-1
double cmax=65535; // max Zähler des 16 Bit counters
double help=0;//Hilfsgrösse
double flanke=0;//Hilfsgrosse für dsp
long Frequenz=0;
long zahl=0;
unsigned int ICR1Htemp;
unsigned int ICR1Ltemp;
//**********************************************************************

//*********** Interrupt für fallende 
Flanke******************************
ISR(TIMER1_CAPT_vect)

{


cli(); //intterrupt spreeren
//PORTB ^= 0xFF;



counter=ICR1H*0x100+ICR1L;
//counter=ICR1H*0x100+ICR1L;//16 Bit Verrechung H und L Reg Timer 1 
capure Register






    if(b_f==0) //Erkennung 1. Flanke

    {



    counterold=counter;//Zählerstand merken
    ueberlauf=0;
    b_f=1;
    }

    //if(b_f==1)
    else
    {
    counternew=counter;//Zählerstand merken
    //diff=counternew-counterold;



    //help=(ueberlauf-1)*cmax;
    diff=cmax-counterold+(ueberlauf-1)*cmax+counternew;//Berechnungsformel
    //b_f=0;
    ueberlauf=0;
    counterold=counternew;

    flanke=1;








  //  diff=counter-counterold;


    }







 sei();// interrups global zulassen
}


//********************************************************************** 
**


//***********Interrupt für Zähler 
Überlauf********************************
ISR( TIMER1_OVF_vect)
{
cli(); //intterrupt spreeren
ueberlauf++;


//if(PORTC==0x00)
//{
//PORTC=0xFF;

//}
//else
//{
//PORTC=0x00;
//}

 sei();// interrups global zulassen

}
//********************************************************************** 
*



//*********************Display***********************************


//*********************Display***********************************



#define   F_CPU 20000000


#define sbi(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))
#define cbi(ADDRESS,BIT) ((ADDRESS) &= ~(1<<(BIT)))
#define outp(VAL,ADRESS) ((ADRESS) = (VAL))
#define inp(VAL) (VAL)


//////////////////////////////////////////////////////////////////////// 
/////
// allgemeine-Funktionen
//---------------------------------------------------------------------- 
-----
//  wait_ms(..) - Wartet einige Millisekunden
//  Die Dauer ist nicht kalibriert.
//  PE:  miliSec=Anzahl der zu wartenden Millisekunden
//---------------------------------------------------------------------- 
-----
void wait_ms(int miliSec)
{
  _delay_loop_2( 1*(F_CPU/(1000/4)) * miliSec);  // 4 Zyklen 
arteschleife
}
void wait_us(int mikroSec)
{
  _delay_loop_2( 1*(F_CPU/(1000000/4)) * mikroSec);  // 4 Zyklen 
arteschleife
}
//////////////////////////////////////////////////////////////////////// 
//////
//  LCD-Funktionen für myAVR-Board + myAVR-LCD
//  4-BitModus an PortD Bit 4-7
//  PortD Bit 2 = RS, high=Daten, low=Kommando
//  PortD Bit 3 = E, high-Impuls für gültige Daten
//---------------------------------------------------------------------- 
-----
//  lcd_send(..) - sendet ein Byte an LCD im 4-Bit-Modus
//  RS muss vorher richtig gesetzt sein
//  PE:  data=zu sendendes Byte
//---------------------------------------------------------------------- 
-----
void lcd_send(char data)
{
  // aktuelles RS ermitteln
  char rs=PORTD;
  rs&=4;
  // High-Teil senden
  char tmp=data;
  tmp&=0xf0;
  tmp|=rs;
  PORTD=tmp;
  // Schreibsignal
  sbi(PORTD,3);
  cbi(PORTD,3);
  // Low-Teil senden
  tmp=data;
  tmp&=0x0f;
  tmp*=16;
  tmp|=rs;
  PORTD=tmp;
  // Schreibsignal
  sbi(PORTD,3);
  cbi(PORTD,3);
  // verarbeiten lassen
  wait_ms(1);
}
//---------------------------------------------------------------------- 
-----
//  lcd_cmd(..) - sendet ein Kommando an LCD
//  PE:  cmd=Kommando-Byte
//---------------------------------------------------------------------- 
-----
void lcd_cmd(char cmd)
{
  cbi(PORTD,2);    // RS löschen = Kommando
  lcd_send(cmd);    // senden
}
//---------------------------------------------------------------------- 
-----
//  lcd_write(..) - sendet ein Zeichen (Daten) an LCD
//  PE:  text=Zeichen
//---------------------------------------------------------------------- 
-----


//---------------------------------------------------------------------- 
-----
//  lcd_write(..) - sendet ein Zeichen (Daten) an LCD
//  PE:  text=Zeichen
//---------------------------------------------------------------------- 
-----
void lcd_write(char text)
{
  sbi(PORTD,2);    // RS setzen = Daten
  lcd_send(text);    // senden
}
//---------------------------------------------------------------------- 
-----


//  lcd_home(..) - Cursor auf Position 1,1
//---------------------------------------------------------------------- 
-----
void lcd_home()
{
  lcd_cmd(0x02);
  wait_ms(2);      // warten
}
//---------------------------------------------------------------------- 
-----
//  lcd_clear(..) - löscht die Anzeige im LCD
//---------------------------------------------------------------------- 
-----
void lcd_clear()
{
  lcd_cmd(0x01);
  wait_ms(2);      // warten
}
//---------------------------------------------------------------------- 
-----
//  lcd_on(..) - schaltet das LCD an
//---------------------------------------------------------------------- 
-----
void lcd_on()
{
  lcd_cmd(0x0E);
}
//---------------------------------------------------------------------- 
-----
//  lcd_off(..) - schaltet das LCD aus
//---------------------------------------------------------------------- 
-----
void lcd_off()
{
  lcd_cmd(0x08);
}
//---------------------------------------------------------------------- 
-----
//  lcd_goto(..) - setzt die Cursorposition
//   PE:  row = Zeile 1..2
//    col = Spalte 1..16
//---------------------------------------------------------------------- 
-----
void lcd_goto(int row, int col)
{
  row--;        // Null-basierend
  row&=0x01;      // sicherheitshalber
  row*=0x40;      // Zeile nach Bit 6 bringen
  col--;        // Null-basierend
  col&=0x0f;      // sicherheitshalber
  char tmp=row|col;
  tmp|=0x80;      // Cursor setzen
  lcd_cmd(tmp);    // senden
}
//---------------------------------------------------------------------- 
-----
//  lcd_init(..) - Schaltet die Ports und Initialisiert das LCD
//---------------------------------------------------------------------- 
-----
void lcd_init()
{
  // Port D = Ausgang
  DDRD=0xff;
  PORTD=0;
  // warten bist LCD-Controller gebootet
  wait_ms(50);
  // SOFT-RESET
  PORTD = 0x30;  //0b00110000;
  sbi(PORTD,3);
  cbi(PORTD,3);
  wait_ms(5);
  PORTD = 0x30;  //0b00110000;
  sbi(PORTD,3);
  cbi(PORTD,3);
  wait_us(100);
  PORTD = 0x30;  //0b00110000;
  sbi(PORTD,3);
  cbi(PORTD,3);
  wait_ms(5);

  // 4-BitModus einschalten
  PORTD=0x20;
  // Schreibsignal
  sbi(PORTD,3);
  cbi(PORTD,3);
  wait_ms(5);

  // ab hier im 4-Bit-Modus
  lcd_cmd(0x28);    // Funktions-Set: 2 Zeilen, 5x7 Matrix, 4 Bit
  //lcd_off();
  lcd_cmd(0x06);    // Entry Mode
  lcd_on();
  lcd_clear();
}













//********************************************************************** 
***



int main(void)
{

unsigned long i;   //lokale Zähler Variable
unsigned long rest=0;
//unsigned long anz=0;
i=0;
//test=9999;
DDRC=0xFF;
//PORTC=0x00;



b_f=0;  //flanken erkennung init
ueberlauf=0;//
diff=0;
counterold=0; //Zählerstand N-1.fallende Flanke
counternew=0; //Zählerstand N fallende Flanke
Frequenz=0;
long anz;


//---------------------Timer 1 Konfiguration----------------------------

  TCCR1B = 0x07;  // capture neg. Flanke und prescaler 1



    TIMSK1 = 0x21;  // interrupt Enable ovfer flow Enable &Capture 
Enable
  sei();// interrups global zulassen



//---------------------------------------------------------------

    wait_ms(200);
lcd_init();

lcd_write(' ');
lcd_write(' ');
lcd_write(' ');
lcd_write(' ');
lcd_write(' ');
lcd_write(' ');
lcd_write(' ');
lcd_write(' ');
lcd_write(' ');
lcd_write(' ');
lcd_write(' ');
lcd_write('H');
lcd_write('r');
lcd_home();
lcd_write ('0');
 PORTC=0xFF;



  while( 1==1 )
  {

wait_ms(1000);
if(PORTC==0x00)
{

PORTC=0xFF;

}
else
{

PORTC=0x00;

}






      if(flanke==1)

      {
        //Frequenz=F_CLOCK*cmax/diff;
        Frequenz=F_CLOCK*cmax/diff;
        rest=Frequenz;
        for(i=1000000;i>0;i/=10)
          {

            anz=rest/i;
            rest %=i;

            if(rest!=zahl)
            {


              lcd_write (anz +'0');
              //wait_ms(200);


            }



            }
          lcd_home();
          flanke=0;
          lcd_clear();
          }






}

}

von Werner A. (homebrew)


Lesenswert?

Es reicht auch in einem Forum zu posten. Hier sollten nur fertige Codes 
sein...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.