At90Usb interrupt

OP #1338296
Lesenswert?

Hallo,

ich probiere derzeit einen Messwert vom ADC über USB an den PC zu 
bringen. Es klappt auch so weit, doch irgendwie läßt sich der Interrupt 
nicht aktivieren, so dass ich nie abwarten kann, bis die Messung fertig 
ist.
Ich glaube das ist das Problem, weil ich immer zweimal auf den Knopf 
drücken muss am PC bis ich die richtige Zahl habe.
In main() mache ich eine dummy-Messung:
//für ADC
  //SREG |= (1<<I);
  sei();

  ADMUX |=(1<<REFS0)|(1<<REFS1);
  ADCSRA |= (1<<ADEN)|(0<<ADATE)|(1<<ADIE);//<<--hier ist das Problem

  ADCSRB |=(0<<ADTS0)|(0<<ADTS1)|(0<<ADTS2);
  DIDR0 |=(1<<ADC0D);
  ADMUX |=(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3)|(0<<MUX4);

  ADCSRA |=(1<<ADSC);

  while (ADCSRA & (1<<ADIF)){}
  uint8_t LB;
  uint8_t HB;
  LB=ADCL;
  HB=ADCH;

ich kann meinen avr nur an usb anmelden, wenn ich (1<<ADIE) weglasse.
Ich brauch es aber für die Schleife...

Wo ist denn das Problem? SREG|=(1<<I) mag er auch nicht.

danke

Markus
OP #1338334
Lesenswert?

Ok, Quellcode: Es ist die Firmware von Salewski... In Main() mache ich 
eine Dummymessung, doch wenn ich ADIE einschalte...dann geht nichts mehr 
mit USB. Den zweiten Kommentar habe ich nicht ganz verstanden... 
entscheiden? Für was?

int
main(void)
{
  //für ADC
  //SREG |= (1<<I);
  sei();

  ADMUX |=(1<<REFS0)|(1<<REFS1);
  ADCSRA |= (1<<ADEN)|(0<<ADATE)|(1<<ADIE);

  ADCSRB |=(0<<ADTS0)|(0<<ADTS1)|(0<<ADTS2);
  DIDR0 |=(1<<ADC0D);
  ADMUX |=(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3)|(0<<MUX4);

  ADCSRA |=(1<<ADSC);

  //while (ADCSRA & (1<<ADIF)){}
  uint8_t LB;
  uint8_t HB;
  LB=ADCL;
  HB=ADCH;
  //ADCSRA |=(1<<ADSC);

  cli();
  CLKPR = (1<<7);
  CLKPR = 0; // clock prescaler == 0, so we have 16 MHz mpu frequency 
with our 16 MHz crystal
  USART_Init();
  USART_WriteString("\r\n------------------------------------------------- 
---------\r\n");
  UsbDevLaunchDevice(false);
  // UsbDevWaitStartupFinished(); // no reason to wait
  blinkforever();
  return 0;
}

UsbDevFillEP1FIFO(void)
{
  if UsbDevTransmitterReady()
  {
   uint8_t LB;
   uint8_t HB;
   ADCSRA |=(1<<ADSC);
   while (ADCSRA & (1<<ADIF)){}
   LB=ADCL;
   HB=ADCH;

    UsbDevClearTransmitterReady();
    UsbDevClearNAK_ResponseInBit();
    //UsbDevSelectEndpoint(1);
    UsbDevWriteByte(LB);
    UsbDevWriteByte(HB);
    UsbDevSendInData();
  }
}
Gast #1338339
Lesenswert?

Das Bit ADIE gibt den ADC-Interrupt frei. Dadurch springt der Controller 
beim Auftreten des auslösenden Ereignisses in die ISR. Eine Abfrage, ob 
das ADIF-Flag gesetzt wurde, kann nichts bringen, da zwischenzeitlich 
die ISR angesprungen wurde. Die fehlt aber scheinbar in deinem Programm.
Eine fehlende ISR bringt den Effekt, dass der Controller immer versucht, 
in die ISR zu springen, da das ADIF-Bit nicht zurückgestzt wurde.
Weiterhin sorgt das Nichtvorhandensein der ISR dazu, dass der Controller 
irgendwohin springt (Dummy-ISR?); zumindest erzeugt der GCC AFIAK solche 
Dummy-ISRs aus welchen Gründen auch immer.
Das Datenblatt deines Controllers beschreibt, wie man ADC-Interrupts 
behandelt...
#1338342
Lesenswert?

Hallo,

wenn Du den Interrupt für den ADC freigibst, muß es natürlich auch die 
passenden Interruptroutine geben, in dieser wird dann der ADC ausgelesen 
und entsprechend reagiert.
Außer wird automatisch das Interruptflag des ADC gelöscht.

Wenn Du per Polling abfragst, wie hier, dann darf der ADC-Interrupt 
natürlich nicht freigegeben werden, es wird einfach gewartet, bis der 
ADC das Bit ADSC im Register ADCSRA wieder auf 0 setzt, dann ist er 
fertig.

Darauf hat STK500-Besitzer (Gast) hingewiesen.

Gruß aus Berlin
Michael
Gast #1338352
Lesenswert?

>Ok, Quellcode: Es ist die Firmware von Salewski...

Wie soll das denn einer ahnen...
Mein Beispiel hat den ADC in der ISR ausgelesen, soweit ich mich 
erinnere. Wenn Du keine ISR verwendest, musst Du den ADC Code sicher 
irgendwie anpassen, wie die anderen oben schon schrieben.
Gast #1338397
Lesenswert?

>Autor: Markus Haege (mh1977)
>Datum: 17.07.2009 18:51

>Danke...

>das mit den ISR wußte ich nicht. Ich könnte dann auch eine
>while-Schleife schreiben, die wartet bis ADSC auf 0 ist...oder?

Ohne ISR ist einfacher. Ich kann Dir momentan dazu nicht viel sagen, da 
ich mich in den letzten 18 Monaten nicht mit der Firmware beschäftigt 
habe. Sollte aber nicht so schwierig sein. Ich würde zunächst mal 
versuchen ohne ISR irgendwelche Datensätze über USB zu schicken. Wenn 
das geht machst Du die ADC-Abfrage ohne ISR und schickst dessen Daten 
dann Über den USB-Port. ADC und USB haben ja nicht direkt etwas 
miteinander zu tun, das war ja nur ein Beispiel. Und zum ADC findest du 
genug, auch hier im Forum.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren