Forum: Compiler & IDEs Programmierung Capture Schrittweite


von Marc Z. (marc567)


Lesenswert?

Hallo zusammen,
ich möchte mit meinem Mega16 (@16MHZ)die Schrittweite eines Signals 
einlesen. 15khz (bei arithm. Mittel=0).
Leider will das Ganze nicht so wie ich es will.
Hat mir jemand einen Tip woran es liegen könnte?
Habe mal das Grundgerüst für das Capture aus meiner Software 
rausgezogen.
Vielen Dank




#include <inttypes.h>    //Header includen als Bibliotheken
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <string.h>
#include <avr/eeprom.h>

volatile double rising = 0;    //Ergibt sich aus den beiden 8bit 
Variablen risinglow/risinghigh
volatile uint8_t risinglow = 0;    //8bit Variable zum Register auslesen
volatile uint8_t risinghigh = 0;  //8bit Variable zum Register auslesen
volatile long double risingtemp = 0;

volatile double falling = 0;    //Ergibt sich aus den beiden 8bit 
Variablen fallinglow/fallinghigh
volatile uint8_t fallinglow = 0;  //8bit Variable zum Register auslesen
volatile uint8_t fallinghigh = 0;  //8bit Variable zum Register auslesen
volatile long double fallingtemp = 0;

volatile uint16_t Overflows = 0;
volatile uchar status=0;
volatile uchar fertig=0;

int main (void)
{
//Capture Input
PORTD &= ~BIT6;    //Pullup aus
DDRD &= ~(1<<PD6);  //Eingang
InitTimer();     // SystemClock
sei();      // Freigabe Interrupts

if (ModulEingang1)
  {  fertig=0;
    status=0;
    //Overflows=0;
    lcd_cls();
    double long countstemp;
    double long countstemp1;

    if (fertig==1)
    {
    countstemp = (fallingtemp-risingtemp);//Schrittweite
    countstemp = (countstemp*0.0625);  //in Mikrocontrollertakten
    countstemp1 = (risingtemp-fallingtemp);

    countstemp1 = (countstemp1*0.0625);  //in Mikrocontrollertakten

      lcd_cls();
        lcd_outdouble(countstemp);
        lcd_outdouble(countstemp1);
      Overflows=0;
      wait(10000);
      fertig=0;
      status=0;
    }
  }
ISR(TIMER1_CAPT_vect)
{
      if (fertig==1){return;}
      if ((PIND & (1<<PIND6))&&(status==0))
                     {
                       risinglow=ICR1L;
      risinghigh=ICR1H;
      rising = risinglow;
      rising += (risinghigh<<8);
risingtemp = (long double)(rising+(Overflows*65536));
      //Overflows=0;
      TCCR1B = 0x81; //on falling edge, noise canceler, @16MHZ
      status=1;


         }
      else
      {
                       fallinglow=ICR1L;
      fallinghigh=ICR1H;
      falling = fallinglow;
      falling += (fallinghigh<<8);
 fallingtemp = (long double)(falling+(Overflows*65536));
      TCCR1B=0xC1;
      //Overflows=0;
      fertig=1;

            }

}

ISR(TIMER1_OVF_vect)
{
  Overflows++;
}

void InitTimer()
{
  TCCR0 = 0x01;   // no prescale -->16MHZ
  TCCR1A = 0x00;
  TCCR1B = 0xC1; //Noise Canceler on, trigger on rising edge, no 
prescale (16MHZ)
  TIMSK |= (1<<TOIE0)|(1<<TICIE1)|(1<<TOIE1);        // Timer0 OverFlow 
Interrupt Enable  (BIT0), Timer1:Interrupt wird ausgelöst wenn ICF1 Flag 
gesetzt wird (edge detector hat rising edge erkannt)

}

von Johannes M. (johnny-m)


Lesenswert?

Bitte beim nächsten Mal den Code richtig formatieren!

> PORTD &= ~BIT6;    //Pullup aus
Das sieht schonmal verdächtig aus. Wie ist "BIT6" definiert?

> risinglow=ICR1L;
> risinghigh=ICR1H;
> rising = risinglow;
> rising += (risinghigh<<8);
Das ist Murks. Lass die 16-Bit-Zugriffe doch den Compiler machen. 
Schmeiß die ***low und ***high weg und schreib einfach
1
rising = ICR1;

Abgesehen davon kennt der AVR-GCC weder double noch long double (bzw. 
double kennt er zwar, aber es ist identisch mit float, also nur 32 Bit 
breit; 64-Bit-Gleitkomma gibt's im AVR-GCC nicht). Schau Dir bitte mal 
den Artikel zum Thema Festkommaarithmetik an. Ich bin überzeugt 
davon, dass Du für Dein Vorhaben mit Sicherheit keine 
Gleitkommaverrenkungen brauchst.

Zudem wendest Du Bitschiebe-Operationen auf Deine double-Variablen an. 
Das geht garantiert schief! Bitschiebereien sind generell nur für 
Ganzzahl-Werte (integer) definiert.

von Johannes M. (johnny-m)


Lesenswert?

Fällt mir grad noch auf: Wo ist der Handler (ISR) für den Timer 0 
Overflow Interrupt?

von Marc Z. (marc567)


Lesenswert?

Hallo,
erstmals tausend dank für die Hilfe.

Hier der Timer0 Overflow:

ISR(TIMER0_OVF_vect)
{
  SystemClk++;

  if (SystemClk>=38)
    {
    SystemClk=0;
    DoForEver10ms=1;
    } // 38 * 256usec @16MHz -> 9,728msec
}


Bit6 ist wie folgt definiert:
#define BIT6  0x40

Ich probier das gleich mal aus - mit dem Register ICR1....
Vielen Dank nochmal....

von Johannes M. (johnny-m)


Lesenswert?

Marc Ziegl wrote:
> Ich probier das gleich mal aus - mit dem Register ICR1....
> Vielen Dank nochmal....
Das mit dem ICR ist aber Dein allerkleinstes Problem...

von Marc Z. (marc567)


Lesenswert?

...wie meinen?

von Johannes M. (johnny-m)


Lesenswert?

Marc Ziegl wrote:
> ...wie meinen?
Will sagen, dass das mit dem ICR noch nicht mal für die Funktion der 
ganzen Sache relevant ist, weil es so, wie es in Deinem Code steht (bis 
auf die double-Geschichten) noch nicht mal ein Fehler ist, sondern 
lediglich eine vermeidbare umständliche Vorgehensweise ist. Die 
Behandlung der anderen genannten Probleme ist da eindeutig zu 
priorisieren.

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.